Merge pull request #7647 from ethereum/virtual-5424

Implement virtual keyword
This commit is contained in:
chriseth 2019-11-19 13:21:27 +01:00 committed by GitHub
commit 6797879128
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
91 changed files with 461 additions and 303 deletions

View File

@ -19,16 +19,13 @@ Breaking changes:
* Source mappings: Add "modifier depth" as a fifth field in the source mappings. * Source mappings: Add "modifier depth" as a fifth field in the source mappings.
* AST: Inline assembly is exported as structured JSON instead of plain string. * AST: Inline assembly is exported as structured JSON instead of plain string.
* Language Feature: When overriding a function or modifier, the new keyword ``override`` must be used. When overriding a function or modifier defined in multiple parallel bases, all bases must be listed in parentheses after the keyword like so: ``override(Base1, Base2)``
Language Features: Language Features:
* Allow global enums and structs. * Allow global enums and structs.
* Allow underscores as delimiters in hex strings. * Allow underscores as delimiters in hex strings.
* Allow explicit conversions from ``address`` to ``address payable`` via ``payable(...)``. * Allow explicit conversions from ``address`` to ``address payable`` via ``payable(...)``.
* Introduce syntax for array slices and implement them for dynamic calldata arrays. * Introduce syntax for array slices and implement them for dynamic calldata arrays.
* Introduce ``push()`` for dynamic storage arrays. It returns a reference to the newly allocated element, if applicable. * Introduce ``push()`` for dynamic storage arrays. It returns a reference to the newly allocated element, if applicable.
* Introduce ``virtual`` and ``override`` keywords
* Modify ``push(element)`` for dynamic storage arrays such that it does not return the new length anymore. * Modify ``push(element)`` for dynamic storage arrays such that it does not return the new length anymore.
* Yul: Introduce ``leave`` statement that exits the current function. * Yul: Introduce ``leave`` statement that exits the current function.

View File

@ -60,6 +60,8 @@ This section highlights changes that affect syntax and semantics.
which send value will revert. If you only implement the receive and not the fallback function, calling a non-existing function on your contract in error is not possible anymore. Unless you are following an upgrade or proxy which send value will revert. If you only implement the receive and not the fallback function, calling a non-existing function on your contract in error is not possible anymore. Unless you are following an upgrade or proxy
pattern, you should not need to implement the fallback function. pattern, you should not need to implement the fallback function.
* Functions can now only be overridden when they are either marked with the ``virtual`` keyword or defined in an interface. When overriding a function or modifier, the new keyword ``override`` must be used. When overriding a function or modifier defined in multiple parallel bases, all bases must be listed in parentheses after the keyword like so: ``override(Base1, Base2)``.
How to update your code How to update your code
======================= =======================
@ -81,6 +83,8 @@ This section gives detailed instructions on how to update prior code for every b
* Choose unique identifiers for variable declarations in inline assembly that do not conflict with declartions outside the inline assembly block. * Choose unique identifiers for variable declarations in inline assembly that do not conflict with declartions outside the inline assembly block.
* Add ``virtual`` to every non-interface function you intend to override. For single inheritance, add ``override`` to every overriding function. For multiple inheritance, add ``override(A, B, ..)``, where you list all contracts that define the overridden function in the brackets. When multiple bases define the same function, the inheriting contract must override all conflicting functions.
New Features New Features
============ ============

View File

