简单公开拍卖智能合约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

posted @ 2022-03-28 20:34  豆豆是只乖狗狗  阅读(319)  评论(0编辑  收藏  举报