diff options
Diffstat (limited to 'docs/common-patterns.rst')
-rw-r--r-- | docs/common-patterns.rst | 51 |
1 files changed, 22 insertions, 29 deletions
diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index de2da690..acef13b7 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -28,7 +28,7 @@ become the new richest. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract WithdrawalContract { address public richest; @@ -52,17 +52,12 @@ become the new richest. } } - function withdraw() returns (bool) { + function withdraw() { 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; - } + msg.sender.transfer(amount); } } @@ -70,7 +65,7 @@ This is as opposed to the more intuitive sending pattern: :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract SendContract { address public richest; @@ -83,12 +78,8 @@ This is as opposed to the more intuitive sending pattern: function becomeRichest() payable 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; - } + // This line can cause problems (explained below). + richest.transfer(msg.value); richest = msg.sender; mostSent = msg.value; return true; @@ -100,12 +91,16 @@ This is as opposed to the more intuitive sending pattern: 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. +the address of a contract that has a fallback function +which fails (e.g. by using ``revert()`` or by just +conssuming more than the 2300 gas stipend). That way, +whenever ``transfer`` is called to deliver funds to the +"poisoned" contract, it will fail and thus also ``becomeRichest`` +will fail, with the contract being stuck forever. + +In contrast, if you use the "withdraw" pattern from the first example, +the attacker can only cause his or her own withdraw to fail and not the +rest of the contract's workings. .. index:: access;restricting @@ -135,7 +130,7 @@ restrictions highly readable. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract AccessRestriction { // These will be assigned at the construction @@ -152,8 +147,7 @@ restrictions highly readable. // a certain address. modifier onlyBy(address _account) { - if (msg.sender != _account) - throw; + require(msg.sender == _account); // Do not forget the "_;"! It will // be replaced by the actual function // body when the modifier is used. @@ -169,7 +163,7 @@ restrictions highly readable. } modifier onlyAfter(uint _time) { - if (now < _time) throw; + require(now >= _time); _; } @@ -190,8 +184,7 @@ restrictions highly readable. // This was dangerous before Solidity version 0.4.0, // where it was possible to skip the part after `_;`. modifier costs(uint _amount) { - if (msg.value < _amount) - throw; + require(msg.value >= _amount); _; if (msg.value > _amount) msg.sender.send(msg.value - _amount); @@ -276,7 +269,7 @@ function finishes. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract StateMachine { enum Stages { @@ -293,7 +286,7 @@ function finishes. uint public creationTime = now; modifier atStage(Stages _stage) { - if (stage != _stage) throw; + require(stage == _stage); _; } |