diff options
Diffstat (limited to 'docs/control-structures.rst')
-rw-r--r-- | docs/control-structures.rst | 42 |
1 files changed, 38 insertions, 4 deletions
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 |