mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #2207 from ethereum/wski-develop
chore(Docs): Replaced instances if - throw to require() where applicable.
This commit is contained in:
commit
4af0451d16
@ -28,7 +28,7 @@ become the new richest.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
contract WithdrawalContract {
|
contract WithdrawalContract {
|
||||||
address public richest;
|
address public richest;
|
||||||
@ -52,17 +52,12 @@ become the new richest.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function withdraw() returns (bool) {
|
function withdraw() {
|
||||||
uint amount = pendingWithdrawals[msg.sender];
|
uint amount = pendingWithdrawals[msg.sender];
|
||||||
// Remember to zero the pending refund before
|
// Remember to zero the pending refund before
|
||||||
// sending to prevent re-entrancy attacks
|
// sending to prevent re-entrancy attacks
|
||||||
pendingWithdrawals[msg.sender] = 0;
|
pendingWithdrawals[msg.sender] = 0;
|
||||||
if (msg.sender.send(amount)) {
|
msg.sender.transfer(amount);
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
pendingWithdrawals[msg.sender] = amount;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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 {
|
contract SendContract {
|
||||||
address public richest;
|
address public richest;
|
||||||
@ -83,12 +78,8 @@ This is as opposed to the more intuitive sending pattern:
|
|||||||
|
|
||||||
function becomeRichest() payable returns (bool) {
|
function becomeRichest() payable returns (bool) {
|
||||||
if (msg.value > mostSent) {
|
if (msg.value > mostSent) {
|
||||||
// Check if call succeeds to prevent an attacker
|
// This line can cause problems (explained below).
|
||||||
// from trapping the previous person's funds in
|
richest.transfer(msg.value);
|
||||||
// this contract through a callstack attack
|
|
||||||
if (!richest.send(msg.value)) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
richest = msg.sender;
|
richest = msg.sender;
|
||||||
mostSent = msg.value;
|
mostSent = msg.value;
|
||||||
return true;
|
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
|
Notice that, in this example, an attacker could trap the
|
||||||
contract into an unusable state by causing ``richest`` to be
|
contract into an unusable state by causing ``richest`` to be
|
||||||
the address of a contract that has a fallback function
|
the address of a contract that has a fallback function
|
||||||
which consumes more than the 2300 gas stipend. That way,
|
which fails (e.g. by using ``revert()`` or by just
|
||||||
whenever ``send`` is called to deliver funds to the
|
conssuming more than the 2300 gas stipend). That way,
|
||||||
"poisoned" contract, it will cause execution to always fail
|
whenever ``transfer`` is called to deliver funds to the
|
||||||
because there will not be enough gas to finish the execution
|
"poisoned" contract, it will fail and thus also ``becomeRichest``
|
||||||
of the fallback function.
|
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
|
.. index:: access;restricting
|
||||||
|
|
||||||
@ -135,7 +130,7 @@ restrictions highly readable.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
contract AccessRestriction {
|
contract AccessRestriction {
|
||||||
// These will be assigned at the construction
|
// These will be assigned at the construction
|
||||||
@ -152,8 +147,7 @@ restrictions highly readable.
|
|||||||
// a certain address.
|
// a certain address.
|
||||||
modifier onlyBy(address _account)
|
modifier onlyBy(address _account)
|
||||||
{
|
{
|
||||||
if (msg.sender != _account)
|
require(msg.sender == _account);
|
||||||
throw;
|
|
||||||
// Do not forget the "_;"! It will
|
// Do not forget the "_;"! It will
|
||||||
// be replaced by the actual function
|
// be replaced by the actual function
|
||||||
// body when the modifier is used.
|
// body when the modifier is used.
|
||||||
@ -169,7 +163,7 @@ restrictions highly readable.
|
|||||||
}
|
}
|
||||||
|
|
||||||
modifier onlyAfter(uint _time) {
|
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,
|
// This was dangerous before Solidity version 0.4.0,
|
||||||
// where it was possible to skip the part after `_;`.
|
// where it was possible to skip the part after `_;`.
|
||||||
modifier costs(uint _amount) {
|
modifier costs(uint _amount) {
|
||||||
if (msg.value < _amount)
|
require(msg.value >= _amount);
|
||||||
throw;
|
|
||||||
_;
|
_;
|
||||||
if (msg.value > _amount)
|
if (msg.value > _amount)
|
||||||
msg.sender.send(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 {
|
contract StateMachine {
|
||||||
enum Stages {
|
enum Stages {
|
||||||
@ -293,7 +286,7 @@ function finishes.
|
|||||||
uint public creationTime = now;
|
uint public creationTime = now;
|
||||||
|
|
||||||
modifier atStage(Stages _stage) {
|
modifier atStage(Stages _stage) {
|
||||||
if (stage != _stage) throw;
|
require(stage == _stage);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
contract owned {
|
||||||
function owned() { owner = msg.sender; }
|
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
|
// function is executed and otherwise, an exception is
|
||||||
// thrown.
|
// thrown.
|
||||||
modifier onlyOwner {
|
modifier onlyOwner {
|
||||||
if (msg.sender != owner)
|
require(msg.sender == owner);
|
||||||
throw;
|
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -390,7 +389,7 @@ inheritable properties of contracts and may be overridden by derived contracts.
|
|||||||
contract Mutex {
|
contract Mutex {
|
||||||
bool locked;
|
bool locked;
|
||||||
modifier noReentrancy() {
|
modifier noReentrancy() {
|
||||||
if (locked) throw;
|
require(!locked);
|
||||||
locked = true;
|
locked = true;
|
||||||
_;
|
_;
|
||||||
locked = false;
|
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
|
/// The `return 7` statement assigns 7 to the return value but still
|
||||||
/// executes the statement `locked = false` in the modifier.
|
/// executes the statement `locked = false` in the modifier.
|
||||||
function f() noReentrancy returns (uint) {
|
function f() noReentrancy returns (uint) {
|
||||||
if (!msg.sender.call()) throw;
|
require(msg.sender.call());
|
||||||
return 7;
|
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 {
|
library Set {
|
||||||
// We define a new struct datatype that will be used to
|
// 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
|
// The library functions can be called without a
|
||||||
// specific instance of the library, since the
|
// specific instance of the library, since the
|
||||||
// "instance" will be the current contract.
|
// "instance" will be the current contract.
|
||||||
if (!Set.insert(knownValues, value))
|
require(Set.insert(knownValues, value));
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
// In this contract, we can also directly access knownValues.flags, if we want.
|
// 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
|
Let us rewrite the set example from the
|
||||||
:ref:`libraries` in this way::
|
: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
|
// This is the same code as before, just without comments
|
||||||
library Set {
|
library Set {
|
||||||
@ -1207,8 +1205,7 @@ Let us rewrite the set example from the
|
|||||||
// corresponding member functions.
|
// corresponding member functions.
|
||||||
// The following function call is identical to
|
// The following function call is identical to
|
||||||
// Set.insert(knownValues, value)
|
// Set.insert(knownValues, value)
|
||||||
if (!knownValues.insert(value))
|
require(knownValues.insert(value));
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -665,8 +665,7 @@ What does the following strange check do in the Custom Token contract?
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
if (balanceOf[_to] + _value < balanceOf[_to])
|
require((balanceOf[_to] + _value) >= balanceOf[_to]);
|
||||||
throw;
|
|
||||||
|
|
||||||
Integers in Solidity (and most other machine-related programming languages) are restricted to a certain range.
|
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
|
For ``uint256``, this is ``0`` up to ``2**256 - 1``. If the result of some operation on those numbers
|
||||||
|
@ -79,7 +79,7 @@ outlined further below:
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
contract Fund {
|
contract Fund {
|
||||||
/// Mapping of ether shares of the contract.
|
/// Mapping of ether shares of the contract.
|
||||||
@ -88,8 +88,7 @@ outlined further below:
|
|||||||
function withdraw() {
|
function withdraw() {
|
||||||
var share = shares[msg.sender];
|
var share = shares[msg.sender];
|
||||||
shares[msg.sender] = 0;
|
shares[msg.sender] = 0;
|
||||||
if (!msg.sender.send(share))
|
msg.sender.transfer(share);
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,22 +123,24 @@ Sending and Receiving Ether
|
|||||||
(for example in the "details" section in Remix).
|
(for example in the "details" section in Remix).
|
||||||
|
|
||||||
- There is a way to forward more gas to the receiving contract using
|
- 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
|
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.
|
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.
|
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.
|
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
|
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.
|
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
|
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).
|
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
|
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>`.
|
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
|
// THIS CONTRACT CONTAINS A BUG - DO NOT USE
|
||||||
contract TxUserWallet {
|
contract TxUserWallet {
|
||||||
@ -172,9 +173,9 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like
|
|||||||
owner = msg.sender;
|
owner = msg.sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
function transfer(address dest, uint amount) {
|
function transferTo(address dest, uint amount) {
|
||||||
if (tx.origin != owner) { throw; }
|
require(tx.origin == owner);
|
||||||
if (!dest.call.value(amount)()) throw;
|
dest.transfer(amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +193,7 @@ Now someone tricks you into sending ether to the address of this attack wallet:
|
|||||||
}
|
}
|
||||||
|
|
||||||
function() {
|
function() {
|
||||||
TxUserWallet(msg.sender).transfer(owner, msg.sender.balance);
|
TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ of votes.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
/// @title Voting with delegation.
|
/// @title Voting with delegation.
|
||||||
contract Ballot {
|
contract Ballot {
|
||||||
@ -87,14 +87,14 @@ of votes.
|
|||||||
// Give `voter` the right to vote on this ballot.
|
// Give `voter` the right to vote on this ballot.
|
||||||
// May only be called by `chairperson`.
|
// May only be called by `chairperson`.
|
||||||
function giveRightToVote(address voter) {
|
function giveRightToVote(address voter) {
|
||||||
if (msg.sender != chairperson || voters[voter].voted) {
|
// If the argument of `require` evaluates to `false`,
|
||||||
// `throw` terminates and reverts all changes to
|
// it terminates and reverts all changes to
|
||||||
// the state and to Ether balances. It is often
|
// the state and to Ether balances. It is often
|
||||||
// a good idea to use this if functions are
|
// a good idea to use this if functions are
|
||||||
// called incorrectly. But watch out, this
|
// called incorrectly. But watch out, this
|
||||||
// will also consume all provided gas.
|
// will currently also consume all provided gas
|
||||||
throw;
|
// (this is planned to change in the future).
|
||||||
}
|
require((msg.sender == chairperson) && !voters[voter].voted);
|
||||||
voters[voter].weight = 1;
|
voters[voter].weight = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,12 +102,10 @@ of votes.
|
|||||||
function delegate(address to) {
|
function delegate(address to) {
|
||||||
// assigns reference
|
// assigns reference
|
||||||
Voter sender = voters[msg.sender];
|
Voter sender = voters[msg.sender];
|
||||||
if (sender.voted)
|
require(!sender.voted);
|
||||||
throw;
|
|
||||||
|
|
||||||
// Self-delegation is not allowed.
|
// Self-delegation is not allowed.
|
||||||
if (to == msg.sender)
|
require(to != msg.sender);
|
||||||
throw;
|
|
||||||
|
|
||||||
// Forward the delegation as long as
|
// Forward the delegation as long as
|
||||||
// `to` also delegated.
|
// `to` also delegated.
|
||||||
@ -121,8 +119,7 @@ of votes.
|
|||||||
to = voters[to].delegate;
|
to = voters[to].delegate;
|
||||||
|
|
||||||
// We found a loop in the delegation, not allowed.
|
// We found a loop in the delegation, not allowed.
|
||||||
if (to == msg.sender)
|
require(to != msg.sender);
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since `sender` is a reference, this
|
// Since `sender` is a reference, this
|
||||||
@ -145,8 +142,7 @@ of votes.
|
|||||||
/// to proposal `proposals[proposal].name`.
|
/// to proposal `proposals[proposal].name`.
|
||||||
function vote(uint proposal) {
|
function vote(uint proposal) {
|
||||||
Voter sender = voters[msg.sender];
|
Voter sender = voters[msg.sender];
|
||||||
if (sender.voted)
|
require(!sender.voted);
|
||||||
throw;
|
|
||||||
sender.voted = true;
|
sender.voted = true;
|
||||||
sender.vote = proposal;
|
sender.vote = proposal;
|
||||||
|
|
||||||
@ -218,7 +214,7 @@ activate themselves.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
contract SimpleAuction {
|
contract SimpleAuction {
|
||||||
// Parameters of the auction. Times are either
|
// Parameters of the auction. Times are either
|
||||||
@ -269,16 +265,15 @@ activate themselves.
|
|||||||
// the transaction. The keyword payable
|
// the transaction. The keyword payable
|
||||||
// is required for the function to
|
// is required for the function to
|
||||||
// be able to receive Ether.
|
// be able to receive Ether.
|
||||||
if (now > auctionStart + biddingTime) {
|
|
||||||
// Revert the call if the bidding
|
// Revert the call if the bidding
|
||||||
// period is over.
|
// period is over.
|
||||||
throw;
|
require(now <= (auctionStart + biddingTime));
|
||||||
}
|
|
||||||
if (msg.value <= highestBid) {
|
// If the bid is not higher, send the
|
||||||
// If the bid is not higher, send the
|
// money back.
|
||||||
// money back.
|
require(msg.value > highestBid);
|
||||||
throw;
|
|
||||||
}
|
|
||||||
if (highestBidder != 0) {
|
if (highestBidder != 0) {
|
||||||
// Sending back the money by simply using
|
// Sending back the money by simply using
|
||||||
// highestBidder.send(highestBid) is a security risk
|
// highestBidder.send(highestBid) is a security risk
|
||||||
@ -327,18 +322,15 @@ activate themselves.
|
|||||||
// external contracts.
|
// external contracts.
|
||||||
|
|
||||||
// 1. Conditions
|
// 1. Conditions
|
||||||
if (now <= auctionStart + biddingTime)
|
require(now >= (auctionStart + biddingTime)); // auction did not yet end
|
||||||
throw; // auction did not yet end
|
require(!ended); // this function has already been called
|
||||||
if (ended)
|
|
||||||
throw; // this function has already been called
|
|
||||||
|
|
||||||
// 2. Effects
|
// 2. Effects
|
||||||
ended = true;
|
ended = true;
|
||||||
AuctionEnded(highestBidder, highestBid);
|
AuctionEnded(highestBidder, highestBid);
|
||||||
|
|
||||||
// 3. Interaction
|
// 3. Interaction
|
||||||
if (!beneficiary.send(highestBid))
|
beneficiary.transfer(highestBid);
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +373,7 @@ high or low invalid bids.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
contract BlindAuction {
|
contract BlindAuction {
|
||||||
struct Bid {
|
struct Bid {
|
||||||
@ -409,8 +401,8 @@ high or low invalid bids.
|
|||||||
/// functions. `onlyBefore` is applied to `bid` below:
|
/// functions. `onlyBefore` is applied to `bid` below:
|
||||||
/// The new function body is the modifier's body where
|
/// The new function body is the modifier's body where
|
||||||
/// `_` is replaced by the old function body.
|
/// `_` is replaced by the old function body.
|
||||||
modifier onlyBefore(uint _time) { if (now >= _time) throw; _; }
|
modifier onlyBefore(uint _time) { require(now < _time); _; }
|
||||||
modifier onlyAfter(uint _time) { if (now <= _time) throw; _; }
|
modifier onlyAfter(uint _time) { require(now > _time); _; }
|
||||||
|
|
||||||
function BlindAuction(
|
function BlindAuction(
|
||||||
uint _biddingTime,
|
uint _biddingTime,
|
||||||
@ -454,13 +446,9 @@ high or low invalid bids.
|
|||||||
onlyBefore(revealEnd)
|
onlyBefore(revealEnd)
|
||||||
{
|
{
|
||||||
uint length = bids[msg.sender].length;
|
uint length = bids[msg.sender].length;
|
||||||
if (
|
require(_values.length == length);
|
||||||
_values.length != length ||
|
require(_fake.length == length);
|
||||||
_fake.length != length ||
|
require(_secret.length == length);
|
||||||
_secret.length != length
|
|
||||||
) {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint refund;
|
uint refund;
|
||||||
for (uint i = 0; i < length; i++) {
|
for (uint i = 0; i < length; i++) {
|
||||||
@ -481,8 +469,7 @@ high or low invalid bids.
|
|||||||
// the same deposit.
|
// the same deposit.
|
||||||
bid.blindedBid = 0;
|
bid.blindedBid = 0;
|
||||||
}
|
}
|
||||||
if (!msg.sender.send(refund))
|
msg.sender.transfer(refund);
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is an "internal" function which means that it
|
// This is an "internal" function which means that it
|
||||||
@ -527,14 +514,12 @@ high or low invalid bids.
|
|||||||
function auctionEnd()
|
function auctionEnd()
|
||||||
onlyAfter(revealEnd)
|
onlyAfter(revealEnd)
|
||||||
{
|
{
|
||||||
if (ended)
|
require(!ended);
|
||||||
throw;
|
|
||||||
AuctionEnded(highestBidder, highestBid);
|
AuctionEnded(highestBidder, highestBid);
|
||||||
ended = true;
|
ended = true;
|
||||||
// We send all the money we have, because some
|
// We send all the money we have, because some
|
||||||
// of the refunds might have failed.
|
// of the refunds might have failed.
|
||||||
if (!beneficiary.send(this.balance))
|
beneficiary.transfer(this.balance);
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -546,7 +531,7 @@ Safe Remote Purchase
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
contract Purchase {
|
contract Purchase {
|
||||||
uint public value;
|
uint public value;
|
||||||
@ -558,26 +543,26 @@ Safe Remote Purchase
|
|||||||
function Purchase() payable {
|
function Purchase() payable {
|
||||||
seller = msg.sender;
|
seller = msg.sender;
|
||||||
value = msg.value / 2;
|
value = msg.value / 2;
|
||||||
if (2 * value != msg.value) throw;
|
require((2 * value) == msg.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier require(bool _condition) {
|
modifier condition(bool _condition) {
|
||||||
if (!_condition) throw;
|
require(_condition);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier onlyBuyer() {
|
modifier onlyBuyer() {
|
||||||
if (msg.sender != buyer) throw;
|
require(msg.sender == buyer);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier onlySeller() {
|
modifier onlySeller() {
|
||||||
if (msg.sender != seller) throw;
|
require(msg.sender == seller);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier inState(State _state) {
|
modifier inState(State _state) {
|
||||||
if (state != _state) throw;
|
require(state == _state);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,8 +579,7 @@ Safe Remote Purchase
|
|||||||
{
|
{
|
||||||
aborted();
|
aborted();
|
||||||
state = State.Inactive;
|
state = State.Inactive;
|
||||||
if (!seller.send(this.balance))
|
seller.transfer(this.balance);
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Confirm the purchase as buyer.
|
/// Confirm the purchase as buyer.
|
||||||
@ -604,7 +588,7 @@ Safe Remote Purchase
|
|||||||
/// is called.
|
/// is called.
|
||||||
function confirmPurchase()
|
function confirmPurchase()
|
||||||
inState(State.Created)
|
inState(State.Created)
|
||||||
require(msg.value == 2 * value)
|
condition(msg.value == (2 * value))
|
||||||
payable
|
payable
|
||||||
{
|
{
|
||||||
purchaseConfirmed();
|
purchaseConfirmed();
|
||||||
@ -623,10 +607,12 @@ Safe Remote Purchase
|
|||||||
// otherwise, the contracts called using `send` below
|
// otherwise, the contracts called using `send` below
|
||||||
// can call in again here.
|
// can call in again here.
|
||||||
state = State.Inactive;
|
state = State.Inactive;
|
||||||
// This actually allows both the buyer and the seller to
|
|
||||||
// block the refund.
|
// NOTE: This actually allows both the buyer and the seller to
|
||||||
if (!buyer.send(value) || !seller.send(this.balance))
|
// block the refund - the withdraw pattern should be used.
|
||||||
throw;
|
|
||||||
|
buyer.transfer(value);
|
||||||
|
seller.transfer(this.balance));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
contract Purchase {
|
||||||
address public seller;
|
address public seller;
|
||||||
|
|
||||||
modifier onlySeller() { // Modifier
|
modifier onlySeller() { // Modifier
|
||||||
if (msg.sender != seller) throw;
|
require(msg.sender == seller);
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +420,7 @@ Example that shows how to use internal function types::
|
|||||||
|
|
||||||
Another example that uses external function types::
|
Another example that uses external function types::
|
||||||
|
|
||||||
pragma solidity ^0.4.5;
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
contract Oracle {
|
contract Oracle {
|
||||||
struct Request {
|
struct Request {
|
||||||
@ -445,7 +445,7 @@ Another example that uses external function types::
|
|||||||
oracle.query("USD", this.oracleResponse);
|
oracle.query("USD", this.oracleResponse);
|
||||||
}
|
}
|
||||||
function oracleResponse(bytes response) {
|
function oracleResponse(bytes response) {
|
||||||
if (msg.sender != address(oracle)) throw;
|
require(msg.sender == address(oracle));
|
||||||
// Use the data
|
// Use the data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -722,7 +722,7 @@ shown in the following example:
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.11;
|
||||||
|
|
||||||
contract CrowdFunding {
|
contract CrowdFunding {
|
||||||
// Defines a new type with two fields.
|
// Defines a new type with two fields.
|
||||||
@ -763,8 +763,7 @@ shown in the following example:
|
|||||||
return false;
|
return false;
|
||||||
uint amount = c.amount;
|
uint amount = c.amount;
|
||||||
c.amount = 0;
|
c.amount = 0;
|
||||||
if (!c.beneficiary.send(amount))
|
c.beneficiary.transfer(amount);
|
||||||
throw;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user