Merge pull request #2207 from ethereum/wski-develop

chore(Docs): Replaced instances if - throw to require() where applicable.
This commit is contained in:
chriseth 2017-05-03 12:28:16 +02:00 committed by GitHub
commit 4af0451d16
7 changed files with 102 additions and 127 deletions

View File

@ -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);
_;
}

View File

@ -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;
require(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));
}
}

View File

@ -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

View File

@ -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;
msg.sender.transfer(share);
}
}
@ -124,22 +123,24 @@ Sending and Receiving Ether
(for example in the "details" section in Remix).
- There is a way to forward more gas to the receiving contract using
``addr.call.value(x)()``. This is essentially the same as ``addr.send(x)``,
``addr.call.value(x)()``. This is essentially the same as ``addr.transfer(x)``,
only that it forwards all remaining gas and opens up the ability for the
recipient to perform more expensive actions. This might include calling back
recipient to perform more expensive actions (and it only returns a failure code
and does not automatically propagate the error). This might include calling back
into the sending contract or other state changes you might not have thought of.
So it allows for great flexibility for honest users but also for malicious actors.
- If you want to send Ether using ``address.send``, there are certain details to be aware of:
- If you want to send Ether using ``address.transfer``, there are certain details to be aware of:
1. If the recipient is a contract, it causes its fallback function to be executed which can, in turn, call back the sending contract.
2. Sending Ether can fail due to the call depth going above 1024. Since the caller is in total control of the call
depth, they can force the transfer to fail; make sure to always check the return value of ``send``. Better yet,
depth, they can force the transfer to fail; take this possibility into account or use ``send`` and make sure to always check its return value. Better yet,
write your contract using a pattern where the recipient can withdraw Ether instead.
3. Sending Ether can also fail because the execution of the recipient contract
requires more than the allotted amount of gas (explicitly by using ``throw`` or
requires more than the allotted amount of gas (explicitly by using ``require``,
``assert``, ``revert``, ``throw`` or
because the operation is just too expensive) - it "runs out of gas" (OOG).
If the return value of ``send`` is checked, this might provide a
If you use ``transfer`` or ``send`` with a return value check, this might provide a
means for the recipient to block progress in the sending contract. Again, the best practice here is to use
a :ref:`"withdraw" pattern instead of a "send" pattern <withdrawal_pattern>`.
@ -162,7 +163,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 {
@ -172,9 +173,9 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like
owner = msg.sender;
}
function transfer(address dest, uint amount) {
if (tx.origin != owner) { throw; }
if (!dest.call.value(amount)()) throw;
function transferTo(address dest, uint amount) {
require(tx.origin == owner);
dest.transfer(amount);
}
}
@ -192,7 +193,7 @@ Now someone tricks you into sending ether to the address of this attack wallet:
}
function() {
TxUserWallet(msg.sender).transfer(owner, msg.sender.balance);
TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance);
}
}

View File

@ -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,14 @@ 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;
}
// If the argument of `require` evaluates to `false`,
// it 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 currently also consume all provided gas
// (this is planned to change in the future).
require((msg.sender == chairperson) && !voters[voter].voted);
voters[voter].weight = 1;
}
@ -102,12 +102,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 +119,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 +142,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 +214,7 @@ activate themselves.
::
pragma solidity ^0.4.0;
pragma solidity ^0.4.11;
contract SimpleAuction {
// Parameters of the auction. Times are either
@ -269,16 +265,15 @@ 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 +322,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;
beneficiary.transfer(highestBid);
}
}
@ -381,7 +373,7 @@ high or low invalid bids.
::
pragma solidity ^0.4.0;
pragma solidity ^0.4.11;
contract BlindAuction {
struct Bid {
@ -409,8 +401,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 +446,9 @@ 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);
require(_fake.length == length);
require(_secret.length == length);
uint refund;
for (uint i = 0; i < length; i++) {
@ -481,8 +469,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 +514,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 +531,7 @@ Safe Remote Purchase
::
pragma solidity ^0.4.0;
pragma solidity ^0.4.11;
contract Purchase {
uint public value;
@ -558,26 +543,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;
modifier condition(bool _condition) {
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 +579,7 @@ Safe Remote Purchase
{
aborted();
state = State.Inactive;
if (!seller.send(this.balance))
throw;
seller.transfer(this.balance);
}
/// Confirm the purchase as buyer.
@ -604,7 +588,7 @@ Safe Remote Purchase
/// is called.
function confirmPurchase()
inState(State.Created)
require(msg.value == 2 * value)
condition(msg.value == (2 * value))
payable
{
purchaseConfirmed();
@ -623,10 +607,12 @@ Safe Remote Purchase
// otherwise, the contracts called using `send` below
// can call in again here.
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;
// NOTE: This actually allows both the buyer and the seller to
// block the refund - the withdraw pattern should be used.
buyer.transfer(value);
seller.transfer(this.balance));
}
}

View File

@ -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);
_;
}

View File

@ -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;
}
}