Solidity教程

Solidity 提款(Withdrawal)模式

当在智能合约中,直接向一个地址转账时,如该地址是一个合约地址,合约中可以编写代码,拒绝接受付款,导致交易失败。为避免这种情况,通常会使用提款模式。
提款模式是让收款方主动来提取款项,而不是直接转账给收款方。
示例
直接转账给收款方。
这是个比富游戏,智能合约接收用户发送的款项(以太),金额最高的将获得首富头衔,前一位首富失去头衔,但将获得金钱补偿,当前首富发送的款项,将转账给前首富(示例中此处使用直接转账)。
不理解游戏没关系,重点是转账给前首富时,是直接转账。
pragma solidity ^0.5.0;
contract Test {
   address payable public richest;
   uint public mostSent;
   constructor() public payable {
      richest = msg.sender;
      mostSent = msg.value;
   }
   function becomeRichest() public payable returns (bool) {
      if (msg.value > mostSent) {
         // 转账给前首富,不安全方法,对方可以拒绝收款,导致交易失败,从而导致当前智能合约失败,游戏不能继续
         richest.transfer(msg.value);
         richest = msg.sender;
         mostSent = msg.value;
         return true;
      } else {
         return false;
      }
   }
}
示例
提款模式,让收款方(前首富)主动来提取款项,交易不会失败,游戏可以继续。
pragma solidity ^0.5.0;
contract Test {
   address public richest;
   uint public mostSent;
   mapping (address => uint) pendingWithdrawals;
   constructor() public payable {
      richest = msg.sender;
      mostSent = msg.value;
   }
   function becomeRichest() public payable returns (bool) {
      if (msg.value > mostSent) {
         // 此处不直接转账,暂时记录应付款项
         pendingWithdrawals[richest] += msg.value;
         richest = msg.sender;
         mostSent = msg.value;
         return true;
      } else {
         return false;
      }
   }
   // 收款方调用这个函数,主动提取款项
   function withdraw() public {
      uint amount = pendingWithdrawals[msg.sender];
      pendingWithdrawals[msg.sender] = 0;
      msg.sender.transfer(amount);
   }
}
昵称: 邮箱:
Copyright © 2022 立地货 All Rights Reserved.
备案号:京ICP备14037608号-4