aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/assembly.rst10
-rw-r--r--docs/bugs_by_version.json4
-rw-r--r--docs/common-patterns.rst20
-rw-r--r--docs/contracts.rst10
-rw-r--r--docs/control-structures.rst42
-rw-r--r--docs/miscellaneous.rst7
-rw-r--r--docs/solidity-by-example.rst66
-rw-r--r--docs/structure-of-a-contract.rst5
-rw-r--r--docs/types.rst9
-rw-r--r--docs/units-and-global-variables.rst29
10 files changed, 164 insertions, 38 deletions
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 705cd1b8..978e71e3 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -405,6 +405,16 @@ changes during the call, and thus references to local variables will be wrong.
}
}
+.. note::
+ If you access variables of a type that spans less than 256 bits
+ (for example ``uint64``, ``address``, ``bytes16`` or ``byte``),
+ you cannot make any assumptions about bits not part of the
+ encoding of the type. Especially, do not assume them to be zero.
+ To be safe, always clear the data properly before you use it
+ in a context where this is important:
+ ``uint32 x = f(); assembly { x := and(x, 0xffffffff) /* now use x */ }``
+ To clean signed types, you can use the ``signextend`` opcode.
+
Labels
------
diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json
index 4c976a32..32f305c8 100644
--- a/docs/bugs_by_version.json
+++ b/docs/bugs_by_version.json
@@ -422,6 +422,10 @@
"bugs": [],
"released": "2018-03-07"
},
+ "0.4.22": {
+ "bugs": [],
+ "released": "2018-04-16"
+ },
"0.4.3": {
"bugs": [
"ZeroFunctionSelector",
diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst
index c62b5aca..233bdc4e 100644
--- a/docs/common-patterns.rst
+++ b/docs/common-patterns.rst
@@ -147,7 +147,10 @@ restrictions highly readable.
// a certain address.
modifier onlyBy(address _account)
{
- require(msg.sender == _account);
+ require(
+ msg.sender == _account,
+ "Sender not authorized."
+ );
// Do not forget the "_;"! It will
// be replaced by the actual function
// body when the modifier is used.
@@ -164,7 +167,10 @@ restrictions highly readable.
}
modifier onlyAfter(uint _time) {
- require(now >= _time);
+ require(
+ now >= _time,
+ "Function called too early."
+ );
_;
}
@@ -186,7 +192,10 @@ 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) {
- require(msg.value >= _amount);
+ require(
+ msg.value >= _amount,
+ "Not enough Ether provided."
+ );
_;
if (msg.value > _amount)
msg.sender.send(msg.value - _amount);
@@ -290,7 +299,10 @@ function finishes.
uint public creationTime = now;
modifier atStage(Stages _stage) {
- require(stage == _stage);
+ require(
+ stage == _stage,
+ "Function cannot be called at this time."
+ );
_;
}
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 6798444c..a9650531 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -315,7 +315,10 @@ inheritable properties of contracts and may be overridden by derived contracts.
// function is executed and otherwise, an exception is
// thrown.
modifier onlyOwner {
- require(msg.sender == owner);
+ require(
+ msg.sender == owner,
+ "Only owner can call this function."
+ );
_;
}
}
@@ -360,7 +363,10 @@ inheritable properties of contracts and may be overridden by derived contracts.
contract Mutex {
bool locked;
modifier noReentrancy() {
- require(!locked);
+ require(
+ !locked,
+ "Reentrant call."
+ );
locked = true;
_;
locked = false;
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index 40070a20..879e26f7 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -455,8 +455,9 @@ The ``require`` function should be used to ensure valid conditions, such as inpu
If used properly, analysis tools can evaluate your contract to identify the conditions and function calls which will reach a failing ``assert``. Properly functioning code should never reach a failing assert statement; if this happens there is a bug in your contract which you should fix.
There are two other ways to trigger exceptions: The ``revert`` function can be used to flag an error and
-revert the current call. In the future it might be possible to also include details about the error
-in a call to ``revert``. The ``throw`` keyword can also be used as an alternative to ``revert()``.
+revert the current call. It is possible to provide a string message containing details about the error
+that will be passed back to the caller.
+The deprecated keyword ``throw`` can also be used as an alternative to ``revert()`` (but only without error message).
.. note::
From version 0.4.13 the ``throw`` keyword is deprecated and will be phased out in the future.
@@ -471,13 +472,16 @@ of an exception instead of "bubbling up".
Catching exceptions is not yet possible.
In the following example, you can see how ``require`` can be used to easily check conditions on inputs
-and how ``assert`` can be used for internal error checking::
+and how ``assert`` can be used for internal error checking. Note that you can optionally provide
+a message string for ``require``, but not for ``assert``.
+
+::
pragma solidity ^0.4.0;
contract Sharer {
function sendHalf(address addr) public payable returns (uint balance) {
- require(msg.value % 2 == 0); // Only allow even numbers
+ require(msg.value % 2 == 0, "Even value required.");
uint balanceBeforeTransfer = this.balance;
addr.transfer(msg.value / 2);
// Since transfer throws an exception on failure and
@@ -515,3 +519,33 @@ the EVM to revert all changes made to the state. The reason for reverting is tha
did not occur. Because we want to retain the atomicity of transactions, the safest thing to do is to revert all changes and make the whole transaction
(or at least call) without effect. Note that ``assert``-style exceptions consume all gas available to the call, while
``require``-style exceptions will not consume any gas starting from the Metropolis release.
+
+The following example shows how an error string can be used together with revert and require:
+
+::
+
+ pragma solidity ^0.4.0;
+
+ contract VendingMachine {
+ function buy(uint amount) payable {
+ if (amount > msg.value / 2 ether)
+ revert("Not enough Ether provided.");
+ // Alternative way to do it:
+ require(
+ amount <= msg.value / 2 ether,
+ "Not enough Ether provided."
+ );
+ // Perform the purchase.
+ }
+ }
+
+The provided string will be :ref:`abi-encoded <ABI>` as if it were a call to a function ``Error(string)``.
+In the above example, ``revert("Not enough Ether provided.");`` will cause the following hexadecimal data be
+set as error return data:
+
+.. code::
+
+ 0x08c379a0 // Function selector for Error(string)
+ 0x0000000000000000000000000000000000000000000000000000000000000020 // Data offset
+ 0x000000000000000000000000000000000000000000000000000000000000001a // String length
+ 0x4e6f7420656e6f7567682045746865722070726f76696465642e000000000000 // String data
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index 20400aa2..c7c32528 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -317,6 +317,11 @@ The following is the order of precedence for operators, listed in order of evalu
Global Variables
================
+- ``abi.encode(...) returns (bytes)``: :ref:`ABI <ABI>`-encodes the given arguments
+- ``abi.encodePacked(...) returns (bytes)``: Performes :ref:`packed encoding <abi_packed_mode>` of the given arguments
+- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: :ref:`ABI <ABI>`-encodes the given arguments
+ starting from the second and prepends the given four-byte selector
+- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(signature), ...)```
- ``block.blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent, excluding current, blocks - deprecated in version 0.4.22 and replaced by ``blockhash(uint blockNumber)``.
- ``block.coinbase`` (``address``): current block miner's address
- ``block.difficulty`` (``uint``): current block difficulty
@@ -333,7 +338,9 @@ Global Variables
- ``tx.origin`` (``address``): sender of the transaction (full call chain)
- ``assert(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for internal error)
- ``require(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component)
+- ``require(bool condition, string message)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component). Also provide error message.
- ``revert()``: abort execution and revert state changes
+- ``revert(string message)``: abort execution and revert state changes providing an explanatory string
- ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent blocks
- ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
- ``sha3(...) returns (bytes32)``: an alias to ``keccak256``
diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst
index 3636a332..3cbfcd66 100644
--- a/docs/solidity-by-example.rst
+++ b/docs/solidity-by-example.rst
@@ -87,17 +87,25 @@ of votes.
// Give `voter` the right to vote on this ballot.
// May only be called by `chairperson`.
function giveRightToVote(address voter) public {
- // If the argument of `require` evaluates to `false`,
- // it terminates and reverts all changes to
- // the state and to Ether balances.
- // This consumes all gas in old EVM versions, but not anymore.
- // It is often a good idea to use this if functions are
- // called incorrectly.
+ // If the first argument of `require` evaluates
+ // to `false`, execution terminates and all
+ // changes to the state and to Ether balances
+ // are reverted.
+ // This used to consume all gas in old EVM versions, but
+ // not anymore.
+ // It is often a good idea to use `require` to check if
+ // functions are called correctly.
+ // As a second argument, you can also provide an
+ // explanation about what went wrong.
require(
- (msg.sender == chairperson) &&
- !voters[voter].voted &&
- (voters[voter].weight == 0)
+ msg.sender == chairperson,
+ "Only chairperson can give right to vote."
);
+ require(
+ !voters[voter].voted,
+ "The voter already voted."
+ );
+ require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
@@ -105,10 +113,9 @@ of votes.
function delegate(address to) public {
// assigns reference
Voter storage sender = voters[msg.sender];
- require(!sender.voted);
+ require(!sender.voted, "You already voted.");
- // Self-delegation is not allowed.
- require(to != msg.sender);
+ require(to != msg.sender, "Self-delegation is disallowed.");
// Forward the delegation as long as
// `to` also delegated.
@@ -122,7 +129,7 @@ of votes.
to = voters[to].delegate;
// We found a loop in the delegation, not allowed.
- require(to != msg.sender);
+ require(to != msg.sender, "Found loop in delegation.");
}
// Since `sender` is a reference, this
@@ -145,7 +152,7 @@ of votes.
/// to proposal `proposals[proposal].name`.
function vote(uint proposal) public {
Voter storage sender = voters[msg.sender];
- require(!sender.voted);
+ require(!sender.voted, "Already voted.");
sender.voted = true;
sender.vote = proposal;
@@ -270,11 +277,17 @@ activate themselves.
// Revert the call if the bidding
// period is over.
- require(now <= auctionEnd);
+ require(
+ now <= auctionEnd,
+ "Auction already ended."
+ );
// If the bid is not higher, send the
// money back.
- require(msg.value > highestBid);
+ require(
+ msg.value > highestBid,
+ "There already is a higher bid."
+ );
if (highestBid != 0) {
// Sending back the money by simply using
@@ -324,8 +337,8 @@ activate themselves.
// external contracts.
// 1. Conditions
- require(now >= auctionEnd); // auction did not yet end
- require(!ended); // this function has already been called
+ require(now >= auctionEnd, "Auction not yet ended.");
+ require(!ended, "auctionEnd has already been called.");
// 2. Effects
ended = true;
@@ -543,7 +556,7 @@ Safe Remote Purchase
function Purchase() public payable {
seller = msg.sender;
value = msg.value / 2;
- require((2 * value) == msg.value);
+ require((2 * value) == msg.value, "Value has to be even.");
}
modifier condition(bool _condition) {
@@ -552,17 +565,26 @@ Safe Remote Purchase
}
modifier onlyBuyer() {
- require(msg.sender == buyer);
+ require(
+ msg.sender == buyer,
+ "Only buyer can call this."
+ );
_;
}
modifier onlySeller() {
- require(msg.sender == seller);
+ require(
+ msg.sender == seller,
+ "Only seller can call this."
+ );
_;
}
modifier inState(State _state) {
- require(state == _state);
+ require(
+ state == _state,
+ "Invalid state."
+ );
_;
}
diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst
index df40b1d0..9e5eacbb 100644
--- a/docs/structure-of-a-contract.rst
+++ b/docs/structure-of-a-contract.rst
@@ -68,7 +68,10 @@ Function modifiers can be used to amend the semantics of functions in a declarat
address public seller;
modifier onlySeller() { // Modifier
- require(msg.sender == seller);
+ require(
+ msg.sender == seller,
+ "Only seller can call this."
+ );
_;
}
diff --git a/docs/types.rst b/docs/types.rst
index 5de6d07e..cf8f91be 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -179,8 +179,8 @@ All three functions ``call``, ``delegatecall`` and ``callcode`` are very low-lev
The ``.gas()`` option is available on all three methods, while the ``.value()`` option is not supported for ``delegatecall``.
.. note::
- All contracts inherit the members of address, so it is possible to query the balance of the
- current contract using ``this.balance``.
+ All contracts can be converted to ``address`` type, so it is possible to query the balance of the
+ current contract using ``address(this).balance``.
.. note::
The use of ``callcode`` is discouraged and will be removed in the future.
@@ -495,7 +495,10 @@ Another example that uses external function types::
oracle.query("USD", this.oracleResponse);
}
function oracleResponse(bytes response) public {
- require(msg.sender == address(oracle));
+ require(
+ msg.sender == address(oracle),
+ "Only oracle can call this."
+ );
// Use the data
}
}
diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst
index e7f41ed1..51f7b9f3 100644
--- a/docs/units-and-global-variables.rst
+++ b/docs/units-and-global-variables.rst
@@ -44,9 +44,10 @@ Special Variables and Functions
===============================
There are special variables and functions which always exist in the global
-namespace and are mainly used to provide information about the blockchain.
+namespace and are mainly used to provide information about the blockchain
+or are general-use utility functions.
-.. index:: block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin
+.. index:: abi, block, coinbase, difficulty, encode, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin
Block and Transaction Properties
@@ -90,6 +91,26 @@ Block and Transaction Properties
You can only access the hashes of the most recent 256 blocks, all other
values will be zero.
+.. index:: abi, encoding, packed
+
+ABI Encoding Functions
+----------------------
+
+- ``abi.encode(...) returns (bytes)``: ABI-encodes the given arguments
+- ``abi.encodePacked(...) returns (bytes)``: Performes packed encoding of the given arguments
+- ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: ABI-encodes the given arguments
+ starting from the second and prepends the given four-byte selector
+- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(signature), ...)```
+
+.. note::
+ These encoding functions can be used to craft data for function calls without actually
+ calling a function. Furthermore, ``keccak256(abi.encodePacked(a, b))`` is a more
+ explicit way to compute ``keccak256(a, b)``, which will be deprecated in future
+ versions.
+
+See the documentation about the :ref:`ABI <ABI>` and the
+:ref:`tightly packed encoding <abi_packed_mode>` for details about the encoding.
+
.. index:: assert, revert, require
Error Handling
@@ -99,8 +120,12 @@ Error Handling
throws if the condition is not met - to be used for internal errors.
``require(bool condition)``:
throws if the condition is not met - to be used for errors in inputs or external components.
+``require(bool condition, string message)``:
+ throws if the condition is not met - to be used for errors in inputs or external components. Also provides an error message.
``revert()``:
abort execution and revert state changes
+``revert(string reason)``:
+ abort execution and revert state changes, providing an explanatory string
.. index:: keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography,