diff options
author | chriseth <chris@ethereum.org> | 2017-05-03 20:36:32 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-03 20:36:32 +0800 |
commit | 68ef5810593e7c8092ed41d5f474dd43141624eb (patch) | |
tree | 36453acfef9495095dc47305d9b40c2cd3b63813 /docs/common-patterns.rst | |
parent | f0d539ae05739e35336cc9cc8f44bd9798a95c28 (diff) | |
parent | 34b28ed760e8ba9b86f661c819fe489fb8403235 (diff) | |
download | dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar.gz dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar.bz2 dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar.lz dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar.xz dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.tar.zst dexon-solidity-68ef5810593e7c8092ed41d5f474dd43141624eb.zip |
Merge pull request #2219 from ethereum/develop
Release for version 0.4.11
Diffstat (limited to 'docs/common-patterns.rst')
-rw-r--r-- | docs/common-patterns.rst | 55 |
1 files changed, 24 insertions, 31 deletions
diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index a2d7ce71..acef13b7 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -23,12 +23,12 @@ 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 +you will receive the funds of the person who has gone on to 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); @@ -232,7 +225,7 @@ reached at a certain point in **time**. An example for this is a blind auction contract which starts in the stage "accepting blinded bids", then transitions to "revealing bids" which is ended by -"determine auction autcome". +"determine auction outcome". .. index:: function;modifier @@ -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); _; } |