@ -24,7 +24,7 @@ all defined functions. The usage of an abstract contract as a base class is show
pragma solidity >=0.4.0 <0.7.0; pragma solidity >=0.4.0 <0.7.0;
abstract contract Feline { abstract contract Feline {
function utterance() public returns (bytes32); function utterance() public virtual returns (bytes32);
} }
contract Cat is Feline { contract Cat is Feline {

View File

@ -42,7 +42,7 @@ Details are given in the following example.
// internal functions and state variables. These cannot be // internal functions and state variables. These cannot be
// accessed externally via `this`, though. // accessed externally via `this`, though.
contract Mortal is Owned { contract Mortal is Owned {
function kill() public { function kill() virtual public {
if (msg.sender == owner) selfdestruct(owner); if (msg.sender == owner) selfdestruct(owner);
} }
} }
@ -77,7 +77,7 @@ Details are given in the following example.
// types of output parameters, that causes an error. // types of output parameters, that causes an error.
// Both local and message-based function calls take these overrides // Both local and message-based function calls take these overrides
// into account. // into account.
function kill() public override { function kill() public virtual override {
if (msg.sender == owner) { if (msg.sender == owner) {
Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
NameReg(config.lookup(1)).unregister(); NameReg(config.lookup(1)).unregister();
@ -115,17 +115,17 @@ seen in the following example::
} }
contract mortal is owned { contract mortal is owned {
function kill() public { function kill() public virtual {
if (msg.sender == owner) selfdestruct(owner); if (msg.sender == owner) selfdestruct(owner);
} }
} }
contract Base1 is mortal { contract Base1 is mortal {
function kill() public override { /* do cleanup 1 */ mortal.kill(); } function kill() public virtual override { /* do cleanup 1 */ mortal.kill(); }
} }
contract Base2 is mortal { contract Base2 is mortal {
function kill() public override { /* do cleanup 2 */ mortal.kill(); } function kill() public virtual override { /* do cleanup 2 */ mortal.kill(); }
} }
contract Final is Base1, Base2 { contract Final is Base1, Base2 {
@ -144,18 +144,18 @@ explicitly in the final override, but this function will bypass
} }
contract mortal is owned { contract mortal is owned {
function kill() public { function kill() virtual public {
if (msg.sender == owner) selfdestruct(owner); if (msg.sender == owner) selfdestruct(owner);
} }
} }
contract Base1 is mortal { contract Base1 is mortal {
function kill() public override { /* do cleanup 1 */ super.kill(); } function kill() public virtual override { /* do cleanup 1 */ super.kill(); }
} }
contract Base2 is mortal { contract Base2 is mortal {
function kill() public override { /* do cleanup 2 */ super.kill(); } function kill() public virtual override { /* do cleanup 2 */ super.kill(); }
} }
contract Final is Base1, Base2 { contract Final is Base1, Base2 {
@ -190,7 +190,7 @@ function header as shown in this example:
contract Base contract Base
{ {
function foo() public {} function foo() virtual public {}
} }
contract Middle is Base {} contract Middle is Base {}
@ -212,12 +212,12 @@ bases, it has to explicitly override it:
contract Base1 contract Base1
{ {
function foo() public {} function foo() virtual public {}
} }
contract Base2 contract Base2
{ {
function foo() public {} function foo() virtual public {}
} }
contract Inherited is Base1, Base2 contract Inherited is Base1, Base2

View File

@ -92,8 +92,8 @@ Yes::
pragma solidity >=0.4.0 <0.7.0; pragma solidity >=0.4.0 <0.7.0;
abstract contract A { abstract contract A {
function spam() public pure; function spam() public virtual pure;
function ham() public pure; function ham() public virtual pure;
} }

View File

@ -143,6 +143,7 @@ namespace langutil
/* Inline Assembly Operators */ \ /* Inline Assembly Operators */ \
T(AssemblyAssign, ":=", 2) \ T(AssemblyAssign, ":=", 2) \
/* Keywords */ \ /* Keywords */ \
K(Abstract, "abstract", 0) \
K(Anonymous, "anonymous", 0) \ K(Anonymous, "anonymous", 0) \
K(As, "as", 0) \ K(As, "as", 0) \
K(Assembly, "assembly", 0) \ K(Assembly, "assembly", 0) \
@ -189,6 +190,7 @@ namespace langutil
K(Using, "using", 0) \ K(Using, "using", 0) \
K(Var, "var", 0) \ K(Var, "var", 0) \
K(View, "view", 0) \ K(View, "view", 0) \
K(Virtual, "virtual", 0) \
K(While, "while", 0) \ K(While, "while", 0) \
\ \
/* Ether subdenominations */ \ /* Ether subdenominations */ \
@ -230,7 +232,6 @@ namespace langutil
T(Identifier, nullptr, 0) \ T(Identifier, nullptr, 0) \
\ \
/* Keywords reserved for future use. */ \ /* Keywords reserved for future use. */ \
K(Abstract, "abstract", 0) \
K(After, "after", 0) \ K(After, "after", 0) \
K(Alias, "alias", 0) \ K(Alias, "alias", 0) \
K(Apply, "apply", 0) \ K(Apply, "apply", 0) \
@ -264,7 +265,6 @@ namespace langutil
K(Typedef, "typedef", 0) \ K(Typedef, "typedef", 0) \
K(TypeOf, "typeof", 0) \ K(TypeOf, "typeof", 0) \
K(Unchecked, "unchecked", 0) \ K(Unchecked, "unchecked", 0) \
K(Virtual, "virtual", 0) \
\ \
/* Illegal token - not able to scan. */ \ /* Illegal token - not able to scan. */ \
T(Illegal, "ILLEGAL", 0) \ T(Illegal, "ILLEGAL", 0) \
@ -313,7 +313,7 @@ namespace TokenTraits
constexpr bool isEtherSubdenomination(Token op) { return op == Token::SubWei || op == Token::SubSzabo || op == Token::SubFinney || op == Token::SubEther; } constexpr bool isEtherSubdenomination(Token op) { return op == Token::SubWei || op == Token::SubSzabo || op == Token::SubFinney || op == Token::SubEther; }
constexpr bool isTimeSubdenomination(Token op) { return op == Token::SubSecond || op == Token::SubMinute || op == Token::SubHour || op == Token::SubDay || op == Token::SubWeek || op == Token::SubYear; } constexpr bool isTimeSubdenomination(Token op) { return op == Token::SubSecond || op == Token::SubMinute || op == Token::SubHour || op == Token::SubDay || op == Token::SubWeek || op == Token::SubYear; }
constexpr bool isReservedKeyword(Token op) { return (Token::Abstract <= op && op <= Token::Virtual); } constexpr bool isReservedKeyword(Token op) { return (Token::After <= op && op <= Token::Unchecked); }
inline Token AssignmentToBinaryOp(Token op) inline Token AssignmentToBinaryOp(Token op)
{ {

View File

@ -245,15 +245,14 @@ void ContractLevelChecker::checkIllegalOverrides(ContractDefinition const& _cont
for (FunctionDefinition const* function: _contract.definedFunctions()) for (FunctionDefinition const* function: _contract.definedFunctions())
{ {
if (function->isConstructor())
continue;
if (contains_if(modSet, MatchByName{function->name()})) if (contains_if(modSet, MatchByName{function->name()}))
m_errorReporter.typeError(function->location(), "Override changes modifier to function."); m_errorReporter.typeError(function->location(), "Override changes modifier to function.");
// Skip if not overridable
if (!function->isOverridable())
continue;
// No inheriting functions found // No inheriting functions found
if (funcSet.find(function) == funcSet.cend() && function->overrides()) if (!funcSet.count(function) && function->overrides())
m_errorReporter.typeError( m_errorReporter.typeError(
function->overrides()->location(), function->overrides()->location(),
"Function has override specified but does not override anything." "Function has override specified but does not override anything."
@ -279,6 +278,12 @@ bool ContractLevelChecker::checkFunctionOverride(FunctionDefinition const& _func
success = false; success = false;
} }
if (!_super.virtualSemantics())
{
overrideError( _super, _function, "Trying to override non-virtual function. Did you forget to add \"virtual\"?", "Overriding function is here:");
success = false;
}
if (!functionType->hasEqualReturnTypes(*superType)) if (!functionType->hasEqualReturnTypes(*superType))
{ {
overrideError(_function, _super, "Overriding function return types differ."); overrideError(_function, _super, "Overriding function return types differ.");
@ -343,11 +348,11 @@ void ContractLevelChecker::overrideListError(FunctionDefinition const& function,
); );
} }
void ContractLevelChecker::overrideError(CallableDeclaration const& function, CallableDeclaration const& super, string message) void ContractLevelChecker::overrideError(CallableDeclaration const& function, CallableDeclaration const& super, string message, string secondaryMsg)
{ {
m_errorReporter.typeError( m_errorReporter.typeError(
function.location(), function.location(),
SecondarySourceLocation().append("Overridden function is here:", super.location()), SecondarySourceLocation().append(secondaryMsg, super.location()),
message message
); );
} }
@ -653,10 +658,10 @@ void ContractLevelChecker::checkAmbiguousOverrides(ContractDefinition const& _co
continue; continue;
// Not an overridable function // Not an overridable function
if (!(*it)->isOverridable()) if ((*it)->isConstructor())
{ {
for (begin++; begin != end; begin++) for (begin++; begin != end; begin++)
solAssert(!(*begin)->isOverridable(), "All functions in range expected to be non-overridable!"); solAssert((*begin)->isConstructor(), "All functions in range expected to be constructors!");
continue; continue;
} }
@ -785,8 +790,7 @@ void ContractLevelChecker::checkOverrideList(FunctionMultiSet const& _funcSet, F
for (auto [begin, end] = _funcSet.equal_range(&_function); begin != end; begin++) for (auto [begin, end] = _funcSet.equal_range(&_function); begin != end; begin++)
{ {
// Validate the override // Validate the override
if (!checkFunctionOverride(_function, **begin)) checkFunctionOverride(_function, **begin);
break;
expectedContracts.insert((*begin)->annotation().contract); expectedContracts.insert((*begin)->annotation().contract);
} }

View File

@ -75,7 +75,7 @@ private:
/// Also stores the direct super function in the AST annotations. /// Also stores the direct super function in the AST annotations.
bool checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super); bool checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super);
void overrideListError(FunctionDefinition const& function, std::set<ContractDefinition const*, LessFunction> _secondary, std::string const& _message1, std::string const& _message2); void overrideListError(FunctionDefinition const& function, std::set<ContractDefinition const*, LessFunction> _secondary, std::string const& _message1, std::string const& _message2);
void overrideError(CallableDeclaration const& function, CallableDeclaration const& super, std::string message); void overrideError(CallableDeclaration const& function, CallableDeclaration const& super, std::string message, std::string secondaryMsg = "Overridden function is here:");
void checkAbstractFunctions(ContractDefinition const& _contract); void checkAbstractFunctions(ContractDefinition const& _contract);
/// Checks that the base constructor arguments are properly provided. /// Checks that the base constructor arguments are properly provided.
/// Fills the list of unimplemented functions in _contract's annotations. /// Fills the list of unimplemented functions in _contract's annotations.

View File

@ -327,6 +327,9 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
{ {
bool isLibraryFunction = _function.inContractKind() == ContractDefinition::ContractKind::Library; bool isLibraryFunction = _function.inContractKind() == ContractDefinition::ContractKind::Library;
if (_function.markedVirtual() && _function.annotation().contract->isInterface())
m_errorReporter.warning(_function.location(), "Interface functions are implicitly \"virtual\"");
if (_function.isPayable()) if (_function.isPayable())
{ {
if (isLibraryFunction) if (isLibraryFunction)

View File

@ -604,13 +604,15 @@ public:
ASTPointer<ASTString> const& _name, ASTPointer<ASTString> const& _name,
Declaration::Visibility _visibility, Declaration::Visibility _visibility,
ASTPointer<ParameterList> const& _parameters, ASTPointer<ParameterList> const& _parameters,
bool _isVirtual = false,
ASTPointer<OverrideSpecifier> const& _overrides = nullptr, ASTPointer<OverrideSpecifier> const& _overrides = nullptr,
ASTPointer<ParameterList> const& _returnParameters = ASTPointer<ParameterList>() ASTPointer<ParameterList> const& _returnParameters = ASTPointer<ParameterList>()
): ):
Declaration(_location, _name, _visibility), Declaration(_location, _name, _visibility),
m_parameters(_parameters), m_parameters(_parameters),
m_overrides(_overrides), m_overrides(_overrides),
m_returnParameters(_returnParameters) m_returnParameters(_returnParameters),
m_isVirtual(_isVirtual)
{ {
} }
@ -619,11 +621,14 @@ public:
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); } std::vector<ASTPointer<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); }
ParameterList const& parameterList() const { return *m_parameters; } ParameterList const& parameterList() const { return *m_parameters; }
ASTPointer<ParameterList> const& returnParameterList() const { return m_returnParameters; } ASTPointer<ParameterList> const& returnParameterList() const { return m_returnParameters; }
bool markedVirtual() const { return m_isVirtual; }
virtual bool virtualSemantics() const { return markedVirtual(); }
protected: protected:
ASTPointer<ParameterList> m_parameters; ASTPointer<ParameterList> m_parameters;
ASTPointer<OverrideSpecifier> m_overrides; ASTPointer<OverrideSpecifier> m_overrides;
ASTPointer<ParameterList> m_returnParameters; ASTPointer<ParameterList> m_returnParameters;
bool m_isVirtual = false;
}; };
/** /**
@ -661,6 +666,7 @@ public:
Declaration::Visibility _visibility, Declaration::Visibility _visibility,
StateMutability _stateMutability, StateMutability _stateMutability,
Token _kind, Token _kind,
bool _isVirtual,
ASTPointer<OverrideSpecifier> const& _overrides, ASTPointer<OverrideSpecifier> const& _overrides,
ASTPointer<ASTString> const& _documentation, ASTPointer<ASTString> const& _documentation,
ASTPointer<ParameterList> const& _parameters, ASTPointer<ParameterList> const& _parameters,
@ -668,7 +674,7 @@ public:
ASTPointer<ParameterList> const& _returnParameters, ASTPointer<ParameterList> const& _returnParameters,
ASTPointer<Block> const& _body ASTPointer<Block> const& _body
): ):
CallableDeclaration(_location, _name, _visibility, _parameters, _overrides, _returnParameters), CallableDeclaration(_location, _name, _visibility, _parameters, _isVirtual, _overrides, _returnParameters),
Documented(_documentation), Documented(_documentation),
ImplementationOptional(_body != nullptr), ImplementationOptional(_body != nullptr),
m_stateMutability(_stateMutability), m_stateMutability(_stateMutability),
@ -688,7 +694,6 @@ public:
bool isFallback() const { return m_kind == Token::Fallback; } bool isFallback() const { return m_kind == Token::Fallback; }
bool isReceive() const { return m_kind == Token::Receive; } bool isReceive() const { return m_kind == Token::Receive; }
Token kind() const { return m_kind; } Token kind() const { return m_kind; }
bool isOverridable() const { return !isConstructor(); }
bool isPayable() const { return m_stateMutability == StateMutability::Payable; } bool isPayable() const { return m_stateMutability == StateMutability::Payable; }
std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; } std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; }
Block const& body() const { solAssert(m_body, ""); return *m_body; } Block const& body() const { solAssert(m_body, ""); return *m_body; }
@ -713,6 +718,12 @@ public:
FunctionDefinitionAnnotation& annotation() const override; FunctionDefinitionAnnotation& annotation() const override;
bool virtualSemantics() const override
{
return
CallableDeclaration::virtualSemantics() ||
annotation().contract->isInterface();
}
private: private:
StateMutability m_stateMutability; StateMutability m_stateMutability;
Token const m_kind; Token const m_kind;
@ -750,6 +761,7 @@ public:
m_overrides(_overrides), m_overrides(_overrides),
m_location(_referenceLocation) {} m_location(_referenceLocation) {}
void accept(ASTVisitor& _visitor) override; void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override; void accept(ASTConstVisitor& _visitor) const override;
@ -811,11 +823,11 @@ private:
/// Initially assigned value, can be missing. For local variables, this is stored inside /// Initially assigned value, can be missing. For local variables, this is stored inside
/// VariableDeclarationStatement and not here. /// VariableDeclarationStatement and not here.
ASTPointer<Expression> m_value; ASTPointer<Expression> m_value;
bool m_isStateVariable; ///< Whether or not this is a contract state variable bool m_isStateVariable = false; ///< Whether or not this is a contract state variable
bool m_isIndexed; ///< Whether this is an indexed variable (used by events). bool m_isIndexed = false; ///< Whether this is an indexed variable (used by events).
bool m_isConstant; ///< Whether the variable is a compile-time constant. bool m_isConstant = false; ///< Whether the variable is a compile-time constant.
ASTPointer<OverrideSpecifier> m_overrides; ///< Contains the override specifier node ASTPointer<OverrideSpecifier> m_overrides; ///< Contains the override specifier node
Location m_location; ///< Location of the variable if it is of reference type. Location m_location = Location::Unspecified; ///< Location of the variable if it is of reference type.
}; };
/** /**
@ -829,10 +841,11 @@ public:
ASTPointer<ASTString> const& _name, ASTPointer<ASTString> const& _name,
ASTPointer<ASTString> const& _documentation, ASTPointer<ASTString> const& _documentation,
ASTPointer<ParameterList> const& _parameters, ASTPointer<ParameterList> const& _parameters,
bool _isVirtual,
ASTPointer<OverrideSpecifier> const& _overrides, ASTPointer<OverrideSpecifier> const& _overrides,
ASTPointer<Block> const& _body ASTPointer<Block> const& _body
): ):
CallableDeclaration(_location, _name, Visibility::Internal, _parameters, _overrides), CallableDeclaration(_location, _name, Visibility::Internal, _parameters, _isVirtual, _overrides),
Documented(_documentation), Documented(_documentation),
m_body(_body) m_body(_body)
{ {

View File

@ -466,8 +466,6 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari
RecursionGuard recursionGuard(*this); RecursionGuard recursionGuard(*this);
FunctionHeaderParserResult result; FunctionHeaderParserResult result;
result.overrides = nullptr;
VarDeclParserOptions options; VarDeclParserOptions options;
options.allowLocationSpecifier = true; options.allowLocationSpecifier = true;
result.parameters = parseParameterList(options); result.parameters = parseParameterList(options);
@ -515,6 +513,14 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari
result.overrides = parseOverrideSpecifier(); result.overrides = parseOverrideSpecifier();
} }
else if (!_isStateVariable && token == Token::Virtual)
{
if (result.isVirtual)
parserError("Virtual already specified.");
result.isVirtual = true;
m_scanner->next();
}
else else
break; break;
} }
@ -591,6 +597,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinition()
header.visibility, header.visibility,
header.stateMutability, header.stateMutability,
kind, kind,
header.isVirtual,
header.overrides, header.overrides,
docstring, docstring,
header.parameters, header.parameters,
@ -804,13 +811,32 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
parameters = createEmptyParameterList(); parameters = createEmptyParameterList();
ASTPointer<OverrideSpecifier> overrides; ASTPointer<OverrideSpecifier> overrides;
bool isVirtual = false;
while (true)
{
if (m_scanner->currentToken() == Token::Override)
{
if (overrides)
parserError("Override already specified.");
overrides = parseOverrideSpecifier();
}
else if (m_scanner->currentToken() == Token::Virtual)
{
if (isVirtual)
parserError("Virtual already specified.");
isVirtual = true;
m_scanner->next();
}
else
break;
}
if (m_scanner->currentToken() == Token::Override)
overrides = parseOverrideSpecifier();
ASTPointer<Block> block = parseBlock(); ASTPointer<Block> block = parseBlock();
nodeFactory.setEndPositionFromNode(block); nodeFactory.setEndPositionFromNode(block);
return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, overrides, block); return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, isVirtual, overrides, block);
} }
ASTPointer<EventDefinition> Parser::parseEventDefinition() ASTPointer<EventDefinition> Parser::parseEventDefinition()

View File

@ -70,6 +70,7 @@ private:
/// This struct is shared for parsing a function header and a function type. /// This struct is shared for parsing a function header and a function type.
struct FunctionHeaderParserResult struct FunctionHeaderParserResult
{ {
bool isVirtual = false;
ASTPointer<OverrideSpecifier> overrides; ASTPointer<OverrideSpecifier> overrides;
ASTPointer<ParameterList> parameters; ASTPointer<ParameterList> parameters;
ASTPointer<ParameterList> returnParameters; ASTPointer<ParameterList> returnParameters;

View File

@ -221,6 +221,7 @@ contract MultiSigWallet {
/// @dev Allows anyone to execute a confirmed transaction. /// @dev Allows anyone to execute a confirmed transaction.
/// @param transactionId Transaction ID. /// @param transactionId Transaction ID.
function executeTransaction(uint transactionId) function executeTransaction(uint transactionId)
virtual
public public
notExecuted(transactionId) notExecuted(transactionId)
{ {

View File

@ -51,7 +51,7 @@ contract module {
moduleHandlerAddress = newModuleHandlerAddress; moduleHandlerAddress = newModuleHandlerAddress;
} }
function connectModule() external onlyForModuleHandler returns (bool success) { function connectModule() virtual external onlyForModuleHandler returns (bool success) {
_connectModule(); _connectModule();
return true; return true;
} }
@ -77,7 +77,7 @@ contract module {
moduleStatus = status.Disconnected; moduleStatus = status.Disconnected;
} }
function replaceModule(address payable newModuleAddress) external onlyForModuleHandler returns (bool success) { function replaceModule(address payable newModuleAddress) virtual external onlyForModuleHandler returns (bool success) {
_replaceModule(newModuleAddress); _replaceModule(newModuleAddress);
return true; return true;
} }
@ -101,10 +101,11 @@ contract module {
moduleStatus = status.Disconnected; moduleStatus = status.Disconnected;
} }
function transferEvent(address payable from, address payable to, uint256 value) external onlyForModuleHandler returns (bool success) { function transferEvent(address payable from, address payable to, uint256
value) virtual external onlyForModuleHandler returns (bool success) {
return true; return true;
} }
function newSchellingRoundEvent(uint256 roundID, uint256 reward) external onlyForModuleHandler returns (bool success) { function newSchellingRoundEvent(uint256 roundID, uint256 reward) virtual external onlyForModuleHandler returns (bool success) {
return true; return true;
} }

View File

@ -120,9 +120,9 @@ abstract contract Event {
/// @dev Calculates and returns event hash /// @dev Calculates and returns event hash
/// @return Event hash /// @return Event hash
function getEventHash() public view returns (bytes32); function getEventHash() virtual public view returns (bytes32);
/// @dev Exchanges sender's winning outcome tokens for collateral tokens /// @dev Exchanges sender's winning outcome tokens for collateral tokens
/// @return Sender's winnings /// @return Sender's winnings
function redeemWinnings() public returns (uint); function redeemWinnings() virtual public returns (uint);
} }

View File

@ -8,7 +8,7 @@ abstract contract MarketMaker {
/* /*
* Public functions * Public functions
*/ */
function calcCost(Market market, uint8 outcomeTokenIndex, uint outcomeTokenCount) public view returns (uint); function calcCost(Market market, uint8 outcomeTokenIndex, uint outcomeTokenCount) virtual public view returns (uint);
function calcProfit(Market market, uint8 outcomeTokenIndex, uint outcomeTokenCount) public view returns (uint); function calcProfit(Market market, uint8 outcomeTokenIndex, uint outcomeTokenCount) virtual public view returns (uint);
function calcMarginalPrice(Market market, uint8 outcomeTokenIndex) public view returns (uint); function calcMarginalPrice(Market market, uint8 outcomeTokenIndex) virtual public view returns (uint);
} }

View File

@ -37,11 +37,11 @@ abstract contract Market {
/* /*
* Public functions * Public functions
*/ */
function fund(uint _funding) public; function fund(uint _funding) virtual public;
function close() public; function close() virtual public;
function withdrawFees() public returns (uint); function withdrawFees() virtual public returns (uint);
function buy(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint maxCost) public returns (uint); function buy(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint maxCost) virtual public returns (uint);
function sell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit) public returns (uint); function sell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit) virtual public returns (uint);
function shortSell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit) public returns (uint); function shortSell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit) virtual public returns (uint);
function calcMarketFee(uint outcomeTokenCost) public view returns (uint); function calcMarketFee(uint outcomeTokenCost) virtual public view returns (uint);
} }

