aboutsummaryrefslogtreecommitdiffstats
path: root/docs/common-patterns.rst
diff options
context:
space:
mode:
authorDenton Liu <liu.denton+github@gmail.com>2016-07-09 00:21:57 +0800
committerDenton Liu <liu.denton+github@gmail.com>2016-08-10 22:40:55 +0800
commitefb48659dd61595e0841419543d919ca21d7854a (patch)
treee29cee390266842507ed7926eee1e8407d78ac79 /docs/common-patterns.rst
parente6a031d4e5cb643dca4a9dcee9cbb0ea5e7ef7ad (diff)
downloaddexon-solidity-efb48659dd61595e0841419543d919ca21d7854a.tar.gz
dexon-solidity-efb48659dd61595e0841419543d919ca21d7854a.tar.zst
dexon-solidity-efb48659dd61595e0841419543d919ca21d7854a.zip
Add section about withdrawal pattern
Diffstat (limited to 'docs/common-patterns.rst')
-rw-r--r--docs/common-patterns.rst74
1 files changed, 74 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
******************