aboutsummaryrefslogtreecommitdiffstats
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
parente6a031d4e5cb643dca4a9dcee9cbb0ea5e7ef7ad (diff)
downloaddexon-solidity-efb48659dd61595e0841419543d919ca21d7854a.tar.gz
dexon-solidity-efb48659dd61595e0841419543d919ca21d7854a.tar.zst
dexon-solidity-efb48659dd61595e0841419543d919ca21d7854a.zip
Add section about withdrawal pattern
-rw-r--r--docs/common-patterns.rst74
-rw-r--r--docs/security-considerations.rst2
-rw-r--r--docs/solidity-by-example.rst2
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
===================