View File

@ -15,5 +15,6 @@ abstract contract MarketFactory {
/* /*
* Public functions * Public functions
*/ */
function createMarket(Event eventContract, MarketMaker marketMaker, uint24 fee) public returns (Market); function createMarket(Event eventContract, MarketMaker marketMaker, uint24
fee) virtual public returns (Market);
} }

View File

@ -4,6 +4,6 @@ pragma solidity >=0.0;
/// @title Abstract oracle contract - Functions to be implemented by oracles /// @title Abstract oracle contract - Functions to be implemented by oracles
abstract contract Oracle { abstract contract Oracle {
function isOutcomeSet() public view returns (bool); function isOutcomeSet() virtual public view returns (bool);
function getOutcome() public view returns (int); function getOutcome() virtual public view returns (int);
} }

View File

@ -14,10 +14,10 @@ abstract contract Token {
/* /*
* Public functions * Public functions
*/ */
function transfer(address to, uint value) public returns (bool); function transfer(address to, uint value) virtual public returns (bool);
function transferFrom(address from, address to, uint value) public returns (bool); function transferFrom(address from, address to, uint value) virtual public returns (bool);
function approve(address spender, uint value) public returns (bool); function approve(address spender, uint value) virtual public returns (bool);
function balanceOf(address owner) public view returns (uint); function balanceOf(address owner) virtual public view returns (uint);
function allowance(address owner, address spender) public view returns (uint); function allowance(address owner, address spender) virtual public view returns (uint);
function totalSupply() public view returns (uint); function totalSupply() virtual public view returns (uint);
} }

View File

