견고성-철수 패턴

인출 패턴은 보안 위협이되는 직접 호 전환이 이루어지지 않도록합니다. 다음 계약은 이더를 보내기 위해 전송 호출의 안전하지 않은 사용을 보여줍니다.

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