Solidity 简单拍卖案例

参考

https://solidity.readthedocs.io/en/latest/solidity-by-example.html
https://ethfans.org/wikis/Solidity-%E6%96%87%E6%A1%A3--%E7%AC%AC%E4%B8%89%E7%AB%A0

简单拍卖

一个所有人都能看到出价的公开拍卖开始。highestBid和auctionEndTime都是public的,大家都可以查询。

简单的公开拍卖

  • 通常简单的公开拍卖合约,是每个人可以在拍卖期间发送他们的竞拍出价
  • 为了实现绑定竞拍人的到他们的拍卖,竞拍包括发送金额/ether。如果产生了新的最高竞拍价,前一个最高价竞拍人将会拿回他的钱
  • 在竞拍阶段结束后,受益人人需要手动调用合约收取他的钱 — — 合约不会激活自己

角色: 竞拍者,竞拍主持人,受益人。 竞拍主持人必须具有一定的公信力,否则转账到了主持人账户,主持人可以在竞拍结束前把资金卷跑,导致退款失败。

  1. 竞拍者往竞拍主持人账户发起转账 Eth,如果竞拍不成功,则直接抛出异常,转账失败。
  2. 如果竞拍成功,则竞拍者资金暂时保存在 竞拍主持人账户里。
  3. 如果有新的更高的出价者,那么老的得主,可以从竞拍主持人账户里面 提取自己的保证金
  4. 投标结束后,拍卖主持人调用auctionEnd()函数,把拍卖成交价转账给 受益人
pragma solidity >=0.4.22 <0.6.0;

contract SimpleAuction {
    // Parameters of the auction. Times are either
    address payable public beneficiary;
    
    // 拍卖持续的时间,now +auctionEndTime =拍卖截止时间
    uint public auctionEndTime;

    // Current state of the auction.
    address public highestBidder;
    uint public highestBid;

    //Allowed withdrawals of previous bids
    
    //给之前的最高出价者退钱,不是直接退,而是存在pendingReturns里面,由 竞拍的人主动取,只要你现在不是得主,就可以取钱了
    mapping(address => uint) pendingReturns;

    // Set to true at the end, disallows any change.By default initialized to `false`.
    //投票结束 收款的时候会触发一次收款,然后 ended设置为true
    bool ended;

    // Events that will be emitted on changes.
    event HighestBidIncreased(address bidder, uint amount);
    event AuctionEnded(address winner, uint amount);

    // The following is a so-called natspec comment,
    // recognizable by the three slashes.
    // It will be shown when the user is asked to
    // confirm a transaction.

    /// Create a simple auction with `_biddingTime`
    /// seconds bidding time on behalf of the
    /// beneficiary address `_beneficiary`.
    constructor(uint _biddingTime,address payable _beneficiary) public {
        beneficiary = _beneficiary;
        auctionEndTime = now + _biddingTime;
    }

    /// Bid on the auction with the value sent together with this transaction.(竞拍价就是 该笔交易的转账金额)
    /// The value will only be refunded if the auction is not won.
    function bid() public payable {
        // No arguments are necessary, all information is already part of the transaction. 
        //The keyword payable is required for the function to be able to receive Ether.
        // Revert the call if the bidding period is over.
        require(
            now <= auctionEndTime,
            "Auction already ended."
        );

        // If the bid is not higher, send the money back.
        //msg.value (uint): 和消息一起发送的wei的数量
        require(
            msg.value > highestBid,
            "There already is a higher bid."
        );
        
        //给之前的最高出价者退钱,不是直接退,而是存在pendingReturns里面,由 竞拍的人主动取
        if (highestBid != 0) {
            // Sending back the money by simply using highestBidder.send(highestBid) is a security risk
            // because it could execute an untrusted contract.
            // It is always safer to let the recipients withdraw their money themselves.
            pendingReturns[highestBidder] += highestBid;
        }

        highestBidder = msg.sender;
        highestBid = msg.value;
        //通知最新的得主
        emit HighestBidIncreased(msg.sender, msg.value);
    }


    
    //流标的竞标者可以随时取回自己的保证金
    function withdraw() public returns (bool) {
        uint amount = pendingReturns[msg.sender];
        if (amount > 0) {
            // It is important to set this to zero because the recipient
            // can call this function again as part of the receiving call
            // before `send` returns.
            pendingReturns[msg.sender] = 0;
            //发起退款,如果退款失败,就重置可退款信息
            if (!msg.sender.send(amount)) {
                // No need to call throw here, just reset the amount owing
                pendingReturns[msg.sender] = amount;
                return false;
            }
        }
        return true;
    }

    /// End the auction and send the highest bid to the beneficiary.
    //这个交易必须由拍卖主持人调用,因为会触发扣款啊。竞拍人往 竞拍主持人账户转账 发起竞拍,最终竞拍结束,竞拍主持人把 最终竞拍成交价 转账给 收款人
    function auctionEnd() public {
        // 1. Conditions
        require(now >= auctionEndTime, "Auction not yet ended.");
        require(!ended, "auctionEnd has already been called.");

        // 2. Effects
        ended = true;
        emit AuctionEnded(highestBidder, highestBid);

        // 3. Interaction
        beneficiary.transfer(highestBid);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_33698043/article/details/86795343