1. 程式人生 > >Openzeppelin庫第九期:支付模式Push與Pull

Openzeppelin庫第九期:支付模式Push與Pull

支付的模式

  • 推送(push):合約主動維護
  • 拉取(pull):使用者主動呼叫
  • 例項:簡單競標說明
  • 只有一個功能:在競標過程中,當有更高的價格產生時,對出價最高競標者的資訊進行更新,合約把之前那一個的競價退回去。
pragma solidity ^0.4.18;

// 競標合約例項
// 1. 推送模式的支付
contract PushPayment{
    // 出價最高的人
    address highestBidder;
    // 競標價格
    uint highestBid;

    // 有出價更高的人出現,競標者資訊需要更新,如果原有的競標者在合約的回退函式中植入
    // 惡意程式碼使得send退款一直失敗,就會導致始終無法更新競標成功者的資訊,可能就可以
    // 使得自己以低價競標成功
    function() payable {
        throw;
    }

    // 競標函式
    function bid() {
        if(msg.value < highestBid) throw; // 如果出的價格小於當前最高價,丟擲
        if(highestBidder != 0) {
            if(!highestBidder.send(highestBid)) {
                throw;
            }
        }
        // 更換出價最高的競標者
        highestBidder = msg.sender;
        // 更換最高價格
        highestBid = msg.value;
    }
}
// 拉取模式
// 在出現出價更高的競標者之後,由使用者自己來呼叫退款函式
contract PullContract {
    address highestBidder; 
    uint highestBid;
    // 儲存每一個待退款的競標者的資訊
    mapping(address=>uint) refunds; 

    function bid() {
        if(msg.value < highestBid) throw;
        if (highestBidder != 0) {
            refunds[highestBidder] += msg.value;
        }
        highestBidder = msg.sender;
         // 更換最高價格
        highestBid = msg.value;
    }

    // 使用者自己呼叫,單獨處理退款,由於不是合約去進行維護,就算退款失敗也不會影響
    // 競標成功者的更換
    function withdrawBid() external {
        uint refund = refunds[msg.sender];
        refunds[msg.sender] = 0;
        if (!msg.sender.send(refund)) {
            refunds[msg.sender] = refund;
        }
    }
}