前言
编译环境:Remix.
代码来源:SolidityDoc.
疑难解决来源:Ethereum gitter.
例子三参考:例图.
以太币单位换算:以太币单位.
本文主要由三个例子构成。分别是Simple Open Auction 以及延伸版本Blind Auction 、此外还有一个涉及到状态机类型的合同为Safe Remote Purchase。
该例子在基于(一)之上引入了相关语法,接下来我会尽力以自己的理解结合网上的资料进行分析解释,从而帮助我更好地理解相关语法的知识点。
本次例子中引入了msg.value变量以及payable变量,重点在于强调value这个价值。只有当地址中包含payable变量的时候,才能引入value这个功能。因此,我们正常输入函数需要在value中设置相应的以太币,如:
一、Simple Open Auction代码分析
a、初始化相应变量
address payable public beneficiary;//引入受益人地址[注1]
uint public auctionEndTime;//定义拍卖停止时间
address public highestBidder;//提出最高价格的竞标人地址
uint public highestBid;//竞标最高价格
mapping (address => uint) pendingReturns;//将每个地址隐射一个退还金额的变量
bool ended;//判断竞标是否结束的变量
event HighestBidIncreased(address bidder, uint amount);//最高竞价增加的log事件(涉及地址以及数量信息)
event AuctionEnded(address winner, uint amount);//竞标成功的地址和数量信息的的log事件
[注1]:address payable
首先,我们得明确address和address payable的差别。
address指的是一个20字节的值,也就是以太坊账户地址。
address payable除了代表以太坊账户地址,还额外具备transfer和send函数的功能。
常见用法会在接下来函数具体应用中说明,并且会在该例子结束后具体对比说明。
b、构造函数
constructor(
uint _biddingTime,//定义一个时间间隔
address payable _beneficiary)//定义受益人地址
{
beneficiary = _beneficiary;//赋值到全局变量
auctionEndTime = block.timestamp + _biddingTime;//[注2]
}
[注2]:这里定义一个整数型变量_biddingTime,实际上可以理解为定义一个时间间隔。比如赋值600 也就等价于600秒。
block.timestamp是获取当前时间,该值主要指的是获取当前时间。
PS:当然有些小伙伴会发现这个solidity7.0版本之前是使用now来代替,在solidity7.0语法升级以后,统一使用block.timestamp来获取当前时间,具体更新改动可以通过阅读Solidity v0.7.0 Breaking Changes 来进一步了解其他方面的变动,当然这里只是扩展一下。
c、竞标函数
function bid() public payable{
require(
block.timestamp <= auctionEndTime,
"Auction already ended."
);//判断是否处于竞标期间
require(
msg.value > highestBid,
"There already is a higher bid"
);//判断竞标金额是否大于最高竞标金额
if (highestBid != 0){
pendingReturns[highestBidder] += highestBid;
}//[注3]
highestBidder = msg.sender;//赋值竞标价格最高者地址
highestBid = msg.value;//赋值竞标价格
emit HighestBidIncreased(msg.sender, msg.value);
//声明log日志用于显示竞标最高者地址以及价格
}
[注3]由于当前竞标价格为最高价格,因此过往的价格都返还到原有地址的返还数组:pendingReturn[highestBidder] 里面。因此,可以调用d中函数把返还数组里面的以太币返还到指定账户。
d、返还竞标金额函数
function withdraw() public returns (bool) {
uint amount = pendingReturns[msg.sender];//定义一个整型变量amount存储返回数组的具体金额
if(amount > 0){
pendingReturns[msg.sender] = 0;//若amount>0,则清空返回数组的数据
if(!msg.sender.send(amount))//[注4]{
pendingReturns[msg.sender] = amount;
return false;
}
}
return true;
}
[注4]通过判断amount是否为0,若不为0则把pendingReturns[msg.sender] = 0; 同时这里运用了msg.sender.send(amount) 函数。也就是前文提到的address payable的特性。
这里先介绍一下send函数的用法以及原理:
msg.sender.send(amount) 指的是将amount的金额发送到msg.sender的账户上。send除了传递金额以后还会发出一个bool型的返回值。
若成功执行则返回的是true,因此该if条件不满足可以直接return true。
若