Implement virtual keyword

This commit is contained in:
Mathias Baumann 2019-11-05 18:25:34 +01:00
parent 7d4e4b6088
commit 5b8ff78176
88 changed files with 395 additions and 314 deletions

View File

@ -19,16 +19,13 @@ Breaking changes:
* 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.
* 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:
* Allow global enums and structs.
* Allow underscores as delimiters in hex strings.
* Allow explicit conversions from ``address`` to ``address payable`` via ``payable(...)``.
* 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 ``virtual`` and ``override`` keywords
* 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.

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
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
=======================
@ -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.
* 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
============

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;
abstract contract Feline {
function utterance() public returns (bytes32);
function utterance() public virtual returns (bytes32);
}
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
// accessed externally via `this`, though.
contract Mortal is Owned {
function kill() public {
function kill() virtual public {
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.
// Both local and message-based function calls take these overrides
// into account.
function kill() public override {
function kill() public virtual override {
if (msg.sender == owner) {
Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
NameReg(config.lookup(1)).unregister();
@ -115,17 +115,17 @@ seen in the following example::
}
contract mortal is owned {
function kill() public {
function kill() public virtual {
if (msg.sender == owner) selfdestruct(owner);
}
}
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 {
function kill() public override { /* do cleanup 2 */ mortal.kill(); }
function kill() public virtual override { /* do cleanup 2 */ mortal.kill(); }
}
contract Final is Base1, Base2 {
@ -144,18 +144,18 @@ explicitly in the final override, but this function will bypass
}
contract mortal is owned {
function kill() public {
function kill() virtual public {
if (msg.sender == owner) selfdestruct(owner);
}
}
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 {
function kill() public override { /* do cleanup 2 */ super.kill(); }
function kill() public virtual override { /* do cleanup 2 */ super.kill(); }
}
contract Final is Base1, Base2 {
@ -190,7 +190,7 @@ function header as shown in this example:
contract Base
{
function foo() public {}
function foo() virtual public {}
}
contract Middle is Base {}
@ -212,12 +212,12 @@ bases, it has to explicitly override it:
contract Base1
{
function foo() public {}
function foo() virtual public {}
}
contract Base2
{
function foo() public {}
function foo() virtual public {}
}
contract Inherited is Base1, Base2

View File

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

View File

@ -245,15 +245,14 @@ void ContractLevelChecker::checkIllegalOverrides(ContractDefinition const& _cont
for (FunctionDefinition const* function: _contract.definedFunctions())
{
if (function->isConstructor())
continue;
if (contains_if(modSet, MatchByName{function->name()}))
m_errorReporter.typeError(function->location(), "Override changes modifier to function.");
// Skip if not overridable
if (!function->isOverridable())
continue;
// No inheriting functions found
if (funcSet.find(function) == funcSet.cend() && function->overrides())
if (!funcSet.count(function) && function->overrides())
m_errorReporter.typeError(
function->overrides()->location(),
"Function has override specified but does not override anything."
@ -279,6 +278,12 @@ bool ContractLevelChecker::checkFunctionOverride(FunctionDefinition const& _func
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))
{
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(
function.location(),
SecondarySourceLocation().append("Overridden function is here:", super.location()),
SecondarySourceLocation().append(secondaryMsg, super.location()),
message
);
}
@ -653,10 +658,10 @@ void ContractLevelChecker::checkAmbiguousOverrides(ContractDefinition const& _co
continue;
// Not an overridable function
if (!(*it)->isOverridable())
if ((*it)->isConstructor())
{
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;
}
@ -785,8 +790,7 @@ void ContractLevelChecker::checkOverrideList(FunctionMultiSet const& _funcSet, F
for (auto [begin, end] = _funcSet.equal_range(&_function); begin != end; begin++)
{
// Validate the override
if (!checkFunctionOverride(_function, **begin))
break;
checkFunctionOverride(_function, **begin);
expectedContracts.insert((*begin)->annotation().contract);
}

View File

@ -75,7 +75,7 @@ private:
/// Also stores the direct super function in the AST annotations.
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 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);
/// Checks that the base constructor arguments are properly provided.
/// 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;
if (_function.markedVirtual() && _function.annotation().contract->isInterface())
m_errorReporter.warning(_function.location(), "Interface functions are implicitly \"virtual\"");
if (_function.isPayable())
{
if (isLibraryFunction)

View File

@ -621,12 +621,14 @@ public:
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); }
ParameterList const& parameterList() const { return *m_parameters; }
ASTPointer<ParameterList> const& returnParameterList() const { return m_returnParameters; }
bool markedVirtual() const { return m_isVirtual; }
virtual bool virtualSemantics() const { return markedVirtual(); }
protected:
ASTPointer<ParameterList> m_parameters;
ASTPointer<OverrideSpecifier> m_overrides;
ASTPointer<ParameterList> m_returnParameters;
bool m_isVirtual;
bool m_isVirtual = false;
};
/**
@ -692,7 +694,6 @@ public:
bool isFallback() const { return m_kind == Token::Fallback; }
bool isReceive() const { return m_kind == Token::Receive; }
Token kind() const { return m_kind; }
bool isOverridable() const { return !isConstructor(); }
bool isPayable() const { return m_stateMutability == StateMutability::Payable; }
std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; }
Block const& body() const { solAssert(m_body, ""); return *m_body; }
@ -717,6 +718,12 @@ public:
FunctionDefinitionAnnotation& annotation() const override;
bool virtualSemantics() const override
{
return
CallableDeclaration::virtualSemantics() ||
annotation().contract->isInterface();
}
private:
StateMutability m_stateMutability;
Token const m_kind;
@ -742,7 +749,6 @@ public:
bool _isStateVar = false,
bool _isIndexed = false,
bool _isConstant = false,
bool _isVirtual = false,
ASTPointer<OverrideSpecifier> const& _overrides = nullptr,
Location _referenceLocation = Location::Unspecified
):
@ -752,7 +758,6 @@ public:
m_isStateVariable(_isStateVar),
m_isIndexed(_isIndexed),
m_isConstant(_isConstant),
m_isVirtual(_isVirtual),
m_overrides(_overrides),
m_location(_referenceLocation) {}
@ -798,7 +803,6 @@ public:
bool isIndexed() const { return m_isIndexed; }
bool isConstant() const { return m_isConstant; }
ASTPointer<OverrideSpecifier> const& overrides() const { return m_overrides; }
bool isVirtual() const { return m_isVirtual; }
Location referenceLocation() const { return m_location; }
/// @returns a set of allowed storage locations for the variable.
std::set<Location> allowedDataLocations() const;
@ -819,12 +823,11 @@ private:
/// Initially assigned value, can be missing. For local variables, this is stored inside
/// VariableDeclarationStatement and not here.
ASTPointer<Expression> m_value;
bool m_isStateVariable; ///< Whether or not this is a contract state variable
bool m_isIndexed; ///< Whether this is an indexed variable (used by events).
bool m_isConstant; ///< Whether the variable is a compile-time constant.
bool m_isVirtual; ///< Whether the variable is virtual and can be overridden
bool m_isStateVariable = false; ///< Whether or not this is a contract state variable
bool m_isIndexed = false; ///< Whether this is an indexed variable (used by events).
bool m_isConstant = false; ///< Whether the variable is a compile-time constant.
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.
};
/**

View File

@ -466,9 +466,6 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _isStateVari
RecursionGuard recursionGuard(*this);
FunctionHeaderParserResult result;
result.isVirtual = false;
result.overrides = nullptr;
VarDeclParserOptions options;
options.allowLocationSpecifier = true;
result.parameters = parseParameterList(options);
@ -689,7 +686,6 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
bool isIndexed = false;
bool isDeclaredConst = false;
bool isVirtual = false;
ASTPointer<OverrideSpecifier> overrides = nullptr;
Declaration::Visibility visibility(Declaration::Visibility::Default);
VariableDeclaration::Location location = VariableDeclaration::Location::Unspecified;
@ -720,14 +716,6 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
overrides = parseOverrideSpecifier();
}
else if (_options.isStateVariable && token == Token::Virtual)
{
if (isVirtual)
parserError("Virtual already specified.");
isVirtual = true;
m_scanner->next();
}
else
{
if (_options.allowIndexed && token == Token::Indexed)
@ -793,7 +781,6 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
_options.isStateVariable,
isIndexed,
isDeclaredConst,
isVirtual,
overrides,
location
);
@ -826,7 +813,7 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
ASTPointer<OverrideSpecifier> overrides;
bool isVirtual = false;
while(true)
while (true)
{
if (m_scanner->currentToken() == Token::Override)
{

View File

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

View File

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

View File

@ -51,7 +51,7 @@ contract module {
moduleHandlerAddress = newModuleHandlerAddress;
}
function connectModule() external onlyForModuleHandler returns (bool success) {
function connectModule() virtual external onlyForModuleHandler returns (bool success) {
_connectModule();
return true;
}
@ -77,7 +77,7 @@ contract module {
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);
return true;
}
@ -101,10 +101,11 @@ contract module {
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;
}
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;
}

View File

@ -120,9 +120,9 @@ abstract contract Event {
/// @dev Calculates and returns 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
/// @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
*/
function calcCost(Market market, uint8 outcomeTokenIndex, uint outcomeTokenCount) public view returns (uint);
function calcProfit(Market market, uint8 outcomeTokenIndex, uint outcomeTokenCount) public view returns (uint);
function calcMarginalPrice(Market market, uint8 outcomeTokenIndex) 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) virtual 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
*/
function fund(uint _funding) public;
function close() public;
function withdrawFees() public returns (uint);
function buy(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint maxCost) public returns (uint);
function sell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit) public returns (uint);
function shortSell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit) public returns (uint);
function calcMarketFee(uint outcomeTokenCost) public view returns (uint);
function fund(uint _funding) virtual public;
function close() virtual public;
function withdrawFees() virtual public returns (uint);
function buy(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint maxCost) virtual public returns (uint);
function sell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit) virtual public returns (uint);
function shortSell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit) virtual public returns (uint);
function calcMarketFee(uint outcomeTokenCost) virtual public view returns (uint);
}

View File

@ -15,5 +15,6 @@ abstract contract MarketFactory {
/*
* 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
abstract contract Oracle {
function isOutcomeSet() public view returns (bool);
function getOutcome() public view returns (int);
function isOutcomeSet() virtual public view returns (bool);
function getOutcome() virtual public view returns (int);
}

View File

@ -14,10 +14,10 @@ abstract contract Token {
/*
* Public functions
*/
function transfer(address to, uint value) public returns (bool);
function transferFrom(address from, address to, uint value) public returns (bool);
function approve(address spender, uint value) public returns (bool);
function balanceOf(address owner) public view returns (uint);
function allowance(address owner, address spender) public view returns (uint);
function totalSupply() public view returns (uint);
function transfer(address to, uint value) virtual public returns (bool);
function transferFrom(address from, address to, uint value) virtual public returns (bool);
function approve(address spender, uint value) virtual public returns (bool);
function balanceOf(address owner) virtual public view returns (uint);
function allowance(address owner, address spender) virtual 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
/// @return max Maximum number
function max(int[] memory nums)
virtual
public
pure
returns (int max)

View File

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

View File

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

View File

@ -128,7 +128,7 @@ contract multiowned {
}
// 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;
uint ownerIndex = m_ownerIndex[uint(_from)];
if (ownerIndex == 0) return;
@ -248,7 +248,7 @@ contract multiowned {
}
}
function clearPending() internal {
function clearPending() internal virtual {
uint length = m_pendingIndex.length;
for (uint i = 0; i < length; ++i)
if (m_pendingIndex[i] != 0)
@ -347,9 +347,9 @@ abstract contract multisig {
// FUNCTIONS
// TODO: document
function changeOwner(address _from, address _to) public;
function execute(address _to, uint _value, bytes calldata _data) external returns (bytes32);
function confirm(bytes32 _h) public returns (bool);
function changeOwner(address _from, address _to) public virtual;
function execute(address _to, uint _value, bytes calldata _data) external virtual returns (bytes32);
function confirm(bytes32 _h) public virtual returns (bool);
}
// usage:

View File

@ -174,14 +174,14 @@ abstract contract DAOInterface {
// );
/// @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
/// to the DAO, it can also be used to receive payments that should not be
/// counted as rewards (donations, grants, etc.)
/// @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
/// `_recipient` with the transaction data `_transactionData`. If
@ -203,7 +203,7 @@ abstract contract DAOInterface {
bytes memory _transactionData,
uint _debatingPeriod,
bool _newCurator
) public payable returns (uint _proposalID);
) public virtual payable returns (uint _proposalID);
/// @notice Check that the proposal with the ID `_proposalID` matches the
/// transaction which sends `_amount` with data `_transactionData`
@ -218,7 +218,7 @@ abstract contract DAOInterface {
address payable _recipient,
uint _amount,
bytes memory _transactionData
) public view returns (bool _codeChecksOut);
) public virtual view returns (bool _codeChecksOut);
/// @notice Vote on proposal `_proposalID` with `_supportsProposal`
/// @param _proposalID The proposal ID
@ -227,7 +227,7 @@ abstract contract DAOInterface {
function vote(
uint _proposalID,
bool _supportsProposal
) public returns (uint _voteID);
) public virtual returns (uint _voteID);
/// @notice Checks whether proposal `_proposalID` with transaction data
/// `_transactionData` has been voted for or rejected, and executes the
@ -238,7 +238,7 @@ abstract contract DAOInterface {
function executeProposal(
uint _proposalID,
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
/// with `_newCurator` as the new Curator, as has been
@ -254,13 +254,13 @@ abstract contract DAOInterface {
function splitDAO(
uint _proposalID,
address payable _newCurator
) public returns (bool _success);
) public virtual returns (bool _success);
/// @dev can only be called by the DAO itself through a proposal
/// 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
/// @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
@ -268,36 +268,36 @@ abstract contract DAOInterface {
/// @param _recipient New recipient address
/// @dev Can only be called by the current Curator
/// @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
/// @param _proposalDeposit The new proposal deposit
/// @dev Can only be called by this DAO (through proposals with the
/// recipient being this DAO itself)
function changeProposalDeposit(uint _proposalDeposit) external;
function changeProposalDeposit(uint _proposalDeposit) virtual external;
/// @notice Move rewards from the DAORewards managed 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
/// @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`
/// @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`
/// to `_account`'s balance
/// @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
/// getMyReward() is called.
/// @param _to The address of the recipient
/// @param _amount The amount of tokens to be transferred
/// @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
/// is approved by `_from`. Prior to this getMyReward() is called.
@ -309,28 +309,28 @@ abstract contract DAOInterface {
address payable _from,
address _to,
uint256 _amount
) public returns (bool success);
) public virtual returns (bool success);
/// @notice Doubles the 'minQuorumDivisor' in the case quorum has not been
/// achieved in 52 weeks
/// @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
function numberOfProposals() public view returns (uint _numberOfProposals);
function numberOfProposals() public virtual view returns (uint _numberOfProposals);
/// @param _proposalID Id of the new curator proposal
/// @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.
/// @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
/// has exprired then unblock him.
/// @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(
uint indexed proposalID,

View File

@ -33,7 +33,7 @@ abstract contract ManagedAccountInterface {
/// @param _amount The amount of wei to send to `_recipient`
/// @param _recipient The address to receive `_amount` of wei
/// @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);
}

View File

@ -45,13 +45,13 @@ abstract contract TokenInterface {
/// @param _owner The address from which the balance will be retrieved
/// @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`
/// @param _to The address of the recipient
/// @param _amount The amount of tokens to be transferred
/// @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
/// is approved by `_from`
@ -59,14 +59,15 @@ abstract contract TokenInterface {
/// @param _to The address of the recipient
/// @param _amount The amount of tokens to be transferred
/// @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
/// its behalf
/// @param _spender The address of the account able to transfer the tokens
/// @param _amount The amount of tokens to be approved for transfer
/// @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 _spender The address of the account able to transfer the tokens
@ -75,7 +76,7 @@ abstract contract TokenInterface {
function allowance(
address _owner,
address _spender
) public view returns (uint256 remaining);
) public virtual view returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _amount);
event Approval(
@ -98,7 +99,7 @@ contract Token is TokenInterface {
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) {
balances[msg.sender] -= _amount;
balances[_to] += _amount;
@ -113,7 +114,7 @@ contract Token is TokenInterface {
address _from,
address _to,
uint256 _amount
) public override returns (bool success) {
) public virtual override returns (bool success) {
if (balances[_from] >= _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
/// @param _tokenHolder The address of the Tokens's recipient
/// @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
/// not reach its minimum fueling goal
function refund() public;
function refund() virtual public;
/// @return The divisor used to calculate the token creation rate during
/// the creation phase
function divisor() public view returns (uint divisor);
function divisor() public virtual view returns (uint divisor);
event FuelingToDate(uint value);
event CreatedToken(address indexed to, uint amount);
@ -151,6 +151,6 @@ override returns (bool success) {
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"(
pragma solidity >=0.0;
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"(
pragma solidity >=0.0;
import "./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"(

View File

@ -2110,7 +2110,7 @@ BOOST_AUTO_TEST_CASE(virtual_function_calls)
char const* sourceCode = R"(
contract Base {
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 {
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)
{
char const* sourceCode = R"(
contract BaseBase { function g() public returns (uint r) { return 1; } }
contract Base is BaseBase { function g() public override returns (uint r) { return 2; } }
contract BaseBase { function g() public virtual returns (uint r) { return 1; } }
contract Base is BaseBase { function g() public virtual override returns (uint r) { return 2; } }
contract Derived is Base {
function f() public returns (uint r) { return BaseBase.g(); }
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 {
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(); }
}
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(); }
function f1() mod2 public { data |= 0x1; }
function f2() public { data |= 0x20; }
function f3() public { }
modifier mod1 { f2(); _; }
function f3() public virtual { }
modifier mod1 virtual { f2(); _; }
modifier mod2 { f3(); if (false) _; }
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)
{
char const* sourceCode = R"(
contract A { function f() public returns (uint r) { return 1; } }
contract B is A { function f() public override returns (uint r) { return super.f() | 2; } }
contract C is A { function f() public override returns (uint r) { return super.f() | 4; } }
contract A { function f() public virtual returns (uint r) { return 1; } }
contract B is A { function f() public virtual override returns (uint r) { return super.f() | 2; } }
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; } }
)";
compileAndRun(sourceCode, 0, "D");
@ -2494,9 +2494,9 @@ BOOST_AUTO_TEST_CASE(super)
BOOST_AUTO_TEST_CASE(super_in_constructor)
{
char const* sourceCode = R"(
contract A { function f() public returns (uint r) { return 1; } }
contract B is A { function f() public override returns (uint r) { return super.f() | 2; } }
contract C is A { function f() public override returns (uint r) { return super.f() | 4; } }
contract A { function f() public virtual returns (uint r) { return 1; } }
contract B is A { function f() public virtual override returns (uint r) { return super.f() | 2; } }
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; } }
)";
compileAndRun(sourceCode, 0, "D");
@ -5969,11 +5969,11 @@ BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes)
// bug #1798
char const* sourceCode = R"(
contract init {
function isOk() public returns (bool) { return false; }
function isOk() public virtual returns (bool) { return false; }
bool public ok = false;
}
contract fix {
function isOk() public returns (bool) { return true; }
function isOk() public virtual returns (bool) { return true; }
bool public ok = true;
}
@ -7944,7 +7944,7 @@ BOOST_AUTO_TEST_CASE(state_variable_local_variable_mixture)
BOOST_AUTO_TEST_CASE(inherited_function) {
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 {
function f() internal override returns (uint) { return 2; }
function g() public returns (uint) {
@ -7959,7 +7959,7 @@ BOOST_AUTO_TEST_CASE(inherited_function) {
BOOST_AUTO_TEST_CASE(inherited_function_calldata_memory) {
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 {
function f(uint[] memory a) public override returns (uint) { return a[1]; }
function g() public returns (uint) {
@ -14439,7 +14439,7 @@ BOOST_AUTO_TEST_CASE(external_public_override)
{
char const* sourceCode = R"(
contract A {
function f() external returns (uint) { return 1; }
function f() external virtual returns (uint) { return 1; }
}
contract B is A {
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 constant constantNameAccessor = type(C).name;
function name() public pure returns (string memory) {
function name() public virtual pure returns (string memory) {
return type(C).name;
}
}

View File

@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract)
{
SourceUnit const* sourceUnit = nullptr;
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 {} }
)";
sourceUnit = parseAndAnalyse(text);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
contract C {
fallback() external {}
fallback() virtual external {}
}
contract D is C {
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 {
fallback() external {}
fallback() virtual external {}
}
contract D is C {
}
@ -7,4 +7,4 @@ contract E is D {
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 {
receive() external payable {}
receive() virtual external payable {}
}
contract D is C {
receive() override external payable {}

View File

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

View File

@ -1,8 +1,8 @@
contract C {
receive() external payable {}
receive() virtual external payable {}
}
contract D is C {
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 {
receive() external payable {}
receive() virtual external payable {}
}
contract D is C {
}
@ -7,4 +7,4 @@ contract E is D {
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 {} }
// ----
// TypeError: (56-83): Overriding function is missing 'override' specifier.
// TypeError: (56-83): Overriding function changes state mutability from "nonpayable" to "view".
// TypeError: (64-91): Overriding function is missing 'override' specifier.
// TypeError: (64-91): Overriding function changes state mutability from "nonpayable" to "view".

View File

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

View File

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

View File

@ -1,5 +1,5 @@
contract A {
function f() external pure {}
function f() external virtual pure {}
}
contract B is A {
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 {
int public testvar;
function test() internal returns (uint256);
function test2() internal returns (uint256);
function test() internal virtual returns (uint256);
function test2() internal virtual returns (uint256);
}
abstract contract X is A {
int public override testvar;

View File

@ -1,14 +1,14 @@
abstract contract A {
int public testvar;
function foo() internal returns (uint256);
function foo() internal virtual returns (uint256);
}
abstract contract B {
function foo() internal returns (uint256);
function test() internal returns (uint256);
function test() internal virtual returns (uint256);
}
abstract contract X is A, B {
int public override testvar;
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 {
function foo() internal returns (uint256);
function foo() internal virtual returns (uint256);
}
abstract contract B is A {
function foo() internal override returns (uint256);
function foo() internal override virtual returns (uint256);
}
abstract contract C is B {
function foo() internal override returns (uint256);
function foo() internal override virtual returns (uint256);
}
abstract contract D is C {
function foo() internal override returns (uint256);
function foo() internal override virtual returns (uint256);
}
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 {
int public testvar;
function foo() internal returns (uint256);
function test(uint8 _a) internal returns (uint256);
function foo() internal virtual returns (uint256);
function test(uint8 _a) internal virtual returns (uint256);
}
abstract contract B {
function foo() internal returns (uint256);
function test() internal returns (uint256);
function foo() internal virtual returns (uint256);
function test() internal virtual returns (uint256);
}
abstract contract C {
function foo() internal returns (uint256);
function foo() internal virtual returns (uint256);
}
abstract contract D {
function foo() internal returns (uint256);
function foo() internal virtual returns (uint256);
}
abstract contract X is A, B, C, D {
int public override testvar;

View File

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

View File

@ -1,18 +1,18 @@
abstract contract A {
int public testvar;
function foo() internal returns (uint256);
function test(uint8 _a) internal returns (uint256);
function foo() internal virtual returns (uint256);
function test(uint8 _a) internal virtual returns (uint256);
}
abstract contract B {
function foo() internal returns (uint256);
function test() internal returns (uint256);
function foo() internal virtual returns (uint256);
function test() internal virtual returns (uint256);
}
abstract contract C {
function foo() internal returns (uint256);
function foo() internal virtual returns (uint256);
}
abstract contract D {
function foo() internal returns (uint256);
function test() internal returns (uint256);
function foo() internal virtual returns (uint256);
function test() internal virtual returns (uint256);
}
abstract contract X is A, B, C, D {
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);
}
// ----
// TypeError: (543-544): Duplicate contract "D" found in override list of "test".
// TypeError: (608-609): Duplicate contract "B" found in override list of "foo".
// TypeError: (611-612): Duplicate contract "B" found in override list of "foo".
// TypeError: (617-618): Duplicate contract "D" found in override list of "foo".
// TypeError: (599-600): Duplicate contract "D" found in override list of "test".
// TypeError: (664-665): Duplicate contract "B" found in override list of "foo".
// TypeError: (667-668): Duplicate contract "B" 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 {
int public testvar;
function foo() internal returns (uint256);
function test(uint8 _a) internal returns (uint256);
function foo() internal virtual returns (uint256);
function test(uint8 _a) virtual internal returns (uint256);
}
abstract contract B {
function foo() internal returns (uint256);
function test() internal returns (uint256);
function foo() internal virtual returns (uint256);
function test() internal virtual returns (uint256);
}
abstract contract C {
function foo() internal returns (uint256);
function foo() internal virtual returns (uint256);
}
abstract contract D {
function foo() internal returns (uint256);
function test() internal returns (uint256);
function foo() internal virtual returns (uint256);
function test() internal virtual returns (uint256);
}
abstract contract X is A, B, C, D {
int public override testvar;
@ -20,5 +20,5 @@ abstract contract X is A, B, C, D {
function foo() internal override(A, C) returns (uint256);
}
// ----
// TypeError: (528-545): Invalid contract specified in override list: C.
// TypeError: (590-604): Function needs to specify overridden contracts B and D.
// TypeError: (584-601): Invalid contract specified in override list: C.
// 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 {
int public testvar;
function foo() internal returns (uint256);
function foo() internal virtual returns (uint256);
}
abstract contract B {
function foo() internal returns (uint8);
function test() internal returns (uint256);
function foo() internal virtual returns (uint8);
function test() internal virtual returns (uint256);
}
abstract contract X is A, B {
int public override testvar;
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 {
function set() public {}
function set() public virtual {}
}
contract A is I {
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 {
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 {

View File

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

View File

@ -1,17 +1,17 @@
abstract contract A {
int public testvar;
function foo() internal returns (uint256);
function test(uint8 _a) internal returns (uint256);
function foo() internal virtual returns (uint256);
function test(uint8 _a) internal virtual returns (uint256);
}
abstract contract B {
function foo() internal returns (uint256);
function test() internal returns (uint256);
function foo() internal virtual returns (uint256);
function test() internal virtual returns (uint256);
}
abstract contract C {
function foo() internal returns (uint256);
function foo() internal virtual returns (uint256);
}
abstract contract D {
function foo() internal returns (uint256);
function foo() internal virtual returns (uint256);
}
abstract contract X is A, B, C, D {
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);
}
// ----
// TypeError: (597-605): Expected contract but got struct X.MyStruct.
// TypeError: (607-611): Expected contract but got enum X.ENUM.
// TypeError: (645-653): Expected contract but got struct X.MyStruct.
// 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 {} }
// ----
// TypeError: (61-83): Overriding function is missing 'override' specifier.
// TypeError: (61-83): Overriding function changes state mutability from "view" to "nonpayable".
// TypeError: (69-91): Overriding function is missing 'override' specifier.
// TypeError: (69-91): Overriding function changes state mutability from "view" to "nonpayable".

View File

@ -1,5 +1,5 @@
contract A {
function f() external pure {}
function f() external virtual pure {}
}
contract B is A {
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

@ -2,9 +2,7 @@ contract C
{
function foo() virtual public virtual {}
modifier modi() virtual virtual {_;}
int virtual public virtual variable;
}
// ----
// ParserError: (44-51): Virtual already specified.
// ParserError: (80-87): Virtual already specified.
// ParserError: (113-120): Virtual already specified.

View File

@ -3,6 +3,4 @@ contract C
function foo() public virtual {}
function foo2() virtual public {}
modifier modi() virtual {_;}
int public virtual variable;
int virtual public variable2;
}

View File

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

View File

@ -1,6 +1,6 @@
contract root { function rootFunction() public {} }
contract inter1 is root { function f() public {} }
contract inter2 is root { function f() public {} }
contract inter1 is root { function f() public virtual {} }
contract inter2 is root { function f() public virtual {} }
contract derived is root, inter2, inter1 {
function g() public { f(); rootFunction(); }
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 {} }
// ----
// TypeError: (58-80): Overriding function is missing 'override' specifier.
// TypeError: (58-80): Overriding function visibility differs.
// TypeError: (66-88): Overriding function is missing 'override' specifier.
// TypeError: (66-88): Overriding function visibility differs.

View File

@ -1,5 +1,5 @@
contract A { function f() public { uint8 x = C(0).g(); } }
contract B { function f() public {} function g() public returns (uint8) {} }
contract A { function f() public virtual { uint8 x = C(0).g(); } }
contract B { function f() public virtual {} function g() public returns (uint8) {} }
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 {
uint x;
fallback() external { x = 1; }
fallback() virtual external { x = 1; }
}
contract C is A {
fallback() override external { x = 2; }

View File

@ -1,8 +1,8 @@
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 {
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 {
function f(uint a) public returns (uint) { }
function f(uint a) public virtual returns (uint) { }
}
contract test is base {
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 {} }
// ----
// TypeError: (64-86): Overriding function is missing 'override' specifier.
// TypeError: (64-86): Overriding function changes state mutability from "payable" to "nonpayable".
// TypeError: (72-94): Overriding function is missing 'override' specifier.
// 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 {} }
// ----
// TypeError: (56-86): Overriding function is missing 'override' specifier.
// TypeError: (56-86): Overriding function changes state mutability from "nonpayable" to "payable".
// TypeError: (64-94): Overriding function is missing 'override' specifier.
// 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 {
}
}
// ----

View File

@ -1,8 +1,8 @@
abstract contract a {
function f() public;
function f() virtual public;
}
contract b is a {
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 {
function f() public;
function f() virtual public;
}
contract b is a {
function f() public override { super.f(); }
function f() public virtual override { super.f(); }
}
contract c is a,b {
// No error here.
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 {
function f() override view external {}
}
// ----

View File

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

View File

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