From 2b4b86aa7f72d8f7c2c4e250953d8f9018f4fd53 Mon Sep 17 00:00:00 2001 From: Matt Wisniewski Date: Wed, 19 Apr 2017 14:12:45 -0400 Subject: Update common-patterns.rst --- docs/common-patterns.rst | 22 ++++---- docs/contracts.rst | 19 +++---- docs/frequently-asked-questions.rst | 3 +- docs/security-considerations.rst | 11 ++-- docs/solidity-by-example.rst | 104 +++++++++++++++--------------------- docs/structure-of-a-contract.rst | 4 +- docs/types.rst | 9 ++-- 7 files changed, 73 insertions(+), 99 deletions(-) (limited to 'docs') diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index de2da690..37973c62 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; @@ -70,7 +70,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; @@ -86,9 +86,7 @@ This is as opposed to the more intuitive sending pattern: // 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.transfer(msg.value); richest = msg.sender; mostSent = msg.value; return true; @@ -135,7 +133,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 +150,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 +166,7 @@ restrictions highly readable. } modifier onlyAfter(uint _time) { - if (now < _time) throw; + require(now >= _time); _; } @@ -190,8 +187,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 +272,7 @@ function finishes. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract StateMachine { enum Stages { @@ -293,7 +289,7 @@ function finishes. uint public creationTime = now; modifier atStage(Stages _stage) { - if (stage != _stage) throw; + require(stage == _stage); _; } diff --git a/docs/contracts.rst b/docs/contracts.rst index 26c0c886..a26d5a5e 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -327,7 +327,7 @@ inheritable properties of contracts and may be overridden by derived contracts. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract owned { function owned() { owner = msg.sender; } @@ -341,8 +341,7 @@ inheritable properties of contracts and may be overridden by derived contracts. // function is executed and otherwise, an exception is // thrown. modifier onlyOwner { - if (msg.sender != owner) - throw; + require(msg.sender == owner); _; } } @@ -390,7 +389,7 @@ inheritable properties of contracts and may be overridden by derived contracts. contract Mutex { bool locked; modifier noReentrancy() { - if (locked) throw; + require(!locked); locked = true; _; locked = false; @@ -401,7 +400,7 @@ inheritable properties of contracts and may be overridden by derived contracts. /// The `return 7` statement assigns 7 to the return value but still /// executes the statement `locked = false` in the modifier. function f() noReentrancy returns (uint) { - if (!msg.sender.call()) throw; + require(msg.sender.call()); return 7; } } @@ -989,7 +988,7 @@ more advanced example to implement a set). :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; library Set { // We define a new struct datatype that will be used to @@ -1035,8 +1034,7 @@ more advanced example to implement a set). // The library functions can be called without a // specific instance of the library, since the // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - throw; + assert(Set.insert(knownValues, value)); } // In this contract, we can also directly access knownValues.flags, if we want. } @@ -1166,7 +1164,7 @@ available without having to add further code. Let us rewrite the set example from the :ref:`libraries` in this way:: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; // This is the same code as before, just without comments library Set { @@ -1207,8 +1205,7 @@ Let us rewrite the set example from the // corresponding member functions. // The following function call is identical to // Set.insert(knownValues, value) - if (!knownValues.insert(value)) - throw; + require(knownValues.insert(value)); } } diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 639eb83e..029e32eb 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -665,8 +665,7 @@ What does the following strange check do in the Custom Token contract? :: - if (balanceOf[_to] + _value < balanceOf[_to]) - throw; + require(balanceOf[_to] + _value >= balanceOf[_to]); Integers in Solidity (and most other machine-related programming languages) are restricted to a certain range. For ``uint256``, this is ``0`` up to ``2**256 - 1``. If the result of some operation on those numbers diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 1e92afa7..f9ceed5d 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -79,7 +79,7 @@ outlined further below: :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract Fund { /// Mapping of ether shares of the contract. @@ -88,8 +88,7 @@ outlined further below: function withdraw() { var share = shares[msg.sender]; shares[msg.sender] = 0; - if (!msg.sender.send(share)) - throw; + require(msg.sender.send(share)); } } @@ -162,7 +161,7 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; // THIS CONTRACT CONTAINS A BUG - DO NOT USE contract TxUserWallet { @@ -173,8 +172,8 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like } function transfer(address dest, uint amount) { - if (tx.origin != owner) { throw; } - if (!dest.call.value(amount)()) throw; + require(tx.origin == owner); + require(dest.call.value(amount)()); } } diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst index 3d6221e4..a8e7eb2c 100644 --- a/docs/solidity-by-example.rst +++ b/docs/solidity-by-example.rst @@ -36,7 +36,7 @@ of votes. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; /// @title Voting with delegation. contract Ballot { @@ -87,14 +87,12 @@ of votes. // Give `voter` the right to vote on this ballot. // May only be called by `chairperson`. function giveRightToVote(address voter) { - if (msg.sender != chairperson || voters[voter].voted) { - // `throw` terminates and reverts all changes to - // the state and to Ether balances. It is often - // a good idea to use this if functions are - // called incorrectly. But watch out, this - // will also consume all provided gas. - throw; - } + // `throw` terminates and reverts all changes to + // the state and to Ether balances. It is often + // a good idea to use this if functions are + // called incorrectly. But watch out, this + // will also consume all provided gas. + require(msg.sender == chairperson || !voters[voter].voted); voters[voter].weight = 1; } @@ -102,12 +100,10 @@ of votes. function delegate(address to) { // assigns reference Voter sender = voters[msg.sender]; - if (sender.voted) - throw; + require(!sender.voted); // Self-delegation is not allowed. - if (to == msg.sender) - throw; + require(to != msg.sender); // Forward the delegation as long as // `to` also delegated. @@ -121,8 +117,7 @@ of votes. to = voters[to].delegate; // We found a loop in the delegation, not allowed. - if (to == msg.sender) - throw; + require(to != msg.sender); } // Since `sender` is a reference, this @@ -145,8 +140,7 @@ of votes. /// to proposal `proposals[proposal].name`. function vote(uint proposal) { Voter sender = voters[msg.sender]; - if (sender.voted) - throw; + require(!sender.voted); sender.voted = true; sender.vote = proposal; @@ -218,7 +212,7 @@ activate themselves. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract SimpleAuction { // Parameters of the auction. Times are either @@ -269,16 +263,16 @@ activate themselves. // the transaction. The keyword payable // is required for the function to // be able to receive Ether. - if (now > auctionStart + biddingTime) { - // Revert the call if the bidding - // period is over. - throw; - } - if (msg.value <= highestBid) { - // If the bid is not higher, send the - // money back. - throw; - } + + // Revert the call if the bidding + // period is over. + require(now < auctionStart + biddingTime); + + + // If the bid is not higher, send the + // money back. + require(msg.value <= highestBid); + if (highestBidder != 0) { // Sending back the money by simply using // highestBidder.send(highestBid) is a security risk @@ -327,18 +321,15 @@ activate themselves. // external contracts. // 1. Conditions - if (now <= auctionStart + biddingTime) - throw; // auction did not yet end - if (ended) - throw; // this function has already been called + require(now >= auctionStart + biddingTime); // auction did not yet end + require(!ended); // this function has already been called // 2. Effects ended = true; AuctionEnded(highestBidder, highestBid); // 3. Interaction - if (!beneficiary.send(highestBid)) - throw; + require(beneficiary.transfer(highestBid)); } } @@ -381,7 +372,7 @@ high or low invalid bids. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract BlindAuction { struct Bid { @@ -409,8 +400,8 @@ high or low invalid bids. /// functions. `onlyBefore` is applied to `bid` below: /// The new function body is the modifier's body where /// `_` is replaced by the old function body. - modifier onlyBefore(uint _time) { if (now >= _time) throw; _; } - modifier onlyAfter(uint _time) { if (now <= _time) throw; _; } + modifier onlyBefore(uint _time) { require(!now >= _time); _; } + modifier onlyAfter(uint _time) { require(!now <= _time); _; } function BlindAuction( uint _biddingTime, @@ -454,13 +445,11 @@ high or low invalid bids. onlyBefore(revealEnd) { uint length = bids[msg.sender].length; - if ( - _values.length != length || - _fake.length != length || - _secret.length != length - ) { - throw; - } + require( + _values.length == length || + _fake.length == length || + _secret.length == length + ); uint refund; for (uint i = 0; i < length; i++) { @@ -481,8 +470,7 @@ high or low invalid bids. // the same deposit. bid.blindedBid = 0; } - if (!msg.sender.send(refund)) - throw; + msg.sender.transfer(refund); } // This is an "internal" function which means that it @@ -527,14 +515,12 @@ high or low invalid bids. function auctionEnd() onlyAfter(revealEnd) { - if (ended) - throw; + require(!ended); AuctionEnded(highestBidder, highestBid); ended = true; // We send all the money we have, because some // of the refunds might have failed. - if (!beneficiary.send(this.balance)) - throw; + beneficiary.transfer(this.balance); } } @@ -546,7 +532,7 @@ Safe Remote Purchase :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract Purchase { uint public value; @@ -558,26 +544,26 @@ Safe Remote Purchase function Purchase() payable { seller = msg.sender; value = msg.value / 2; - if (2 * value != msg.value) throw; + require(!2 * value != msg.value); } modifier require(bool _condition) { - if (!_condition) throw; + require(_condition); _; } modifier onlyBuyer() { - if (msg.sender != buyer) throw; + require(msg.sender == buyer); _; } modifier onlySeller() { - if (msg.sender != seller) throw; + require(msg.sender == seller); _; } modifier inState(State _state) { - if (state != _state) throw; + require(state == _state); _; } @@ -594,8 +580,7 @@ Safe Remote Purchase { aborted(); state = State.Inactive; - if (!seller.send(this.balance)) - throw; + seller.transfer(this.balance); } /// Confirm the purchase as buyer. @@ -625,8 +610,7 @@ Safe Remote Purchase state = State.Inactive; // This actually allows both the buyer and the seller to // block the refund. - if (!buyer.send(value) || !seller.send(this.balance)) - throw; + require(buyer.transfer(value) || seller.transfer(this.balance)); } } diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index 24ef69a6..224eb368 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -62,13 +62,13 @@ Function modifiers can be used to amend the semantics of functions in a declarat :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract Purchase { address public seller; modifier onlySeller() { // Modifier - if (msg.sender != seller) throw; + require(msg.sender == seller); _; } diff --git a/docs/types.rst b/docs/types.rst index c868adc6..c400aecb 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -420,7 +420,7 @@ Example that shows how to use internal function types:: Another example that uses external function types:: - pragma solidity ^0.4.5; + pragma solidity ^0.4.11; contract Oracle { struct Request { @@ -445,7 +445,7 @@ Another example that uses external function types:: oracle.query("USD", this.oracleResponse); } function oracleResponse(bytes response) { - if (msg.sender != address(oracle)) throw; + require(msg.sender == address(oracle)); // Use the data } } @@ -722,7 +722,7 @@ shown in the following example: :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract CrowdFunding { // Defines a new type with two fields. @@ -763,8 +763,7 @@ shown in the following example: return false; uint amount = c.amount; c.amount = 0; - if (!c.beneficiary.send(amount)) - throw; + c.beneficiary.transfer(amount); return true; } } -- cgit v1.2.3