简单公开拍卖智能合约solidity代码
简单公开拍卖基本思想:在竞价期间每个节点都可以调用function bid()参与竞价,若最高出价被抬高,之前的最高出价节点可以调用function withdraw()拿回竞价金额,最终调用function auctionEnd()获取竞价结果。
pragma solidity ^0.8.4; //简单的公开拍卖 contract SimpleAuction{ address payable public beneficiary;//竞价受益者 uint public auctionEndTime;//竞价最后时间期限 address public highestBidder;//最高竞价者地址 uint public highestBid;//最高竞价 mapping(address => uint) pendingReturns;//记录所有最高竞价者地址和其竞价 bool ended;//标记竞价状态,默认值为false //调用event可以将合约中某些内容的更改记录到日志,用关键字emit修饰调用 //事件(event)和日志不能在合约内部访问,可以被子合约调用 event HighestBidIncreased(address bidder,uint amount); event AuctionEnded(address winner,uint amount); error AuctionAlreadyEnded();//标识该竞价周期已结束 error BidNotHighEnough(uint highestBid);//标识已存在更高的竞价 error AuctionNotYetEnded();//标识当前竞价周期还未结束 error AuctionEndAlreadyCalled();//标识该竞价周期状态ended已更改 //构造函数,部署合约时调用,仅调用一次,初始化竞价受益者地址和竞价周期 //当前版本的address分为:address 和 payable address //payable address支持.transfer和.send方法,用于发送ether //payable address只能给payable address转账,而不能给address转账 constructor(uint biddingTime,address payable beneficiaryAddress) public{ beneficiary = beneficiaryAddress; auctionEndTime = block.timestamp +biddingTime; } //竞价,只有payable修饰的function才能接收以太币 function bid() external payable{ //若竞拍周期结束则退出function,回退当前调用所有改变 if(block.timestamp > auctionEndTime) revert AuctionAlreadyEnded(); //若当前竞价金额并非最高则退出function,回退当前调用所有改变 if(msg.value <= highestBid) revert BidNotHighEnough(highestBid); //添加最高竞价信息到一维数组pendingReturns中 if(highestBid != 0) pendingReturns[highestBidder] += highestBid; highestBidder = msg.sender;//更新最高竞价者地址 highestBid = msg.value;//更新最高竞价 emit HighestBidIncreased(msg.sender, msg.value);//调用HighestBidIncreased事件更新最新竞价信息 } //退回调用者的竞价金额,注:msg.sender指调用该函数的地址,而不是调用整个合约的地址 function withdraw() external returns(bool){ uint amount = pendingReturns[msg.sender];//取出调用该function竞价地址的竞价金额 if(amount>0){ pendingReturns[msg.sender] = 0;//将pendingReturns中对应竞价者的竞价金额置为0 //向调用该function的竞价地址返还竞价金额,若返还竞价金额失败则恢复pendingReturns状态 //将msg.sender由address类型强制转换为payable address类型 if(!payable(msg.sender).send(amount)){ pendingReturns[msg.sender] = amount; return false;//return false表明退钱失败 } } return true;//return false表明退钱成功 } //修改竞价状态,发钱给竞价受益者 function auctionEnd() external{ //下述if类似于:require(block.timestamp >= auctionEndTime,"Auction not yet ended."); //require抛出异常回退状态并返回字符串,revert error()抛出异常回退状态并返回error数据 if(block.timestamp < auctionEndTime) revert AuctionAlreadyEnded();//竞价周期结束,退出该function,回退状态 //下述if类似于:require(!ended,"auctionEnd has already been called."); if(ended) revert AuctionEndAlreadyCalled();//竞价状态已改变,退出该function,回退状态 ended = true;//修改竞价状态 emit AuctionEnded(highestBidder,highestBid);//调用AuctionEnded事件记录最终最高竞价信息 beneficiary.transfer(highestBid);//给竞价受益者发送最终竞价金额 } }
来源(solidity官方文档):https://docs.soliditylang.org/en/v0.8.13/solidity-by-example.html#simple-open-auction