Solidity - รูปแบบการถอน

รูปแบบการถอนทำให้มั่นใจได้ว่าจะไม่มีการโอนสายโดยตรงซึ่งก่อให้เกิดภัยคุกคามด้านความปลอดภัย สัญญาต่อไปนี้แสดงการใช้การโอนสายเพื่อส่งอีเธอร์ที่ไม่ปลอดภัย

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) {
         // Insecure practice
         richest.transfer(msg.value);
         richest = msg.sender;
         mostSent = msg.value;
         return true;
      } else {
         return false;
      }
   }
}

สัญญาข้างต้นสามารถแสดงผลในสถานะใช้ไม่ได้โดยทำให้คนรวยที่สุดเป็นสัญญาของฟังก์ชันทางเลือกที่ล้มเหลว เมื่อฟังก์ชันทางเลือกล้มเหลวฟังก์ชัน becomeRichest () จะล้มเหลวและสัญญาจะค้างตลอดไป เพื่อลดปัญหานี้เราสามารถใช้รูปแบบการถอน

ในรูปแบบการถอนเราจะรีเซ็ตจำนวนเงินที่รอดำเนินการก่อนการโอนแต่ละครั้ง จะทำให้มั่นใจได้ว่าสัญญาเฉพาะผู้โทรล้มเหลว

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);
   }
}