diff options
author | Denton Liu <liu.denton+github@gmail.com> | 2016-07-09 00:21:57 +0800 |
---|---|---|
committer | Denton Liu <liu.denton+github@gmail.com> | 2016-08-10 22:40:55 +0800 |
commit | efb48659dd61595e0841419543d919ca21d7854a (patch) | |
tree | e29cee390266842507ed7926eee1e8407d78ac79 | |
parent | e6a031d4e5cb643dca4a9dcee9cbb0ea5e7ef7ad (diff) | |
download | dexon-solidity-efb48659dd61595e0841419543d919ca21d7854a.tar.gz dexon-solidity-efb48659dd61595e0841419543d919ca21d7854a.tar.zst dexon-solidity-efb48659dd61595e0841419543d919ca21d7854a.zip |
Add section about withdrawal pattern
-rw-r--r-- | docs/common-patterns.rst | 74 | ||||
-rw-r--r-- | docs/security-considerations.rst | 2 | ||||
-rw-r--r-- | docs/solidity-by-example.rst | 2 |
3 files changed, 78 insertions, 0 deletions
diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index 422e2758..1a9083d9 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -2,6 +2,80 @@ Common Patterns ############### +.. index:: withdrawal + +************************* +Withdrawal from Contracts +************************* + +The recommended method of sending funds after an effect +is with the withdrawal pattern. Although the most intuitive +aethod of sending Ether as a result of an effect is a +direct ``send`` call, this is not recommended as it +introduces a potential security risk. You may read +more about this on the :ref:`security_considerations` page. + +This is an example of the withdrawal pattern in practice in +an Ether storage contract. + +:: + + contract WithdrawalPattern { + + mapping (address => uint) etherStore; + mapping (address => uint) pendingReturns; + + function sendEther(uint amount) { + if (amount < etherStore[msg.sender]) { + throw; + } + etherStore[msg.sender] -= amount; + pendingReturns[msg.sender] += amount; + } + + function withdraw() { + uint amount = pendingReturns[msg.sender]; + // It is important to zero the mapping entry + // before sending otherwise this could open + // the contract to a re-entrancy attack + pendingReturns[msg.sender] = 0; + if (!msg.sender.send(amount)) { + throw; + } + } + + function () { + etherStore[msg.sender] += msg.value; + } + } + +This is as opposed to the more intuitive sending pattern. + +:: + + contract SendPattern { + + mapping (address => uint) etherStore; + + function sendEther(uint amount) { + if (amount < etherStore[msg.sender]) { + throw; + } + etherStore[msg.sender] -= amount; + if (!msg.sender.send(amount)) { + throw; + } + } + + function () { + etherStore[msg.sender] += msg.value; + } + } + +An example of this pattern in a less contrived +application can be found on the :ref:`simple_auction` +example. + .. index:: access;restricting ****************** diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index bae6e20b..c5d20649 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -1,3 +1,5 @@ +.. _security_considerations: + ####################### Security Considerations ####################### diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst index 7dd51f00..e68ce448 100644 --- a/docs/solidity-by-example.rst +++ b/docs/solidity-by-example.rst @@ -191,6 +191,8 @@ contract into a blind auction where it is not possible to see the actual bid until the bidding period ends. +.. _simple_auction: + Simple Open Auction =================== |