diff --git a/docs/Solidity.g4 b/docs/Solidity.g4 index a415c19f9..96504a3c8 100644 --- a/docs/Solidity.g4 +++ b/docs/Solidity.g4 @@ -8,7 +8,8 @@ grammar Solidity; sourceUnit - : (pragmaDirective | importDirective | structDefinition | enumDefinition | contractDefinition)* EOF ; + : (pragmaDirective | importDirective | structDefinition | enumDefinition | contractDefinition | + errorDefinition)* EOF ; pragmaDirective : 'pragma' pragmaName pragmaValue ';' ; @@ -51,6 +52,7 @@ contractPart | modifierDefinition | functionDefinition | eventDefinition + | errorDefinition | enumDefinition ; stateVariableDeclaration @@ -92,6 +94,10 @@ modifierInvocation eventDefinition : 'event' identifier eventParameterList AnonymousKeyword? ';' ; +errorDefinition : 'error' identifier errorParameterList ';' ; +errorParameterList : '(' (errorParameter (',' errorParameter)*)? ')' ; +errorParameter : typeName identifier? ; + enumDefinition : 'enum' identifier '{' enumValue? (',' enumValue)* '}' ; @@ -167,6 +173,9 @@ tryStatement : 'try' expression returnParameters? block catchClause+ ; // leave this as is, befitting with the Solidity docs. catchClause : 'catch' ( identifier? parameterList )? block ; +catchClauseNEW : 'catch' errorTypeName parameterList block ; +errorTypeName : identifier ; + whileStatement : 'while' '(' expression ')' statement ; diff --git a/docs/error-type.md b/docs/error-type.md new file mode 100644 index 000000000..2a8a6b721 --- /dev/null +++ b/docs/error-type.md @@ -0,0 +1,92 @@ +# Solidity `error` type + +## Motivation + +We want to support typed errors in a syntactically equivalent and convenient way like +the programmer can define `event` types. + +Example: + +```solidity +contract C { + event HighestBidIncreased(address bidder, uint amount); + error BiddingFailed(string reason); + + function bid() public payable { + try attemptBid() { + emit HighestBidIncreased(msg.sender, msg.value); // Triggering event + } catch BiddingFailed(reason) { + // handle error with given reason + } + } + + function attemptBid() { + // require() should now support a custom secondary parameter to throw custom errors upon failed expectations. + require(biddingPossible, BiddingFailed("Bidding impossible")); + } +} +``` + +## Syntax + +```bnf +errorDefinition + : 'error' identifier eventParameterList AnonymousKeyword? ';' ; +``` + +## Semantic + +Errors can be instantiated wherever a variable of a type can be declared. +Errors can NOT be instantiated like any arbitrary type, but instead only be used +within `require` and `revert`. + +Error types are ALWAYS publicly visible, i.e. they can not be made private. + +## Catching Errors + +With the try-catch statement, you can already catch `Error(string)`. This will be extended +to catch errors by other structured types that were declared via the `error` keyword. + +The fallback catch will also apply to error types that weren't matched. + +Example: + +```solidity +contract C { + event HighestBidIncreased(address bidder, uint amount); + + error BiddingFailed(string reason); + error SomeOtherError(string text, uint value); + + function bid() public payable { + try attemptBid() { + emit HighestBidIncreased(msg.sender, msg.value); // Triggering event + } catch BiddingFailed(string reason) { + // handle error with given reason + } catch SomeOtherError(string reason, uint value) { + // handle other error with an additional value + } catch Error(string message) { + // handle classic error messages + } catch (bytes data) { + // parametrized default + } + } +} +``` + +## The current `Error(string message)` type. + +Currently, exceptions can be caught via `catch Error(string text)`. This behaviour will be retained +by providing the default error type `Error`. + +## Code Generation + +Whatever ABI encoder is selected, this one will be used to encode/decode the error in +require/revert/catch. + + + + + + +