aboutsummaryrefslogtreecommitdiffstats
path: root/docs/common-patterns.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/common-patterns.rst')
-rw-r--r--docs/common-patterns.rst104
1 files changed, 104 insertions, 0 deletions
diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst
index 322be3ef..74f9c078 100644
--- a/docs/common-patterns.rst
+++ b/docs/common-patterns.rst
@@ -2,6 +2,110 @@
Common Patterns
###############
+.. index:: withdrawal
+
+.. _withdrawal_pattern:
+
+*************************
+Withdrawal from Contracts
+*************************
+
+The recommended method of sending funds after an effect
+is using the withdrawal pattern. Although the most intuitive
+method 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
+a contract where the goal is to send the most money to the
+contract in order to become the "richest", inspired by
+`King of the Ether <https://www.kingoftheether.com/>`_.
+
+In the following contract, if you are usurped as the richest,
+you will recieve the funds of the person who has gone on to
+become the new richest.
+
+::
+
+ contract WithdrawalContract {
+ address public richest;
+ uint public mostSent;
+
+ mapping (address => uint) pendingWithdrawals;
+
+ function WithdrawalContract() {
+ richest = msg.sender;
+ mostSent = msg.value;
+ }
+
+ function becomeRichest() returns (bool) {
+ if (msg.value > mostSent) {
+ pendingWithdrawals[richest] += msg.value;
+ richest = msg.sender;
+ mostSent = msg.value;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ function withdraw() returns (bool) {
+ uint amount = pendingWithdrawals[msg.sender];
+ // Remember to zero the pending refund before
+ // sending to prevent re-entrancy attacks
+ pendingWithdrawals[msg.sender] = 0;
+ if (msg.sender.send(amount)) {
+ return true;
+ }
+ else {
+ pendingWithdrawals[msg.sender] = amount;
+ return false;
+ }
+ }
+ }
+
+This is as opposed to the more intuitive sending pattern.
+
+::
+
+ contract SendContract {
+ address public richest;
+ uint public mostSent;
+
+ function SendContract() {
+ richest = msg.sender;
+ mostSent = msg.value;
+ }
+
+ function becomeRichest() returns (bool) {
+ if (msg.value > mostSent) {
+ // Check if call succeeds to prevent an attacker
+ // from trapping the previous person's funds in
+ // this contract through a callstack attack
+ if (!richest.send(msg.value)) {
+ throw;
+ }
+ richest = msg.sender;
+ mostSent = msg.value;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+
+Notice that, in this example, an attacker could trap the
+contract into an unusable state by causing ``richest`` to be
+the address of a contract that has a fallback function
+which consumes more than the 2300 gas stipend. That way,
+whenever ``send`` is called to deliver funds to the
+"poisoned" contract, it will cause execution to always fail
+because there will not be enough gas to finish the execution
+of the fallback function.
+
.. index:: access;restricting
******************