mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Revert statement.
This commit is contained in:
parent
b04b189959
commit
fb67051467
@ -86,6 +86,16 @@ void PostTypeChecker::endVisit(EmitStatement const& _emit)
|
|||||||
callEndVisit(_emit);
|
callEndVisit(_emit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PostTypeChecker::visit(RevertStatement const& _revert)
|
||||||
|
{
|
||||||
|
return callVisit(_revert);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostTypeChecker::endVisit(RevertStatement const& _revert)
|
||||||
|
{
|
||||||
|
callEndVisit(_revert);
|
||||||
|
}
|
||||||
|
|
||||||
bool PostTypeChecker::visit(FunctionCall const& _functionCall)
|
bool PostTypeChecker::visit(FunctionCall const& _functionCall)
|
||||||
{
|
{
|
||||||
return callVisit(_functionCall);
|
return callVisit(_functionCall);
|
||||||
@ -281,42 +291,59 @@ private:
|
|||||||
bool m_insideModifierInvocation = false;
|
bool m_insideModifierInvocation = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EventOutsideEmitChecker: public PostTypeChecker::Checker
|
struct EventOutsideEmitErrorOutsideRevertChecker: public PostTypeChecker::Checker
|
||||||
{
|
{
|
||||||
EventOutsideEmitChecker(ErrorReporter& _errorReporter):
|
EventOutsideEmitErrorOutsideRevertChecker(ErrorReporter& _errorReporter):
|
||||||
Checker(_errorReporter) {}
|
Checker(_errorReporter) {}
|
||||||
|
|
||||||
bool visit(EmitStatement const&) override
|
bool visit(EmitStatement const& _emitStatement) override
|
||||||
{
|
{
|
||||||
m_insideEmitStatement = true;
|
m_currentStatement = &_emitStatement;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void endVisit(EmitStatement const&) override
|
void endVisit(EmitStatement const&) override
|
||||||
{
|
{
|
||||||
m_insideEmitStatement = true;
|
m_currentStatement = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool visit(RevertStatement const& _revertStatement) override
|
||||||
|
{
|
||||||
|
m_currentStatement = &_revertStatement;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void endVisit(RevertStatement const&) override
|
||||||
|
{
|
||||||
|
m_currentStatement = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool visit(FunctionCall const& _functionCall) override
|
bool visit(FunctionCall const& _functionCall) override
|
||||||
{
|
{
|
||||||
if (*_functionCall.annotation().kind != FunctionCallKind::FunctionCall)
|
if (*_functionCall.annotation().kind == FunctionCallKind::FunctionCall)
|
||||||
return true;
|
if (auto const* functionType = dynamic_cast<FunctionType const*>(_functionCall.expression().annotation().type))
|
||||||
|
{
|
||||||
if (FunctionTypePointer const functionType = dynamic_cast<FunctionTypePointer const>(_functionCall.expression().annotation().type))
|
// Check for event outside of emit statement
|
||||||
// Check for event outside of emit statement
|
if (!dynamic_cast<EmitStatement const*>(m_currentStatement) && functionType->kind() == FunctionType::Kind::Event)
|
||||||
if (!m_insideEmitStatement && functionType->kind() == FunctionType::Kind::Event)
|
m_errorReporter.typeError(
|
||||||
m_errorReporter.typeError(
|
3132_error,
|
||||||
3132_error,
|
_functionCall.location(),
|
||||||
_functionCall.location(),
|
"Event invocations have to be prefixed by \"emit\"."
|
||||||
"Event invocations have to be prefixed by \"emit\"."
|
);
|
||||||
);
|
else if (!dynamic_cast<RevertStatement const*>(m_currentStatement) && functionType->kind() == FunctionType::Kind::Error)
|
||||||
|
m_errorReporter.typeError(
|
||||||
|
7757_error,
|
||||||
|
_functionCall.location(),
|
||||||
|
"Errors can only be used with revert statements: \"revert MyError();\"."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
m_currentStatement = nullptr;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Flag indicating whether we are currently inside an EmitStatement.
|
Statement const* m_currentStatement = nullptr;
|
||||||
bool m_insideEmitStatement = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NoVariablesInInterfaceChecker: public PostTypeChecker::Checker
|
struct NoVariablesInInterfaceChecker: public PostTypeChecker::Checker
|
||||||
@ -395,14 +422,16 @@ struct ReservedErrorSelector: public PostTypeChecker::Checker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PostTypeChecker::PostTypeChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter)
|
PostTypeChecker::PostTypeChecker(langutil::ErrorReporter& _errorReporter): m_errorReporter(_errorReporter)
|
||||||
{
|
{
|
||||||
m_checkers.push_back(make_shared<ConstStateVarCircularReferenceChecker>(_errorReporter));
|
m_checkers.push_back(make_shared<ConstStateVarCircularReferenceChecker>(_errorReporter));
|
||||||
m_checkers.push_back(make_shared<OverrideSpecifierChecker>(_errorReporter));
|
m_checkers.push_back(make_shared<OverrideSpecifierChecker>(_errorReporter));
|
||||||
m_checkers.push_back(make_shared<ModifierContextChecker>(_errorReporter));
|
m_checkers.push_back(make_shared<ModifierContextChecker>(_errorReporter));
|
||||||
m_checkers.push_back(make_shared<EventOutsideEmitChecker>(_errorReporter));
|
m_checkers.push_back(make_shared<EventOutsideEmitErrorOutsideRevertChecker>(_errorReporter));
|
||||||
m_checkers.push_back(make_shared<NoVariablesInInterfaceChecker>(_errorReporter));
|
m_checkers.push_back(make_shared<NoVariablesInInterfaceChecker>(_errorReporter));
|
||||||
m_checkers.push_back(make_shared<ReservedErrorSelector>(_errorReporter));
|
m_checkers.push_back(make_shared<ReservedErrorSelector>(_errorReporter));
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,9 @@ private:
|
|||||||
bool visit(EmitStatement const& _emit) override;
|
bool visit(EmitStatement const& _emit) override;
|
||||||
void endVisit(EmitStatement const& _emit) override;
|
void endVisit(EmitStatement const& _emit) override;
|
||||||
|
|
||||||
|
bool visit(RevertStatement const& _revert) override;
|
||||||
|
void endVisit(RevertStatement const& _revert) override;
|
||||||
|
|
||||||
bool visit(FunctionCall const& _functionCall) override;
|
bool visit(FunctionCall const& _functionCall) override;
|
||||||
|
|
||||||
bool visit(Identifier const& _identifier) override;
|
bool visit(Identifier const& _identifier) override;
|
||||||
|
@ -1167,6 +1167,18 @@ void TypeChecker::endVisit(EmitStatement const& _emit)
|
|||||||
m_errorReporter.typeError(9292_error, _emit.eventCall().expression().location(), "Expression has to be an event invocation.");
|
m_errorReporter.typeError(9292_error, _emit.eventCall().expression().location(), "Expression has to be an event invocation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TypeChecker::endVisit(RevertStatement const& _revert)
|
||||||
|
{
|
||||||
|
FunctionCall const& errorCall = _revert.errorCall();
|
||||||
|
if (
|
||||||
|
*errorCall.annotation().kind != FunctionCallKind::FunctionCall ||
|
||||||
|
type(errorCall.expression())->category() != Type::Category::Function ||
|
||||||
|
dynamic_cast<FunctionType const&>(*type(errorCall.expression())).kind() != FunctionType::Kind::Error
|
||||||
|
)
|
||||||
|
m_errorReporter.typeError(1885_error, errorCall.expression().location(), "Expression has to be an error.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
||||||
{
|
{
|
||||||
if (!_statement.initialValue())
|
if (!_statement.initialValue())
|
||||||
|
@ -134,6 +134,7 @@ private:
|
|||||||
bool visit(ForStatement const& _forStatement) override;
|
bool visit(ForStatement const& _forStatement) override;
|
||||||
void endVisit(Return const& _return) override;
|
void endVisit(Return const& _return) override;
|
||||||
void endVisit(EmitStatement const& _emit) override;
|
void endVisit(EmitStatement const& _emit) override;
|
||||||
|
void endVisit(RevertStatement const& _revert) override;
|
||||||
bool visit(VariableDeclarationStatement const& _variable) override;
|
bool visit(VariableDeclarationStatement const& _variable) override;
|
||||||
void endVisit(ExpressionStatement const& _statement) override;
|
void endVisit(ExpressionStatement const& _statement) override;
|
||||||
bool visit(Conditional const& _conditional) override;
|
bool visit(Conditional const& _conditional) override;
|
||||||
|
@ -1726,6 +1726,31 @@ public:
|
|||||||
void accept(ASTConstVisitor& _visitor) const override;
|
void accept(ASTConstVisitor& _visitor) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The revert statement is used to revert state changes and return error data.
|
||||||
|
*/
|
||||||
|
class RevertStatement: public Statement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit RevertStatement(
|
||||||
|
int64_t _id,
|
||||||
|
SourceLocation const& _location,
|
||||||
|
ASTPointer<ASTString> const& _docString,
|
||||||
|
ASTPointer<FunctionCall> _functionCall
|
||||||
|
):
|
||||||
|
Statement(_id, _location, _docString), m_errorCall(std::move(_functionCall))
|
||||||
|
{
|
||||||
|
solAssert(m_errorCall, "");
|
||||||
|
}
|
||||||
|
void accept(ASTVisitor& _visitor) override;
|
||||||
|
void accept(ASTConstVisitor& _visitor) const override;
|
||||||
|
|
||||||
|
FunctionCall const& errorCall() const { return *m_errorCall; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASTPointer<FunctionCall> m_errorCall;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The emit statement is used to emit events: emit EventName(arg1, ..., argn)
|
* The emit statement is used to emit events: emit EventName(arg1, ..., argn)
|
||||||
*/
|
*/
|
||||||
|
@ -90,6 +90,7 @@ public:
|
|||||||
virtual bool visit(Return& _node) { return visitNode(_node); }
|
virtual bool visit(Return& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(Throw& _node) { return visitNode(_node); }
|
virtual bool visit(Throw& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(EmitStatement& _node) { return visitNode(_node); }
|
virtual bool visit(EmitStatement& _node) { return visitNode(_node); }
|
||||||
|
virtual bool visit(RevertStatement& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(VariableDeclarationStatement& _node) { return visitNode(_node); }
|
virtual bool visit(VariableDeclarationStatement& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(ExpressionStatement& _node) { return visitNode(_node); }
|
virtual bool visit(ExpressionStatement& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(Conditional& _node) { return visitNode(_node); }
|
virtual bool visit(Conditional& _node) { return visitNode(_node); }
|
||||||
@ -144,6 +145,7 @@ public:
|
|||||||
virtual void endVisit(Return& _node) { endVisitNode(_node); }
|
virtual void endVisit(Return& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(Throw& _node) { endVisitNode(_node); }
|
virtual void endVisit(Throw& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(EmitStatement& _node) { endVisitNode(_node); }
|
virtual void endVisit(EmitStatement& _node) { endVisitNode(_node); }
|
||||||
|
virtual void endVisit(RevertStatement& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(VariableDeclarationStatement& _node) { endVisitNode(_node); }
|
virtual void endVisit(VariableDeclarationStatement& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(ExpressionStatement& _node) { endVisitNode(_node); }
|
virtual void endVisit(ExpressionStatement& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(Conditional& _node) { endVisitNode(_node); }
|
virtual void endVisit(Conditional& _node) { endVisitNode(_node); }
|
||||||
@ -220,6 +222,7 @@ public:
|
|||||||
virtual bool visit(Return const& _node) { return visitNode(_node); }
|
virtual bool visit(Return const& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(Throw const& _node) { return visitNode(_node); }
|
virtual bool visit(Throw const& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(EmitStatement const& _node) { return visitNode(_node); }
|
virtual bool visit(EmitStatement const& _node) { return visitNode(_node); }
|
||||||
|
virtual bool visit(RevertStatement const& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(VariableDeclarationStatement const& _node) { return visitNode(_node); }
|
virtual bool visit(VariableDeclarationStatement const& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(ExpressionStatement const& _node) { return visitNode(_node); }
|
virtual bool visit(ExpressionStatement const& _node) { return visitNode(_node); }
|
||||||
virtual bool visit(Conditional const& _node) { return visitNode(_node); }
|
virtual bool visit(Conditional const& _node) { return visitNode(_node); }
|
||||||
@ -274,6 +277,7 @@ public:
|
|||||||
virtual void endVisit(Return const& _node) { endVisitNode(_node); }
|
virtual void endVisit(Return const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(Throw const& _node) { endVisitNode(_node); }
|
virtual void endVisit(Throw const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(EmitStatement const& _node) { endVisitNode(_node); }
|
virtual void endVisit(EmitStatement const& _node) { endVisitNode(_node); }
|
||||||
|
virtual void endVisit(RevertStatement const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(VariableDeclarationStatement const& _node) { endVisitNode(_node); }
|
virtual void endVisit(VariableDeclarationStatement const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(ExpressionStatement const& _node) { endVisitNode(_node); }
|
virtual void endVisit(ExpressionStatement const& _node) { endVisitNode(_node); }
|
||||||
virtual void endVisit(Conditional const& _node) { endVisitNode(_node); }
|
virtual void endVisit(Conditional const& _node) { endVisitNode(_node); }
|
||||||
|
@ -682,6 +682,20 @@ void Throw::accept(ASTConstVisitor& _visitor) const
|
|||||||
_visitor.endVisit(*this);
|
_visitor.endVisit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RevertStatement::accept(ASTVisitor& _visitor)
|
||||||
|
{
|
||||||
|
if (_visitor.visit(*this))
|
||||||
|
m_errorCall->accept(_visitor);
|
||||||
|
_visitor.endVisit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RevertStatement::accept(ASTConstVisitor& _visitor) const
|
||||||
|
{
|
||||||
|
if (_visitor.visit(*this))
|
||||||
|
m_errorCall->accept(_visitor);
|
||||||
|
_visitor.endVisit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
void EmitStatement::accept(ASTVisitor& _visitor)
|
void EmitStatement::accept(ASTVisitor& _visitor)
|
||||||
{
|
{
|
||||||
if (_visitor.visit(*this))
|
if (_visitor.visit(*this))
|
||||||
|
@ -1250,11 +1250,13 @@ ASTPointer<Statement> Parser::parseStatement(bool _allowUnchecked)
|
|||||||
statement = parseEmitStatement(docString);
|
statement = parseEmitStatement(docString);
|
||||||
break;
|
break;
|
||||||
case Token::Identifier:
|
case Token::Identifier:
|
||||||
if (m_insideModifier && m_scanner->currentLiteral() == "_")
|
if (m_scanner->currentLiteral() == "revert" && m_scanner->peekNextToken() == Token::Identifier)
|
||||||
{
|
statement = parseRevertStatement(docString);
|
||||||
statement = ASTNodeFactory(*this).createNode<PlaceholderStatement>(docString);
|
else if (m_insideModifier && m_scanner->currentLiteral() == "_")
|
||||||
m_scanner->next();
|
{
|
||||||
}
|
statement = ASTNodeFactory(*this).createNode<PlaceholderStatement>(docString);
|
||||||
|
m_scanner->next();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
statement = parseSimpleStatement(docString);
|
statement = parseSimpleStatement(docString);
|
||||||
break;
|
break;
|
||||||
@ -1474,8 +1476,38 @@ ASTPointer<EmitStatement> Parser::parseEmitStatement(ASTPointer<ASTString> const
|
|||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
expectToken(Token::RParen);
|
expectToken(Token::RParen);
|
||||||
auto eventCall = eventCallNodeFactory.createNode<FunctionCall>(eventName, arguments, names);
|
auto eventCall = eventCallNodeFactory.createNode<FunctionCall>(eventName, arguments, names);
|
||||||
auto statement = nodeFactory.createNode<EmitStatement>(_docString, eventCall);
|
return nodeFactory.createNode<EmitStatement>(_docString, eventCall);
|
||||||
return statement;
|
}
|
||||||
|
|
||||||
|
ASTPointer<RevertStatement> Parser::parseRevertStatement(ASTPointer<ASTString> const& _docString)
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
solAssert(*expectIdentifierToken() == "revert", "");
|
||||||
|
|
||||||
|
ASTNodeFactory errorCallNodeFactory(*this);
|
||||||
|
|
||||||
|
solAssert(m_scanner->currentToken() == Token::Identifier, "");
|
||||||
|
|
||||||
|
IndexAccessedPath iap;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
iap.path.push_back(parseIdentifier());
|
||||||
|
if (m_scanner->currentToken() != Token::Period)
|
||||||
|
break;
|
||||||
|
m_scanner->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto errorName = expressionFromIndexAccessStructure(iap);
|
||||||
|
expectToken(Token::LParen);
|
||||||
|
|
||||||
|
vector<ASTPointer<Expression>> arguments;
|
||||||
|
vector<ASTPointer<ASTString>> names;
|
||||||
|
std::tie(arguments, names) = parseFunctionCallArguments();
|
||||||
|
errorCallNodeFactory.markEndPosition();
|
||||||
|
nodeFactory.markEndPosition();
|
||||||
|
expectToken(Token::RParen);
|
||||||
|
auto errorCall = errorCallNodeFactory.createNode<FunctionCall>(errorName, arguments, names);
|
||||||
|
return nodeFactory.createNode<RevertStatement>(_docString, errorCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString)
|
ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const& _docString)
|
||||||
|
@ -127,6 +127,7 @@ private:
|
|||||||
ASTPointer<WhileStatement> parseDoWhileStatement(ASTPointer<ASTString> const& _docString);
|
ASTPointer<WhileStatement> parseDoWhileStatement(ASTPointer<ASTString> const& _docString);
|
||||||
ASTPointer<ForStatement> parseForStatement(ASTPointer<ASTString> const& _docString);
|
ASTPointer<ForStatement> parseForStatement(ASTPointer<ASTString> const& _docString);
|
||||||
ASTPointer<EmitStatement> parseEmitStatement(ASTPointer<ASTString> const& docString);
|
ASTPointer<EmitStatement> parseEmitStatement(ASTPointer<ASTString> const& docString);
|
||||||
|
ASTPointer<RevertStatement> parseRevertStatement(ASTPointer<ASTString> const& docString);
|
||||||
/// A "simple statement" can be a variable declaration statement or an expression statement.
|
/// A "simple statement" can be a variable declaration statement or an expression statement.
|
||||||
ASTPointer<Statement> parseSimpleStatement(ASTPointer<ASTString> const& _docString);
|
ASTPointer<Statement> parseSimpleStatement(ASTPointer<ASTString> const& _docString);
|
||||||
ASTPointer<VariableDeclarationStatement> parseVariableDeclarationStatement(
|
ASTPointer<VariableDeclarationStatement> parseVariableDeclarationStatement(
|
||||||
|
18
test/libsolidity/semanticTests/errors/panic_via_import.sol
Normal file
18
test/libsolidity/semanticTests/errors/panic_via_import.sol
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
==== Source: s1.sol ====
|
||||||
|
error E(uint);
|
||||||
|
==== Source: s2.sol ====
|
||||||
|
import { E as Panic } from "s1.sol";
|
||||||
|
contract C {
|
||||||
|
error E(uint);
|
||||||
|
function a() public pure {
|
||||||
|
revert Panic(1);
|
||||||
|
}
|
||||||
|
function b() public pure {
|
||||||
|
revert E(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// a() -> FAILURE, hex"002ff067", hex"0000000000000000000000000000000000000000000000000000000000000001"
|
||||||
|
// b() -> FAILURE, hex"002ff067", hex"0000000000000000000000000000000000000000000000000000000000000001"
|
20
test/libsolidity/semanticTests/errors/using_structs.sol
Normal file
20
test/libsolidity/semanticTests/errors/using_structs.sol
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
pragma abicoder v2;
|
||||||
|
struct S { uint a; string b; }
|
||||||
|
error E(uint a, S s, uint b);
|
||||||
|
contract C {
|
||||||
|
S s;
|
||||||
|
function f(bool c) public {
|
||||||
|
if (c) {
|
||||||
|
s.a = 9;
|
||||||
|
s.b = "abc";
|
||||||
|
revert E(2, s, 7);
|
||||||
|
} else {
|
||||||
|
revert E({b: 7, a: 2, s: S({b: "abc", a: 9})});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// f(bool): true -> FAILURE, hex"e96e07f0", hex"0000000000000000000000000000000000000000000000000000000000000002", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000007", hex"0000000000000000000000000000000000000000000000000000000000000009", hex"0000000000000000000000000000000000000000000000000000000000000040", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"6162630000000000000000000000000000000000000000000000000000000000"
|
||||||
|
// f(bool): false -> FAILURE, hex"e96e07f0", hex"0000000000000000000000000000000000000000000000000000000000000002", hex"0000000000000000000000000000000000000000000000000000000000000060", hex"0000000000000000000000000000000000000000000000000000000000000007", hex"0000000000000000000000000000000000000000000000000000000000000009", hex"0000000000000000000000000000000000000000000000000000000000000040", hex"0000000000000000000000000000000000000000000000000000000000000003", hex"6162630000000000000000000000000000000000000000000000000000000000"
|
8
test/libsolidity/syntaxTests/errors/require_custom.sol
Normal file
8
test/libsolidity/syntaxTests/errors/require_custom.sol
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
error E(uint a, uint b);
|
||||||
|
contract C {
|
||||||
|
function f(bool c) public pure {
|
||||||
|
require(c, E(2, 7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 9322: (83-90): No matching declaration found after argument-dependent lookup.
|
@ -0,0 +1,8 @@
|
|||||||
|
error E(uint a, uint b);
|
||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
revert(E(2, 7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 9322: (77-83): No matching declaration found after argument-dependent lookup.
|
@ -0,0 +1,3 @@
|
|||||||
|
revert X();
|
||||||
|
// ----
|
||||||
|
// ParserError 2314: (8-9): Expected ';' but got '('
|
@ -0,0 +1,6 @@
|
|||||||
|
error E();
|
||||||
|
function f() pure {
|
||||||
|
E();
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 7757: (35-38): Errors can only be used with revert statements: "revert MyError();".
|
@ -0,0 +1,4 @@
|
|||||||
|
error E();
|
||||||
|
function f() pure {
|
||||||
|
revert E();
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
error E();
|
||||||
|
function f() public pure {
|
||||||
|
revert E;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// ParserError 2314: (50-51): Expected '(' but got ';'
|
@ -0,0 +1,5 @@
|
|||||||
|
function f() public pure {
|
||||||
|
revert 1;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// ParserError 2314: (38-39): Expected ';' but got 'Number'
|
6
test/libsolidity/syntaxTests/revertStatement/regular.sol
Normal file
6
test/libsolidity/syntaxTests/revertStatement/regular.sol
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
error E();
|
||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
revert E();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
contract C {
|
||||||
|
event E();
|
||||||
|
function f() public pure {
|
||||||
|
revert E();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 1885: (74-75): Expression has to be an error.
|
@ -0,0 +1,8 @@
|
|||||||
|
error revert();
|
||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
revert revert();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 2319: (0-15): This declaration shadows a builtin symbol.
|
8
test/libsolidity/syntaxTests/revertStatement/scoped.sol
Normal file
8
test/libsolidity/syntaxTests/revertStatement/scoped.sol
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
contract A {
|
||||||
|
error E();
|
||||||
|
}
|
||||||
|
contract C {
|
||||||
|
function f() public pure {
|
||||||
|
revert A.E();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
error f(uint, uint);
|
||||||
|
contract C {
|
||||||
|
function f(uint) public {
|
||||||
|
revert f(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 2519: (38-91): This declaration shadows an existing declaration.
|
||||||
|
// TypeError 1885: (79-80): Expression has to be an error.
|
@ -0,0 +1,8 @@
|
|||||||
|
struct S { uint x; }
|
||||||
|
contract C {
|
||||||
|
function f() public {
|
||||||
|
revert S(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError 1885: (75-76): Expression has to be an error.
|
Loading…
Reference in New Issue
Block a user