mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Grammar and Documentation.
This commit is contained in:
parent
a66c354698
commit
a54d9d622f
@ -50,6 +50,12 @@ This section gives detailed instructions on how to update prior code for every b
|
||||
* Change ``uint length = array.push(value)`` to ``array.push(value);``. The new length can be
|
||||
accessed via ``array.length``.
|
||||
|
||||
New Features
|
||||
============
|
||||
|
||||
* The :ref:`try/catch statement <try-catch>` allows you to react on failed external calls.
|
||||
|
||||
|
||||
Deprecated Elements
|
||||
===================
|
||||
|
||||
|
@ -15,6 +15,10 @@ Most of the control structures known from curly-braces languages are available i
|
||||
There is: ``if``, ``else``, ``while``, ``do``, ``for``, ``break``, ``continue``, ``return``, with
|
||||
the usual semantics known from C or JavaScript.
|
||||
|
||||
Solidity also supports exception handling in the form of ``try``/``catch``-statements,
|
||||
but only for :ref:`external function calls <external-function-calls>` and
|
||||
contract creation calls.
|
||||
|
||||
Parentheses can *not* be omitted for conditionals, but curly brances can be omitted
|
||||
around single-statement bodies.
|
||||
|
||||
@ -383,7 +387,7 @@ of an exception instead of "bubbling up".
|
||||
.. warning::
|
||||
The low-level functions ``call``, ``delegatecall`` and ``staticcall`` return ``true`` as their first return value if the account called is non-existent, as part of the design of EVM. Existence must be checked prior to calling if needed.
|
||||
|
||||
It is not yet possible to catch exceptions with Solidity.
|
||||
Exceptions can be caught with the ``try``/``catch`` statement.
|
||||
|
||||
``assert`` and ``require``
|
||||
--------------------------
|
||||
@ -488,3 +492,94 @@ In the above example, ``revert("Not enough Ether provided.");`` returns the foll
|
||||
.. note::
|
||||
There used to be a keyword called ``throw`` with the same semantics as ``revert()`` which
|
||||
was deprecated in version 0.4.13 and removed in version 0.5.0.
|
||||
|
||||
|
||||
.. _try-catch:
|
||||
|
||||
``try``/``catch``
|
||||
-----------------
|
||||
|
||||
A failure in an external call can be caught using a try/catch statement, as follows:
|
||||
|
||||
::
|
||||
|
||||
pragma solidity >=0.5.0 <0.7.0;
|
||||
|
||||
interface DataFeed { function getData(address token) external returns (uint value); }
|
||||
|
||||
contract FeedConsumer {
|
||||
DataFeed feed;
|
||||
uint errorCount;
|
||||
function rate(address token) public returns (uint value, bool success) {
|
||||
// Permanently disable the mechanism if there are
|
||||
// more than 10 errors.
|
||||
require(errorCount < 10);
|
||||
try feed.getData(token) returns (uint v) {
|
||||
return (v, true);
|
||||
} catch Error(string memory /*reason*/) {
|
||||
// This is executed in case
|
||||
// revert was called inside getData
|
||||
// and a reason string was provided.
|
||||
errorCount++;
|
||||
return (0, false);
|
||||
} catch (bytes memory /*lowLevelData*/) {
|
||||
// This is executed in case revert() was used
|
||||
// or there was a failing assertion, division
|
||||
// by zero, etc. inside getData.
|
||||
errorCount++;
|
||||
return (0, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
The ``try`` keyword has to be followed by an expression representing an external function call
|
||||
or a contract creation (``new ContractName()``).
|
||||
Errors inside the expression are not caught (for example if it is a complex expression
|
||||
that also involves internal function calls), only a revert happening inside the external
|
||||
call itself. The ``returns`` part (which is optional) that follows declares return variables
|
||||
matching the types returned by the external call. In case there was no error,
|
||||
these variables are assigned and the contract's execution continues inside the
|
||||
first success block. If the end of the success block is reached, execution continues after the ``catch`` blocks.
|
||||
|
||||
Currently, Solidity supports different kinds of catch blocks depending on the
|
||||
type of error. If the error was caused by ``revert("reasonString")`` or
|
||||
``require(false, "reasonString")`` (or an internal error that causes such an
|
||||
exception), then the catch clause
|
||||
of the type ``catch Error(string memory reason)`` will be executed.
|
||||
|
||||
It is planned to support other types of error data in the future.
|
||||
The string ``Error`` is currently parsed as is and is not treated as an identifier.
|
||||
|
||||
The clause ``catch (bytes memory lowLevelData)`` is executed if the error signature
|
||||
does not match any other clause, there was an error during decoding of the error
|
||||
message, if there was a failing assertion in the external
|
||||
call (for example due to a division by zero or a failing ``assert()``) or
|
||||
if no error data was provided with the exception.
|
||||
The declared variable provides access to the low-level error data in that case.
|
||||
|
||||
If you are not interested in the error data, you can just use
|
||||
``catch { ... }`` (even as the only catch clause).
|
||||
|
||||
In order to catch all error cases, you have to have at least the clause
|
||||
``catch { ...}`` or the clause ``catch (bytes memory lowLevelData) { ... }``.
|
||||
|
||||
The variables declared in the ``returns`` and the ``catch`` clause are only
|
||||
in scope in the block that follows.
|
||||
|
||||
.. note::
|
||||
|
||||
If an error happens during the decoding of the return data
|
||||
inside a try/catch-statement, this causes an exception in the currently
|
||||
executing contract and because of that, it is not caught in the catch clause.
|
||||
If there is an error during decoding of ``catch Error(string memory reason)``
|
||||
and there is a low-level catch clause, this error is caught there.
|
||||
|
||||
.. note::
|
||||
|
||||
If execution reaches a catch-block, then the state-changing effects of
|
||||
the external call have been reverted. If execution reaches
|
||||
the success block, the effects were not reverted.
|
||||
If the effects have been reverted, then execution either continues
|
||||
in a catch block or the execution of the try/catch statement itself
|
||||
reverts (for example due to decoding failures as noted above or
|
||||
due to not providing a low-level catch clause).
|
@ -62,12 +62,14 @@ StorageLocation = 'memory' | 'storage' | 'calldata'
|
||||
StateMutability = 'pure' | 'view' | 'payable'
|
||||
|
||||
Block = '{' Statement* '}'
|
||||
Statement = IfStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement |
|
||||
Statement = IfStatement | TryStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement |
|
||||
( DoWhileStatement | PlaceholderStatement | Continue | Break | Return |
|
||||
Throw | EmitStatement | SimpleStatement ) ';'
|
||||
|
||||
ExpressionStatement = Expression
|
||||
IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )?
|
||||
TryStatement = 'try' Expression ( 'returns' ParameterList )? Block CatchClause+
|
||||
CatchClause = 'catch' Identifier? ParameterList Block
|
||||
WhileStatement = 'while' '(' Expression ')' Statement
|
||||
PlaceholderStatement = '_'
|
||||
SimpleStatement = VariableDefinition | ExpressionStatement
|
||||
|
Loading…
Reference in New Issue
Block a user