@ -177,6 +177,7 @@ library Math {
/// @param nums Numbers to look through /// @param nums Numbers to look through
/// @return max Maximum number /// @return max Maximum number
function max(int[] memory nums) function max(int[] memory nums)
virtual
public public
pure pure
returns (int max) returns (int max)

View File

@ -46,20 +46,20 @@ static char const* registrarCode = R"DELIMITER(
pragma solidity >=0.4.0 <0.7.0; pragma solidity >=0.4.0 <0.7.0;
abstract contract NameRegister { abstract contract NameRegister {
function addr(string memory _name) public view returns (address o_owner); function addr(string memory _name) public virtual view returns (address o_owner);
function name(address _owner) public view returns (string memory o_name); function name(address _owner) public view virtual returns (string memory o_name);
} }
abstract contract Registrar is NameRegister { abstract contract Registrar is NameRegister {
event Changed(string indexed name); event Changed(string indexed name);
event PrimaryChanged(string indexed name, address indexed addr); event PrimaryChanged(string indexed name, address indexed addr);
function owner(string memory _name) public view returns (address o_owner); function owner(string memory _name) public view virtual returns (address o_owner);
function addr(string memory _name) public override view returns (address o_address); function addr(string memory _name) public virtual override view returns (address o_address);
function subRegistrar(string memory _name) public view returns (address o_subRegistrar); function subRegistrar(string memory _name) public virtual view returns (address o_subRegistrar);
function content(string memory _name) public view returns (bytes32 o_content); function content(string memory _name) public virtual view returns (bytes32 o_content);
function name(address _owner) public override view returns (string memory o_name); function name(address _owner) public virtual override view returns (string memory o_name);
} }
abstract contract AuctionSystem { abstract contract AuctionSystem {
@ -67,7 +67,7 @@ abstract contract AuctionSystem {
event NewBid(string indexed _name, address _bidder, uint _value); event NewBid(string indexed _name, address _bidder, uint _value);
/// Function that is called once an auction ends. /// Function that is called once an auction ends.
function onAuctionEnd(string memory _name) internal; function onAuctionEnd(string memory _name) internal virtual;
function bid(string memory _name, address payable _bidder, uint _value) internal { function bid(string memory _name, address payable _bidder, uint _value) internal {
Auction storage auction = m_auctions[_name]; Auction storage auction = m_auctions[_name];

View File

@ -58,10 +58,10 @@ pragma solidity >=0.4.0 <0.7.0;
abstract contract Registrar { abstract contract Registrar {
event Changed(string indexed name); event Changed(string indexed name);
function owner(string memory _name) public view returns (address o_owner); function owner(string memory _name) public virtual view returns (address o_owner);
function addr(string memory _name) public view returns (address o_address); function addr(string memory _name) public virtual view returns (address o_address);
function subRegistrar(string memory _name) public view returns (address o_subRegistrar); function subRegistrar(string memory _name) virtual public view returns (address o_subRegistrar);
function content(string memory _name) public view returns (bytes32 o_content); function content(string memory _name) public virtual view returns (bytes32 o_content);
} }
contract FixedFeeRegistrar is Registrar { contract FixedFeeRegistrar is Registrar {

View File

@ -128,7 +128,7 @@ contract multiowned {
} }
// Replaces an owner `_from` with another `_to`. // Replaces an owner `_from` with another `_to`.
function changeOwner(address _from, address _to) onlymanyowners(keccak256(msg.data)) public { function changeOwner(address _from, address _to) onlymanyowners(keccak256(msg.data)) public virtual {
if (isOwner(_to)) return; if (isOwner(_to)) return;
uint ownerIndex = m_ownerIndex[uint(_from)]; uint ownerIndex = m_ownerIndex[uint(_from)];
if (ownerIndex == 0) return; if (ownerIndex == 0) return;
@ -248,7 +248,7 @@ contract multiowned {
} }
} }
function clearPending() internal { function clearPending() internal virtual {
uint length = m_pendingIndex.length; uint length = m_pendingIndex.length;
for (uint i = 0; i < length; ++i) for (uint i = 0; i < length; ++i)
if (m_pendingIndex[i] != 0) if (m_pendingIndex[i] != 0)
@ -347,9 +347,9 @@ abstract contract multisig {
// FUNCTIONS // FUNCTIONS
// TODO: document // TODO: document
function changeOwner(address _from, address _to) public; function changeOwner(address _from, address _to) public virtual;
function execute(address _to, uint _value, bytes calldata _data) external returns (bytes32); function execute(address _to, uint _value, bytes calldata _data) external virtual returns (bytes32);
function confirm(bytes32 _h) public returns (bool); function confirm(bytes32 _h) public virtual returns (bool);
} }
// usage: // usage:

View File

@ -174,14 +174,14 @@ abstract contract DAOInterface {
// ); // );
/// @notice Create Token with `msg.sender` as the beneficiary /// @notice Create Token with `msg.sender` as the beneficiary
receive() external payable; receive() virtual external payable;
/// @dev This function is used to send ether back /// @dev This function is used to send ether back
/// to the DAO, it can also be used to receive payments that should not be /// to the DAO, it can also be used to receive payments that should not be
/// counted as rewards (donations, grants, etc.) /// counted as rewards (donations, grants, etc.)
/// @return Whether the DAO received the ether successfully /// @return Whether the DAO received the ether successfully
function receiveEther() public returns (bool); function receiveEther() public virtual returns (bool);
/// @notice `msg.sender` creates a proposal to send `_amount` Wei to /// @notice `msg.sender` creates a proposal to send `_amount` Wei to
/// `_recipient` with the transaction data `_transactionData`. If /// `_recipient` with the transaction data `_transactionData`. If
@ -203,7 +203,7 @@ abstract contract DAOInterface {
bytes memory _transactionData, bytes memory _transactionData,
uint _debatingPeriod, uint _debatingPeriod,
bool _newCurator bool _newCurator
) public payable returns (uint _proposalID); ) public virtual payable returns (uint _proposalID);
/// @notice Check that the proposal with the ID `_proposalID` matches the /// @notice Check that the proposal with the ID `_proposalID` matches the
/// transaction which sends `_amount` with data `_transactionData` /// transaction which sends `_amount` with data `_transactionData`
@ -218,7 +218,7 @@ abstract contract DAOInterface {
address payable _recipient, address payable _recipient,
uint _amount, uint _amount,
bytes memory _transactionData bytes memory _transactionData
) public view returns (bool _codeChecksOut); ) public virtual view returns (bool _codeChecksOut);
/// @notice Vote on proposal `_proposalID` with `_supportsProposal` /// @notice Vote on proposal `_proposalID` with `_supportsProposal`
/// @param _proposalID The proposal ID /// @param _proposalID The proposal ID
@ -227,7 +227,7 @@ abstract contract DAOInterface {
function vote( function vote(
uint _proposalID, uint _proposalID,
bool _supportsProposal bool _supportsProposal
) public returns (uint _voteID); ) public virtual returns (uint _voteID);
/// @notice Checks whether proposal `_proposalID` with transaction data /// @notice Checks whether proposal `_proposalID` with transaction data
/// `_transactionData` has been voted for or rejected, and executes the /// `_transactionData` has been voted for or rejected, and executes the
@ -238,7 +238,7 @@ abstract contract DAOInterface {
function executeProposal( function executeProposal(
uint _proposalID, uint _proposalID,
bytes memory _transactionData bytes memory _transactionData
) public returns (bool _success); ) public virtual returns (bool _success);
/// @notice ATTENTION! I confirm to move my remaining ether to a new DAO /// @notice ATTENTION! I confirm to move my remaining ether to a new DAO
/// with `_newCurator` as the new Curator, as has been /// with `_newCurator` as the new Curator, as has been
@ -254,13 +254,13 @@ abstract contract DAOInterface {
function splitDAO( function splitDAO(
uint _proposalID, uint _proposalID,
address payable _newCurator address payable _newCurator
) public returns (bool _success); ) public virtual returns (bool _success);
/// @dev can only be called by the DAO itself through a proposal /// @dev can only be called by the DAO itself through a proposal
/// updates the contract of the DAO by sending all ether and rewardTokens /// updates the contract of the DAO by sending all ether and rewardTokens
/// to the new DAO. The new DAO needs to be approved by the Curator /// to the new DAO. The new DAO needs to be approved by the Curator
/// @param _newContract the address of the new contract /// @param _newContract the address of the new contract
function newContract(address payable _newContract) public; function newContract(address payable _newContract) virtual public;
/// @notice Add a new possible recipient `_recipient` to the whitelist so /// @notice Add a new possible recipient `_recipient` to the whitelist so
@ -268,36 +268,36 @@ abstract contract DAOInterface {
/// @param _recipient New recipient address /// @param _recipient New recipient address
/// @dev Can only be called by the current Curator /// @dev Can only be called by the current Curator
/// @return Whether successful or not /// @return Whether successful or not
function changeAllowedRecipients(address _recipient, bool _allowed) external returns (bool _success); function changeAllowedRecipients(address _recipient, bool _allowed) virtual external returns (bool _success);
/// @notice Change the minimum deposit required to submit a proposal /// @notice Change the minimum deposit required to submit a proposal
/// @param _proposalDeposit The new proposal deposit /// @param _proposalDeposit The new proposal deposit
/// @dev Can only be called by this DAO (through proposals with the /// @dev Can only be called by this DAO (through proposals with the
/// recipient being this DAO itself) /// recipient being this DAO itself)
function changeProposalDeposit(uint _proposalDeposit) external; function changeProposalDeposit(uint _proposalDeposit) virtual external;
/// @notice Move rewards from the DAORewards managed account /// @notice Move rewards from the DAORewards managed account
/// @param _toMembers If true rewards are moved to the actual reward account /// @param _toMembers If true rewards are moved to the actual reward account
/// for the DAO. If not then it's moved to the DAO itself /// for the DAO. If not then it's moved to the DAO itself
/// @return Whether the call was successful /// @return Whether the call was successful
function retrieveDAOReward(bool _toMembers) external returns (bool _success); function retrieveDAOReward(bool _toMembers) virtual external returns (bool _success);
/// @notice Get my portion of the reward that was sent to `rewardAccount` /// @notice Get my portion of the reward that was sent to `rewardAccount`
/// @return Whether the call was successful /// @return Whether the call was successful
function getMyReward() public returns (bool _success); function getMyReward() public virtual returns (bool _success);
/// @notice Withdraw `_account`'s portion of the reward from `rewardAccount` /// @notice Withdraw `_account`'s portion of the reward from `rewardAccount`
/// to `_account`'s balance /// to `_account`'s balance
/// @return Whether the call was successful /// @return Whether the call was successful
function withdrawRewardFor(address payable _account) internal returns (bool _success); function withdrawRewardFor(address payable _account) internal virtual returns (bool _success);
/// @notice Send `_amount` tokens to `_to` from `msg.sender`. Prior to this /// @notice Send `_amount` tokens to `_to` from `msg.sender`. Prior to this
/// getMyReward() is called. /// getMyReward() is called.
/// @param _to The address of the recipient /// @param _to The address of the recipient
/// @param _amount The amount of tokens to be transferred /// @param _amount The amount of tokens to be transferred
/// @return Whether the transfer was successful or not /// @return Whether the transfer was successful or not
function transferWithoutReward(address _to, uint256 _amount) public returns (bool success); function transferWithoutReward(address _to, uint256 _amount) public virtual returns (bool success);
/// @notice Send `_amount` tokens to `_to` from `_from` on the condition it /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
/// is approved by `_from`. Prior to this getMyReward() is called. /// is approved by `_from`. Prior to this getMyReward() is called.
@ -309,28 +309,28 @@ abstract contract DAOInterface {
address payable _from, address payable _from,
address _to, address _to,
uint256 _amount uint256 _amount
) public returns (bool success); ) public virtual returns (bool success);
/// @notice Doubles the 'minQuorumDivisor' in the case quorum has not been /// @notice Doubles the 'minQuorumDivisor' in the case quorum has not been
/// achieved in 52 weeks /// achieved in 52 weeks
/// @return Whether the change was successful or not /// @return Whether the change was successful or not
function halveMinQuorum() public returns (bool _success); function halveMinQuorum() public virtual returns (bool _success);
/// @return total number of proposals ever created /// @return total number of proposals ever created
function numberOfProposals() public view returns (uint _numberOfProposals); function numberOfProposals() public virtual view returns (uint _numberOfProposals);
/// @param _proposalID Id of the new curator proposal /// @param _proposalID Id of the new curator proposal
/// @return Address of the new DAO /// @return Address of the new DAO
function getNewDAOAddress(uint _proposalID) public view returns (address _newDAO); function getNewDAOAddress(uint _proposalID) public virtual view returns (address _newDAO);
/// @param _account The address of the account which is checked. /// @param _account The address of the account which is checked.
/// @return Whether the account is blocked (not allowed to transfer tokens) or not. /// @return Whether the account is blocked (not allowed to transfer tokens) or not.
function isBlocked(address _account) internal returns (bool); function isBlocked(address _account) internal virtual returns (bool);
/// @notice If the caller is blocked by a proposal whose voting deadline /// @notice If the caller is blocked by a proposal whose voting deadline
/// has exprired then unblock him. /// has exprired then unblock him.
/// @return Whether the account is blocked (not allowed to transfer tokens) or not. /// @return Whether the account is blocked (not allowed to transfer tokens) or not.
function unblockMe() public returns (bool); function unblockMe() public virtual returns (bool);
event ProposalAdded( event ProposalAdded(
uint indexed proposalID, uint indexed proposalID,

View File

@ -33,7 +33,7 @@ abstract contract ManagedAccountInterface {
/// @param _amount The amount of wei to send to `_recipient` /// @param _amount The amount of wei to send to `_recipient`
/// @param _recipient The address to receive `_amount` of wei /// @param _recipient The address to receive `_amount` of wei
/// @return True if the send completed /// @return True if the send completed
function payOut(address payable _recipient, uint _amount) public returns (bool); function payOut(address payable _recipient, uint _amount) public virtual returns (bool);
event PayOut(address indexed _recipient, uint _amount); event PayOut(address indexed _recipient, uint _amount);
} }

View File

@ -45,13 +45,13 @@ abstract contract TokenInterface {
/// @param _owner The address from which the balance will be retrieved /// @param _owner The address from which the balance will be retrieved
/// @return balance The balance /// @return balance The balance
function balanceOf(address _owner) public view returns (uint256 balance); function balanceOf(address _owner) public virtual view returns (uint256 balance);
/// @notice Send `_amount` tokens to `_to` from `msg.sender` /// @notice Send `_amount` tokens to `_to` from `msg.sender`
/// @param _to The address of the recipient /// @param _to The address of the recipient
/// @param _amount The amount of tokens to be transferred /// @param _amount The amount of tokens to be transferred
/// @return success Whether the transfer was successful or not /// @return success Whether the transfer was successful or not
function transfer(address _to, uint256 _amount) public returns (bool success); function transfer(address _to, uint256 _amount) public virtual returns (bool success);
/// @notice Send `_amount` tokens to `_to` from `_from` on the condition it /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
/// is approved by `_from` /// is approved by `_from`
@ -59,14 +59,15 @@ abstract contract TokenInterface {
/// @param _to The address of the recipient /// @param _to The address of the recipient
/// @param _amount The amount of tokens to be transferred /// @param _amount The amount of tokens to be transferred
/// @return success Whether the transfer was successful or not /// @return success Whether the transfer was successful or not
function transferFrom(address _from, address _to, uint256 _amount) public returns (bool success); function transferFrom(address _from, address _to, uint256 _amount) public
virtual returns (bool success);
/// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
/// its behalf /// its behalf
/// @param _spender The address of the account able to transfer the tokens /// @param _spender The address of the account able to transfer the tokens
/// @param _amount The amount of tokens to be approved for transfer /// @param _amount The amount of tokens to be approved for transfer
/// @return success Whether the approval was successful or not /// @return success Whether the approval was successful or not
function approve(address _spender, uint256 _amount) public returns (bool success); function approve(address _spender, uint256 _amount) public virtual returns (bool success);
/// @param _owner The address of the account owning tokens /// @param _owner The address of the account owning tokens
/// @param _spender The address of the account able to transfer the tokens /// @param _spender The address of the account able to transfer the tokens
@ -75,7 +76,7 @@ abstract contract TokenInterface {
function allowance( function allowance(
address _owner, address _owner,
address _spender address _spender
) public view returns (uint256 remaining); ) public virtual view returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _amount); event Transfer(address indexed _from, address indexed _to, uint256 _amount);
event Approval( event Approval(
@ -98,7 +99,7 @@ contract Token is TokenInterface {
return balances[_owner]; return balances[_owner];
} }
function transfer(address _to, uint256 _amount) public override returns (bool success) { function transfer(address _to, uint256 _amount) public virtual override returns (bool success) {
if (balances[msg.sender] >= _amount && _amount > 0) { if (balances[msg.sender] >= _amount && _amount > 0) {
balances[msg.sender] -= _amount; balances[msg.sender] -= _amount;
balances[_to] += _amount; balances[_to] += _amount;
@ -113,7 +114,7 @@ contract Token is TokenInterface {
address _from, address _from,
address _to, address _to,
uint256 _amount uint256 _amount
) public override returns (bool success) { ) public virtual override returns (bool success) {
if (balances[_from] >= _amount if (balances[_from] >= _amount
&& allowed[_from][msg.sender] >= _amount && allowed[_from][msg.sender] >= _amount

View File

@ -65,15 +65,15 @@ abstract contract TokenCreationInterface {
/// @notice Create Token with `_tokenHolder` as the initial owner of the Token /// @notice Create Token with `_tokenHolder` as the initial owner of the Token
/// @param _tokenHolder The address of the Tokens's recipient /// @param _tokenHolder The address of the Tokens's recipient
/// @return Whether the token creation was successful /// @return Whether the token creation was successful
function createTokenProxy(address payable _tokenHolder) payable public returns (bool success); function createTokenProxy(address payable _tokenHolder) payable virtual public returns (bool success);
/// @notice Refund `msg.sender` in the case the Token Creation did /// @notice Refund `msg.sender` in the case the Token Creation did
/// not reach its minimum fueling goal /// not reach its minimum fueling goal
function refund() public; function refund() virtual public;
/// @return The divisor used to calculate the token creation rate during /// @return The divisor used to calculate the token creation rate during
/// the creation phase /// the creation phase
function divisor() public view returns (uint divisor); function divisor() public virtual view returns (uint divisor);
event FuelingToDate(uint value); event FuelingToDate(uint value);
event CreatedToken(address indexed to, uint amount); event CreatedToken(address indexed to, uint amount);
@ -151,6 +151,6 @@ override returns (bool success) {
return 30; return 30;
} }
} }
receive() external payable { receive() external virtual payable {
} }
} }

View File

@ -212,14 +212,14 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports)
char const* sourceCodeA = R"( char const* sourceCodeA = R"(
pragma solidity >=0.0; pragma solidity >=0.0;
contract A { contract A {
function g(function(uint) external returns (uint) x) public {} function g(function(uint) external returns (uint) x) public virtual {}
} }
)"; )";
char const* sourceCodeB = R"( char const* sourceCodeB = R"(
pragma solidity >=0.0; pragma solidity >=0.0;
import "./A"; import "./A";
contract B is A { contract B is A {
function g(function(uint) external returns (uint) x) public override {} function g(function(uint) external returns (uint) x) public virtual override {}
} }
)"; )";
char const* sourceCodeC = R"( char const* sourceCodeC = R"(

View File

@ -2110,7 +2110,7 @@ BOOST_AUTO_TEST_CASE(virtual_function_calls)
char const* sourceCode = R"( char const* sourceCode = R"(
contract Base { contract Base {
function f() public returns (uint i) { return g(); } function f() public returns (uint i) { return g(); }
function g() public returns (uint i) { return 1; } function g() public virtual returns (uint i) { return 1; }
} }
contract Derived is Base { contract Derived is Base {
function g() public override returns (uint i) { return 2; } function g() public override returns (uint i) { return 2; }
@ -2174,8 +2174,8 @@ BOOST_AUTO_TEST_CASE(single_copy_with_multiple_inheritance)
BOOST_AUTO_TEST_CASE(explicit_base_class) BOOST_AUTO_TEST_CASE(explicit_base_class)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract BaseBase { function g() public returns (uint r) { return 1; } } contract BaseBase { function g() public virtual returns (uint r) { return 1; } }
contract Base is BaseBase { function g() public override returns (uint r) { return 2; } } contract Base is BaseBase { function g() public virtual override returns (uint r) { return 2; } }
contract Derived is Base { contract Derived is Base {
function f() public returns (uint r) { return BaseBase.g(); } function f() public returns (uint r) { return BaseBase.g(); }
function g() public override returns (uint r) { return 3; } function g() public override returns (uint r) { return 3; }
@ -2236,7 +2236,7 @@ BOOST_AUTO_TEST_CASE(virtual_function_usage_in_constructor_arguments)
constructor(uint a) public { constructor(uint a) public {
m_a = a; m_a = a;
} }
function overridden() public returns (uint r) { return 1; } function overridden() public virtual returns (uint r) { return 1; }
function g() public returns (uint r) { return overridden(); } function g() public returns (uint r) { return overridden(); }
} }
contract Base is BaseBase(BaseBase.g()) { contract Base is BaseBase(BaseBase.g()) {
@ -2350,8 +2350,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_calling_functions_in_creation_context)
constructor() mod1 public { f1(); } constructor() mod1 public { f1(); }
function f1() mod2 public { data |= 0x1; } function f1() mod2 public { data |= 0x1; }
function f2() public { data |= 0x20; } function f2() public { data |= 0x20; }
function f3() public { } function f3() public virtual { }
modifier mod1 { f2(); _; } modifier mod1 virtual { f2(); _; }
modifier mod2 { f3(); if (false) _; } modifier mod2 { f3(); if (false) _; }
function getData() public returns (uint r) { return data; } function getData() public returns (uint r) { return data; }
} }
@ -2482,9 +2482,9 @@ BOOST_AUTO_TEST_CASE(crazy_elementary_typenames_on_stack)
BOOST_AUTO_TEST_CASE(super) BOOST_AUTO_TEST_CASE(super)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract A { function f() public returns (uint r) { return 1; } } contract A { function f() public virtual returns (uint r) { return 1; } }
contract B is A { function f() public override returns (uint r) { return super.f() | 2; } } contract B is A { function f() public virtual override returns (uint r) { return super.f() | 2; } }
contract C is A { function f() public override returns (uint r) { return super.f() | 4; } } contract C is A { function f() public virtual override returns (uint r) { return super.f() | 4; } }
contract D is B, C { function f() public override(B, C) returns (uint r) { return super.f() | 8; } } contract D is B, C { function f() public override(B, C) returns (uint r) { return super.f() | 8; } }
)"; )";
compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "D");
@ -2494,9 +2494,9 @@ BOOST_AUTO_TEST_CASE(super)
BOOST_AUTO_TEST_CASE(super_in_constructor) BOOST_AUTO_TEST_CASE(super_in_constructor)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract A { function f() public returns (uint r) { return 1; } } contract A { function f() public virtual returns (uint r) { return 1; } }
contract B is A { function f() public override returns (uint r) { return super.f() | 2; } } contract B is A { function f() public virtual override returns (uint r) { return super.f() | 2; } }
contract C is A { function f() public override returns (uint r) { return super.f() | 4; } } contract C is A { function f() public virtual override returns (uint r) { return super.f() | 4; } }
contract D is B, C { uint data; constructor() public { data = super.f() | 8; } function f() public override (B, C) returns (uint r) { return data; } } contract D is B, C { uint data; constructor() public { data = super.f() | 8; } function f() public override (B, C) returns (uint r) { return data; } }
)"; )";
compileAndRun(sourceCode, 0, "D"); compileAndRun(sourceCode, 0, "D");
@ -5969,11 +5969,11 @@ BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes)
// bug #1798 // bug #1798
char const* sourceCode = R"( char const* sourceCode = R"(
contract init { contract init {
function isOk() public returns (bool) { return false; } function isOk() public virtual returns (bool) { return false; }
bool public ok = false; bool public ok = false;
} }
contract fix { contract fix {
function isOk() public returns (bool) { return true; } function isOk() public virtual returns (bool) { return true; }
bool public ok = true; bool public ok = true;
} }
@ -7944,7 +7944,7 @@ BOOST_AUTO_TEST_CASE(state_variable_local_variable_mixture)
BOOST_AUTO_TEST_CASE(inherited_function) { BOOST_AUTO_TEST_CASE(inherited_function) {
char const* sourceCode = R"( char const* sourceCode = R"(
contract A { function f() internal returns (uint) { return 1; } } contract A { function f() virtual internal returns (uint) { return 1; } }
contract B is A { contract B is A {
function f() internal override returns (uint) { return 2; } function f() internal override returns (uint) { return 2; }
function g() public returns (uint) { function g() public returns (uint) {
@ -7959,7 +7959,7 @@ BOOST_AUTO_TEST_CASE(inherited_function) {
BOOST_AUTO_TEST_CASE(inherited_function_calldata_memory) { BOOST_AUTO_TEST_CASE(inherited_function_calldata_memory) {
char const* sourceCode = R"( char const* sourceCode = R"(
contract A { function f(uint[] calldata a) external returns (uint) { return a[0]; } } contract A { function f(uint[] calldata a) virtual external returns (uint) { return a[0]; } }
contract B is A { contract B is A {
function f(uint[] memory a) public override returns (uint) { return a[1]; } function f(uint[] memory a) public override returns (uint) { return a[1]; }
function g() public returns (uint) { function g() public returns (uint) {
@ -14439,7 +14439,7 @@ BOOST_AUTO_TEST_CASE(external_public_override)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract A { contract A {
function f() external returns (uint) { return 1; } function f() external virtual returns (uint) { return 1; }
} }
contract B is A { contract B is A {
function f() public override returns (uint) { return 2; } function f() public override returns (uint) { return 2; }
@ -14605,7 +14605,7 @@ BOOST_AUTO_TEST_CASE(contract_name)
string public nameAccessor = type(C).name; string public nameAccessor = type(C).name;
string public constant constantNameAccessor = type(C).name; string public constant constantNameAccessor = type(C).name;
function name() public pure returns (string memory) { function name() public virtual pure returns (string memory) {
return type(C).name; return type(C).name;
} }
} }

View File

@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract)
{ {
SourceUnit const* sourceUnit = nullptr; SourceUnit const* sourceUnit = nullptr;
char const* text = R"( char const* text = R"(
abstract contract base { function foo() public; } abstract contract base { function foo() public virtual; }
contract derived is base { function foo() public override {} } contract derived is base { function foo() public override {} }
)"; )";
sourceUnit = parseAndAnalyse(text); sourceUnit = parseAndAnalyse(text);

View File

@ -118,6 +118,14 @@ while(0)
BOOST_AUTO_TEST_SUITE(SolidityParser) BOOST_AUTO_TEST_SUITE(SolidityParser)
BOOST_AUTO_TEST_CASE(reserved_keywords)
{
BOOST_CHECK(!TokenTraits::isReservedKeyword(Token::Identifier));
BOOST_CHECK(TokenTraits::isReservedKeyword(Token::After));
BOOST_CHECK(TokenTraits::isReservedKeyword(Token::Unchecked));
BOOST_CHECK(!TokenTraits::isReservedKeyword(Token::Illegal));
}
BOOST_AUTO_TEST_CASE(unsatisfied_version) BOOST_AUTO_TEST_CASE(unsatisfied_version)
{ {
char const* text = R"( char const* text = R"(
@ -524,7 +532,6 @@ BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers)
BOOST_AUTO_TEST_CASE(keyword_is_reserved) BOOST_AUTO_TEST_CASE(keyword_is_reserved)
{ {
auto keywords = { auto keywords = {
"abstract",
"after", "after",
"alias", "alias",
"apply", "apply",
@ -560,6 +567,8 @@ BOOST_AUTO_TEST_CASE(keyword_is_reserved)
"unchecked" "unchecked"
}; };
BOOST_CHECK_EQUAL(std::size(keywords), static_cast<int>(Token::Unchecked) - static_cast<int>(Token::After) + 1);
for (auto const& keyword: keywords) for (auto const& keyword: keywords)
{ {
auto text = std::string("contract ") + keyword + " {}"; auto text = std::string("contract ") + keyword + " {}";

View File

@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
// TypeType is tested with contract // TypeType is tested with contract
auto emptyParams = make_shared<ParameterList>(SourceLocation(), std::vector<ASTPointer<VariableDeclaration>>()); auto emptyParams = make_shared<ParameterList>(SourceLocation(), std::vector<ASTPointer<VariableDeclaration>>());
ModifierDefinition mod(SourceLocation{}, make_shared<string>("modif"), {}, emptyParams, {}, {}); ModifierDefinition mod(SourceLocation{}, make_shared<string>("modif"), {}, emptyParams, {}, {}, {});
BOOST_CHECK_EQUAL(ModifierType(mod).identifier(), "t_modifier$__$"); BOOST_CHECK_EQUAL(ModifierType(mod).identifier(), "t_modifier$__$");
SourceUnit su({}, {}); SourceUnit su({}, {});

View File

@ -1,11 +1,11 @@
contract BaseBase { contract BaseBase {
uint public x; uint public x;
uint public y; uint public y;
function init(uint a, uint b) public { function init(uint a, uint b) public virtual {
x = b; x = b;
y = a; y = a;
} }
function init(uint a) public { function init(uint a) public virtual {
x = a + 1; x = a + 1;
} }
} }

View File

@ -2,7 +2,7 @@ contract X {
function f() public returns (uint x) { function f() public returns (uint x) {
x = g(); x = g();
} }
function g() public returns (uint x) { function g() public virtual returns (uint x) {
x = 2; x = 2;
} }
} }

View File

@ -4,7 +4,7 @@ pragma experimental SMTChecker;
contract A { contract A {
uint x; uint x;
fallback () external { fallback () external virtual {
assert(x == 1); assert(x == 1);
} }
function g() public view { function g() public view {
@ -21,7 +21,7 @@ contract B is A {
} }
} }
// ---- // ----
// Warning: (114-128): Assertion violation happens here // Warning: (122-136): Assertion violation happens here
// Warning: (163-177): Assertion violation happens here // Warning: (171-185): Assertion violation happens here
// Warning: (280-294): Assertion violation happens here // Warning: (288-302): Assertion violation happens here
// Warning: (163-177): Assertion violation happens here // Warning: (171-185): Assertion violation happens here

View File

@ -4,7 +4,7 @@ pragma experimental SMTChecker;
contract A { contract A {
uint x; uint x;
function f() public view { function f() public virtual view {
assert(x == 1); assert(x == 1);
} }
function g() public view { function g() public view {
@ -19,7 +19,7 @@ contract B is A {
} }
} }
// ---- // ----
// Warning: (113-127): Assertion violation happens here // Warning: (121-135): Assertion violation happens here
// Warning: (162-176): Assertion violation happens here // Warning: (170-184): Assertion violation happens here
// Warning: (268-282): Assertion violation happens here // Warning: (276-290): Assertion violation happens here
// Warning: (162-176): Assertion violation happens here // Warning: (170-184): Assertion violation happens here

View File

@ -4,7 +4,7 @@ pragma experimental SMTChecker;
contract A { contract A {
uint x; uint x;
function f() public view { function f() public virtual view {
assert(x == 1); assert(x == 1);
} }
function g() public view { function g() public view {
@ -21,7 +21,7 @@ contract B is A {
} }
} }
// ---- // ----
// Warning: (113-127): Assertion violation happens here // Warning: (121-135): Assertion violation happens here
// Warning: (162-176): Assertion violation happens here // Warning: (170-184): Assertion violation happens here
// Warning: (278-292): Assertion violation happens here // Warning: (286-300): Assertion violation happens here
// Warning: (162-176): Assertion violation happens here // Warning: (170-184): Assertion violation happens here

View File

@ -4,7 +4,7 @@ pragma experimental SMTChecker;
contract A { contract A {
uint x; uint x;
function f() public view { function f() public virtual view {
assert(x == 1); assert(x == 1);
} }
function g() public view { function g() public view {
@ -16,7 +16,7 @@ contract A {
contract B is A { contract B is A {
uint y; uint y;
function f() public view override { function f() public view virtual override {
assert(x == 0); assert(x == 0);
} }
function h() public view { function h() public view {
@ -36,12 +36,12 @@ contract C is B {
} }
} }
// ---- // ----
// Warning: (113-127): Assertion violation happens here // Warning: (121-135): Assertion violation happens here
// Warning: (162-176): Assertion violation happens here // Warning: (170-184): Assertion violation happens here
// Warning: (280-294): Assertion violation happens here // Warning: (296-310): Assertion violation happens here
// Warning: (329-343): Assertion violation happens here // Warning: (345-359): Assertion violation happens here
// Warning: (162-176): Assertion violation happens here // Warning: (170-184): Assertion violation happens here
// Warning: (452-466): Assertion violation happens here // Warning: (468-482): Assertion violation happens here
// Warning: (501-515): Assertion violation happens here // Warning: (517-531): Assertion violation happens here
// Warning: (329-343): Assertion violation happens here // Warning: (345-359): Assertion violation happens here
// Warning: (162-176): Assertion violation happens here // Warning: (170-184): Assertion violation happens here

View File

@ -4,7 +4,7 @@ pragma experimental SMTChecker;
contract A { contract A {
uint x; uint x;
receive () external payable { receive () external virtual payable {
assert(x == 1); assert(x == 1);
} }
function g() public view { function g() public view {
@ -21,7 +21,7 @@ contract B is A {
} }
} }
// ---- // ----
// Warning: (120-134): Assertion violation happens here // Warning: (128-142): Assertion violation happens here
// Warning: (169-183): Assertion violation happens here // Warning: (177-191): Assertion violation happens here
// Warning: (292-306): Assertion violation happens here // Warning: (300-314): Assertion violation happens here
// Warning: (169-183): Assertion violation happens here // Warning: (177-191): Assertion violation happens here

View File

@ -1,5 +1,5 @@
contract C { contract C {
fallback() external {} fallback() virtual external {}
} }
contract D is C { contract D is C {
fallback() override external {} fallback() override external {}

View File

@ -1,5 +1,5 @@
contract C { contract C {
fallback() external {} fallback() virtual external {}
} }
contract D is C { contract D is C {
} }

View File

@ -1,8 +1,8 @@
contract C { contract C {
fallback() external {} fallback() virtual external {}
} }
contract D is C { contract D is C {
fallback() external {} fallback() external {}
} }
// ---- // ----
// TypeError: (58-80): Overriding function is missing 'override' specifier. // TypeError: (66-88): Overriding function is missing 'override' specifier.

View File

@ -1,5 +1,5 @@
contract C { contract C {
fallback() external {} fallback() virtual external {}
} }
contract D is C { contract D is C {
} }
@ -7,4 +7,4 @@ contract E is D {
fallback() external {} fallback() external {}
} }
// ---- // ----
// TypeError: (78-100): Overriding function is missing 'override' specifier. // TypeError: (86-108): Overriding function is missing 'override' specifier.

View File

@ -1,5 +1,5 @@
contract C { contract C {
receive() external payable {} receive() virtual external payable {}
} }
contract D is C { contract D is C {
receive() override external payable {} receive() override external payable {}

View File

@ -1,5 +1,5 @@
contract C { contract C {
receive() external payable {} receive() virtual external payable {}
} }
contract D is C { contract D is C {
} }

View File

@ -1,8 +1,8 @@
contract C { contract C {
receive() external payable {} receive() virtual external payable {}
} }
contract D is C { contract D is C {
receive() external payable {} receive() external payable {}
} }
// ---- // ----
// TypeError: (65-94): Overriding function is missing 'override' specifier. // TypeError: (73-102): Overriding function is missing 'override' specifier.

View File

@ -1,5 +1,5 @@
contract C { contract C {
receive() external payable {} receive() virtual external payable {}
} }
contract D is C { contract D is C {
} }
@ -7,4 +7,4 @@ contract E is D {
receive() external payable {} receive() external payable {}
} }
// ---- // ----
// TypeError: (85-114): Overriding function is missing 'override' specifier. // TypeError: (93-122): Overriding function is missing 'override' specifier.

View File

@ -0,0 +1,5 @@
interface I {
function foo() virtual external;
}
// ----
// Warning: (15-47): Interface functions are implicitly "virtual"

View File

@ -1,5 +1,5 @@
contract B { function f() public {} } contract B { function f() virtual public {} }
contract C is B { function f() public view {} } contract C is B { function f() public view {} }
// ---- // ----
// TypeError: (56-83): Overriding function is missing 'override' specifier. // TypeError: (64-91): Overriding function is missing 'override' specifier.
// TypeError: (56-83): Overriding function changes state mutability from "nonpayable" to "view". // TypeError: (64-91): Overriding function changes state mutability from "nonpayable" to "view".

View File

@ -1,9 +1,9 @@
contract A { contract A {
uint dummy; uint dummy;
function f(uint[] calldata) external pure {} function f(uint[] calldata) external virtual pure {}
function g(uint[] calldata) external view { dummy; } function g(uint[] calldata) external virtual view { dummy; }
function h(uint[] calldata) external { dummy = 42; } function h(uint[] calldata) external virtual { dummy = 42; }
function i(uint[] calldata) external payable {} function i(uint[] calldata) external virtual payable {}
} }
contract B is A { contract B is A {
function f(uint[] memory) public override pure {} function f(uint[] memory) public override pure {}

View File

@ -1,9 +1,9 @@
contract A { contract A {
uint dummy; uint dummy;
function f(uint[] calldata) external pure {} function f(uint[] calldata) external virtual pure {}
function g(uint[] calldata) external view { dummy; } function g(uint[] calldata) external virtual view { dummy; }
function h(uint[] calldata) external { dummy = 42; } function h(uint[] calldata) external virtual { dummy = 42; }
function i(uint[] calldata) external payable {} function i(uint[] calldata) external virtual payable {}
} }
contract B is A { contract B is A {
function f(uint[] calldata) external override pure {} function f(uint[] calldata) external override pure {}
@ -16,7 +16,7 @@ contract B is A {
function i(uint[] memory) public override payable {} function i(uint[] memory) public override payable {}
} }
// ---- // ----
// DeclarationError: (268-321): Function with same name and arguments defined twice. // DeclarationError: (300-353): Function with same name and arguments defined twice.
// DeclarationError: (326-387): Function with same name and arguments defined twice. // DeclarationError: (358-419): Function with same name and arguments defined twice.
// DeclarationError: (392-453): Function with same name and arguments defined twice. // DeclarationError: (424-485): Function with same name and arguments defined twice.
// DeclarationError: (458-514): Function with same name and arguments defined twice. // DeclarationError: (490-546): Function with same name and arguments defined twice.

View File

@ -2,10 +2,10 @@ pragma experimental ABIEncoderV2;
contract A { contract A {
uint dummy; uint dummy;
struct S { int a; } struct S { int a; }
function f(S calldata) external pure {} function f(S calldata) external virtual pure {}
function g(S calldata) external view { dummy; } function g(S calldata) external virtual view { dummy; }
function h(S calldata) external { dummy = 42; } function h(S calldata) external virtual { dummy = 42; }
function i(S calldata) external payable {} function i(S calldata) external virtual payable {}
} }
contract B is A { contract B is A {
function f(S memory) public override pure {} function f(S memory) public override pure {}

View File

@ -1,5 +1,5 @@
contract A { contract A {
function f() external pure {} function f() external virtual pure {}
} }
contract B is A { contract B is A {
function f() public override pure { function f() public override pure {

View File

@ -0,0 +1,7 @@
contract C {
function() external virtual fp;
function() external override fp2;
function() external override virtual fp3;
}
// ----
// ParserError: (34-41): Expected identifier but got 'virtual'

View File

@ -1,7 +1,7 @@
abstract contract A { abstract contract A {
int public testvar; int public testvar;
function test() internal returns (uint256); function test() internal virtual returns (uint256);
function test2() internal returns (uint256); function test2() internal virtual returns (uint256);
} }
abstract contract X is A { abstract contract X is A {
int public override testvar; int public override testvar;

View File

@ -1,14 +1,14 @@
abstract contract A { abstract contract A {
int public testvar; int public testvar;
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
} }
abstract contract B { abstract contract B {
function foo() internal returns (uint256); function foo() internal returns (uint256);
function test() internal returns (uint256); function test() internal virtual returns (uint256);
} }
abstract contract X is A, B { abstract contract X is A, B {
int public override testvar; int public override testvar;
function test() internal override returns (uint256); function test() internal override returns (uint256);
} }
// ---- // ----
// TypeError: (202-317): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes. // TypeError: (218-333): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes.

View File

@ -1,17 +1,17 @@
abstract contract A { abstract contract A {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
} }
abstract contract B is A { abstract contract B is A {
function foo() internal override returns (uint256); function foo() internal override virtual returns (uint256);
} }
abstract contract C is B { abstract contract C is B {
function foo() internal override returns (uint256); function foo() internal override virtual returns (uint256);
} }
abstract contract D is C { abstract contract D is C {
function foo() internal override returns (uint256); function foo() internal override virtual returns (uint256);
} }
abstract contract X is D { abstract contract X is D {

View File

@ -0,0 +1,9 @@
interface A {
function test() external returns (uint256);
function test2() external returns (uint256);
}
abstract contract X is A {
function test() external override returns (uint256);
function test2() external override(A) returns (uint256);
}
// ----

View File

@ -0,0 +1,14 @@
interface A {
function test() external returns (uint256);
function test2() external returns (uint256);
}
interface B {
function test() external returns (uint256);
function test2() external returns (uint256);
}
abstract contract X is A, B {
function test() external override(A, B) returns (uint256);
function test2() external override(B, A) returns (uint256);
}
// ----

View File

@ -0,0 +1,11 @@
abstract contract A {
function test() external virtual returns (uint256);
function test2() external returns (uint256);
}
abstract contract X is A {
function test() external returns (uint256);
function test2() external override(A) returns (uint256);
}
// ----
// TypeError: (151-194): Overriding function is missing 'override' specifier.
// TypeError: (76-120): Trying to override non-virtual function. Did you forget to add "virtual"?

View File

@ -1,17 +1,17 @@
abstract contract A { abstract contract A {
int public testvar; int public testvar;
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test(uint8 _a) internal returns (uint256); function test(uint8 _a) internal virtual returns (uint256);
} }
abstract contract B { abstract contract B {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test() internal returns (uint256); function test() internal virtual returns (uint256);
} }
abstract contract C { abstract contract C {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
} }
abstract contract D { abstract contract D {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
} }
abstract contract X is A, B, C, D { abstract contract X is A, B, C, D {
int public override testvar; int public override testvar;

View File

@ -1,10 +1,10 @@
abstract contract A { abstract contract A {
int public testvar; int public testvar;
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test(uint8 _a) internal returns (uint256); function test(uint8 _a) internal returns (uint256);
} }
abstract contract B { abstract contract B {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
} }
abstract contract C is A { abstract contract C is A {

View File

@ -1,18 +1,18 @@
abstract contract A { abstract contract A {
int public testvar; int public testvar;
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test(uint8 _a) internal returns (uint256); function test(uint8 _a) internal virtual returns (uint256);
} }
abstract contract B { abstract contract B {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test() internal returns (uint256); function test() internal virtual returns (uint256);
} }
abstract contract C { abstract contract C {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
} }
abstract contract D { abstract contract D {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test() internal returns (uint256); function test() internal virtual returns (uint256);
} }
abstract contract X is A, B, C, D { abstract contract X is A, B, C, D {
int public override testvar; int public override testvar;
@ -20,7 +20,7 @@ abstract contract X is A, B, C, D {
function foo() internal override(A, C, B, B, B, D ,D) returns (uint256); function foo() internal override(A, C, B, B, B, D ,D) returns (uint256);
} }
// ---- // ----
// TypeError: (543-544): Duplicate contract "D" found in override list of "test". // TypeError: (599-600): Duplicate contract "D" found in override list of "test".
// TypeError: (608-609): Duplicate contract "B" found in override list of "foo". // TypeError: (664-665): Duplicate contract "B" found in override list of "foo".
// TypeError: (611-612): Duplicate contract "B" found in override list of "foo". // TypeError: (667-668): Duplicate contract "B" found in override list of "foo".
// TypeError: (617-618): Duplicate contract "D" found in override list of "foo". // TypeError: (673-674): Duplicate contract "D" found in override list of "foo".

View File

@ -1,18 +1,18 @@
abstract contract A { abstract contract A {
int public testvar; int public testvar;
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test(uint8 _a) internal returns (uint256); function test(uint8 _a) virtual internal returns (uint256);
} }
abstract contract B { abstract contract B {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test() internal returns (uint256); function test() internal virtual returns (uint256);
} }
abstract contract C { abstract contract C {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
} }
abstract contract D { abstract contract D {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test() internal returns (uint256); function test() internal virtual returns (uint256);
} }
abstract contract X is A, B, C, D { abstract contract X is A, B, C, D {
int public override testvar; int public override testvar;
@ -20,5 +20,5 @@ abstract contract X is A, B, C, D {
function foo() internal override(A, C) returns (uint256); function foo() internal override(A, C) returns (uint256);
} }
// ---- // ----
// TypeError: (528-545): Invalid contract specified in override list: C. // TypeError: (584-601): Invalid contract specified in override list: C.
// TypeError: (590-604): Function needs to specify overridden contracts B and D. // TypeError: (646-660): Function needs to specify overridden contracts B and D.

View File

@ -0,0 +1,14 @@
contract A
{
function foo() virtual internal {}
}
contract B
{
function foo() internal {}
}
contract C is A, B
{
function foo() internal override(A, B) {}
}
// ----
// TypeError: (65-91): Trying to override non-virtual function. Did you forget to add "virtual"?

View File

@ -0,0 +1,13 @@
contract A
{
function foo() virtual internal {}
}
contract B
{
function foo() internal {}
}
contract C is A, B
{
}
// ----
// TypeError: (94-116): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes.

View File

@ -0,0 +1,7 @@
abstract contract A {
int public testvar;
}
abstract contract X is A {
int public override testvar;
}
// ----

View File

@ -1,14 +1,14 @@
abstract contract A { abstract contract A {
int public testvar; int public testvar;
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
} }
abstract contract B { abstract contract B {
function foo() internal returns (uint8); function foo() internal virtual returns (uint8);
function test() internal returns (uint256); function test() internal virtual returns (uint256);
} }
abstract contract X is A, B { abstract contract X is A, B {
int public override testvar; int public override testvar;
function test() internal override returns (uint256); function test() internal override returns (uint256);
} }
// ---- // ----
// TypeError: (200-315): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes. // TypeError: (224-339): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes.

View File

@ -1,13 +1,13 @@
contract I { contract I {
function set() public {} function set() public virtual {}
} }
contract A is I { contract A is I {
uint a; uint a;
function set() public override { a = 1; super.set(); a = 2; } function set() public virtual override { a = 1; super.set(); a = 2; }
} }
contract B is I { contract B is I {
uint b; uint b;
function set() public override { b = 1; super.set(); b = 2; } function set() public virtual override { b = 1; super.set(); b = 2; }
} }
contract X is A, B { contract X is A, B {

View File

@ -1,8 +1,8 @@
contract I { contract I {
function f() external {} function f() external virtual {}
} }
contract A is I { contract A is I {
function f() external override {} function f() external virtual override {}
} }
contract B is I {} contract B is I {}
contract C is A, B { contract C is A, B {

View File

@ -1,17 +1,17 @@
abstract contract A { abstract contract A {
int public testvar; int public testvar;
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test(uint8 _a) internal returns (uint256); function test(uint8 _a) internal virtual returns (uint256);
} }
abstract contract B { abstract contract B {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
function test() internal returns (uint256); function test() internal virtual returns (uint256);
} }
abstract contract C { abstract contract C {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
} }
abstract contract D { abstract contract D {
function foo() internal returns (uint256); function foo() internal virtual returns (uint256);
} }
abstract contract X is A, B, C, D { abstract contract X is A, B, C, D {
struct MyStruct { int abc; } struct MyStruct { int abc; }
@ -22,5 +22,5 @@ abstract contract X is A, B, C, D {
function foo() internal override(MyStruct, ENUM, A, B, C, D) returns (uint256); function foo() internal override(MyStruct, ENUM, A, B, C, D) returns (uint256);
} }
// ---- // ----
// TypeError: (597-605): Expected contract but got struct X.MyStruct. // TypeError: (645-653): Expected contract but got struct X.MyStruct.
// TypeError: (607-611): Expected contract but got enum X.ENUM. // TypeError: (655-659): Expected contract but got enum X.ENUM.

View File

@ -1,5 +1,5 @@
contract B { function f() public view {} } contract B { function f() virtual public view {} }
contract C is B { function f() public {} } contract C is B { function f() public {} }
// ---- // ----
// TypeError: (61-83): Overriding function is missing 'override' specifier. // TypeError: (69-91): Overriding function is missing 'override' specifier.
// TypeError: (61-83): Overriding function changes state mutability from "view" to "nonpayable". // TypeError: (69-91): Overriding function changes state mutability from "view" to "nonpayable".

View File

@ -1,5 +1,5 @@
contract A { contract A {
function f() external pure {} function f() external virtual pure {}
} }
contract B is A { contract B is A {
function f() public override pure { function f() public override pure {
@ -7,4 +7,4 @@ contract B is A {
} }
} }
// ---- // ----
// TypeError: (115-122): Member "f" not found or not visible after argument-dependent lookup in contract super B. // TypeError: (123-130): Member "f" not found or not visible after argument-dependent lookup in contract super B.

View File

@ -0,0 +1,8 @@
contract C
{
function foo() virtual public virtual {}
modifier modi() virtual virtual {_;}
}
// ----
// ParserError: (44-51): Virtual already specified.
// ParserError: (80-87): Virtual already specified.

View File

@ -0,0 +1,6 @@
contract C
{
function foo() public virtual {}
function foo2() virtual public {}
modifier modi() virtual {_;}
}

View File

@ -1,6 +1,6 @@
abstract contract base { function foo() public; } abstract contract base { function foo() public virtual; }
contract derived is base { function foo() public override {} } contract derived is base { function foo() public virtual override {} }
contract wrong is derived { function foo() public; } contract wrong is derived { function foo() public; }
// ---- // ----
// TypeError: (141-163): Overriding function is missing 'override' specifier. // TypeError: (157-179): Overriding function is missing 'override' specifier.
// TypeError: (141-163): Redeclaring an already implemented function as abstract // TypeError: (157-179): Redeclaring an already implemented function as abstract

View File

@ -1,6 +1,6 @@
contract root { function rootFunction() public {} } contract root { function rootFunction() public {} }
contract inter1 is root { function f() public {} } contract inter1 is root { function f() public virtual {} }
contract inter2 is root { function f() public {} } contract inter2 is root { function f() public virtual {} }
contract derived is root, inter2, inter1 { contract derived is root, inter2, inter1 {
function g() public { f(); rootFunction(); } function g() public { f(); rootFunction(); }
function f() override(inter1, inter2) public {} function f() override(inter1, inter2) public {}

View File

@ -1,5 +1,5 @@
contract B { function f() internal {} } contract B { function f() virtual internal {} }
contract C is B { function f() public {} } contract C is B { function f() public {} }
// ---- // ----
// TypeError: (58-80): Overriding function is missing 'override' specifier. // TypeError: (66-88): Overriding function is missing 'override' specifier.
// TypeError: (58-80): Overriding function visibility differs. // TypeError: (66-88): Overriding function visibility differs.

View File

@ -1,5 +1,5 @@
contract A { function f() public { uint8 x = C(0).g(); } } contract A { function f() public virtual { uint8 x = C(0).g(); } }
contract B { function f() public {} function g() public returns (uint8) {} } contract B { function f() public virtual {} function g() public returns (uint8) {} }
contract C is A, B { function f() public override (A, B) { A.f(); } } contract C is A, B { function f() public override (A, B) { A.f(); } }
// ---- // ----
// Warning: (35-42): Unused local variable. // Warning: (43-50): Unused local variable.

View File

@ -1,6 +1,6 @@
contract A { contract A {
uint x; uint x;
fallback() external { x = 1; } fallback() virtual external { x = 1; }
} }
contract C is A { contract C is A {
fallback() override external { x = 2; } fallback() override external { x = 2; }

View File

@ -1,8 +1,8 @@
contract Vehicle { contract Vehicle {
function f(bytes calldata) external returns (uint256 r) {r = 1;} function f(bytes calldata) external virtual returns (uint256 r) {r = 1;}
} }
contract Bike is Vehicle { contract Bike is Vehicle {
function f(bytes calldata) override external returns (uint256 r) {r = 42;} function f(bytes calldata) override external returns (uint256 r) {r = 42;}
} }
// ---- // ----
// Warning: (23-87): Function state mutability can be restricted to pure // Warning: (23-95): Function state mutability can be restricted to pure

View File

@ -1,8 +1,8 @@
contract base { contract base {
function f(uint a) public returns (uint) { } function f(uint a) public virtual returns (uint) { }
} }
contract test is base { contract test is base {
function f(uint a) public override returns (uint8) { } function f(uint a) public override returns (uint8) { }
} }
// ---- // ----
// TypeError: (95-149): Overriding function return types differ. // TypeError: (103-157): Overriding function return types differ.

View File

@ -1,5 +1,5 @@
contract B { function f() payable public {} } contract B { function f() payable virtual public {} }
contract C is B { function f() public {} } contract C is B { function f() public {} }
// ---- // ----
// TypeError: (64-86): Overriding function is missing 'override' specifier. // TypeError: (72-94): Overriding function is missing 'override' specifier.
// TypeError: (64-86): Overriding function changes state mutability from "payable" to "nonpayable". // TypeError: (72-94): Overriding function changes state mutability from "payable" to "nonpayable".

View File

@ -1,5 +1,5 @@
contract B { function f() public {} } contract B { function f() virtual public {} }
contract C is B { function f() payable public {} } contract C is B { function f() payable public {} }
// ---- // ----
// TypeError: (56-86): Overriding function is missing 'override' specifier. // TypeError: (64-94): Overriding function is missing 'override' specifier.
// TypeError: (56-86): Overriding function changes state mutability from "nonpayable" to "payable". // TypeError: (64-94): Overriding function changes state mutability from "nonpayable" to "payable".

View File

@ -5,3 +5,4 @@ contract C is I {
function f() public override { function f() public override {
} }
} }
// ----

View File

@ -1,8 +1,8 @@
abstract contract a { abstract contract a {
function f() public; function f() virtual public;
} }
contract b is a { contract b is a {
function f() public override { super.f(); } function f() public override { super.f(); }
} }
// ---- // ----
// TypeError: (102-109): Member "f" not found or not visible after argument-dependent lookup in contract super b. // TypeError: (110-117): Member "f" not found or not visible after argument-dependent lookup in contract super b.

View File

@ -1,12 +1,12 @@
abstract contract a { abstract contract a {
function f() public; function f() virtual public;
} }
contract b is a { contract b is a {
function f() public override { super.f(); } function f() public virtual override { super.f(); }
} }
contract c is a,b { contract c is a,b {
// No error here. // No error here.
function f() public override(a, b) { super.f(); } function f() public override(a, b) { super.f(); }
} }
// ---- // ----
// TypeError: (102-109): Member "f" not found or not visible after argument-dependent lookup in contract super b. // TypeError: (118-125): Member "f" not found or not visible after argument-dependent lookup in contract super b.

View File

@ -4,3 +4,4 @@ interface D {
contract C is D { contract C is D {
function f() override view external {} function f() override view external {}
} }
// ----

View File

@ -1,16 +1,16 @@
contract D { contract D {
uint x; uint x;
function f() public view { x; } function f() public virtual view { x; }
function g() public pure {} function g() public virtual pure {}
} }
contract C1 is D { contract C1 is D {
function f() public override {} function f() public override {}
function g() public override view {} function g() public virtual override view {}
} }
contract C2 is D { contract C2 is D {
function g() public override {} function g() public override {}
} }
// ---- // ----
// TypeError: (118-149): Overriding function changes state mutability from "view" to "nonpayable". // TypeError: (134-165): Overriding function changes state mutability from "view" to "nonpayable".
// TypeError: (154-190): Overriding function changes state mutability from "pure" to "view". // TypeError: (170-214): Overriding function changes state mutability from "pure" to "view".
// TypeError: (216-247): Overriding function changes state mutability from "pure" to "nonpayable". // TypeError: (240-271): Overriding function changes state mutability from "pure" to "nonpayable".

View File

@ -1,6 +1,6 @@
contract D { contract D {
uint x; uint x;
function f() public { x = 2; } function f() virtual public { x = 2; }
} }
contract C is D { contract C is D {
function f() public override {} function f() public override {}