mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #7563 from ethereum/override-rewrite-5424
Implement override keyword
This commit is contained in:
commit
49e8093e06
@ -12,6 +12,7 @@ Breaking changes:
|
||||
* Syntax: ``push(element)`` for dynamic storage arrays do not return the new length anymore.
|
||||
* Inline Assembly: Only strict inline assembly is allowed.
|
||||
* Type checker: Resulting type of exponentiation is equal to the type of the base. Also allow signed types for the base.
|
||||
* 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.
|
||||
|
@ -23,7 +23,7 @@ Such contracts cannot be compiled (even if they contain implemented functions al
|
||||
}
|
||||
|
||||
contract Cat is Feline {
|
||||
function utterance() public returns (bytes32) { return "miaow"; }
|
||||
function utterance() public override returns (bytes32) { return "miaow"; }
|
||||
}
|
||||
|
||||
If a contract inherits from an abstract contract and does not implement all non-implemented functions by overriding, it will itself be abstract.
|
||||
|
@ -10,6 +10,9 @@ All function calls are virtual, which means that the most derived function
|
||||
is called, except when the contract name is explicitly given or the
|
||||
``super`` keyword is used.
|
||||
|
||||
All functions overriding a base function must specify the ``override`` keyword.
|
||||
See :ref:`Function Overriding <function-overriding>` for more details.
|
||||
|
||||
When a contract inherits from other contracts, only a single
|
||||
contract is created on the blockchain, and the code from all the base contracts
|
||||
is compiled into the created contract. This means that all internal calls
|
||||
@ -74,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 {
|
||||
function kill() public override {
|
||||
if (msg.sender == owner) {
|
||||
Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
|
||||
NameReg(config.lookup(1)).unregister();
|
||||
@ -94,6 +97,7 @@ Details are given in the following example.
|
||||
if (msg.sender == owner) info = newInfo;
|
||||
}
|
||||
|
||||
function kill() public override (Mortal, Named) { Named.kill(); }
|
||||
function get() public view returns(uint r) { return info; }
|
||||
|
||||
uint info;
|
||||
@ -117,20 +121,20 @@ seen in the following example::
|
||||
}
|
||||
|
||||
contract Base1 is mortal {
|
||||
function kill() public { /* do cleanup 1 */ mortal.kill(); }
|
||||
function kill() public override { /* do cleanup 1 */ mortal.kill(); }
|
||||
}
|
||||
|
||||
contract Base2 is mortal {
|
||||
function kill() public { /* do cleanup 2 */ mortal.kill(); }
|
||||
function kill() public override { /* do cleanup 2 */ mortal.kill(); }
|
||||
}
|
||||
|
||||
contract Final is Base1, Base2 {
|
||||
function kill() public override(Base1, Base2) { Base2.kill(); }
|
||||
}
|
||||
|
||||
A call to ``Final.kill()`` will call ``Base2.kill`` as the most
|
||||
derived override, but this function will bypass
|
||||
``Base1.kill``, basically because it does not even know about
|
||||
``Base1``. The way around this is to use ``super``::
|
||||
A call to ``Final.kill()`` will call ``Base2.kill`` because we specify it
|
||||
explicitly in the final override, but this function will bypass
|
||||
``Base1.kill``. The way around this is to use ``super``::
|
||||
|
||||
pragma solidity >=0.4.22 <0.7.0;
|
||||
|
||||
@ -146,15 +150,16 @@ derived override, but this function will bypass
|
||||
}
|
||||
|
||||
contract Base1 is mortal {
|
||||
function kill() public { /* do cleanup 1 */ super.kill(); }
|
||||
function kill() public override { /* do cleanup 1 */ super.kill(); }
|
||||
}
|
||||
|
||||
|
||||
contract Base2 is mortal {
|
||||
function kill() public { /* do cleanup 2 */ super.kill(); }
|
||||
function kill() public override { /* do cleanup 2 */ super.kill(); }
|
||||
}
|
||||
|
||||
contract Final is Base1, Base2 {
|
||||
function kill() public override(Base1, Base2) { super.kill(); }
|
||||
}
|
||||
|
||||
If ``Base2`` calls a function of ``super``, it does not simply
|
||||
@ -168,6 +173,123 @@ not known in the context of the class where it is used,
|
||||
although its type is known. This is similar for ordinary
|
||||
virtual method lookup.
|
||||
|
||||
.. _function-overriding:
|
||||
|
||||
.. index:: ! overriding;function
|
||||
|
||||
Function Overriding
|
||||
===================
|
||||
|
||||
Base functions can be overridden by inheriting contracts to change their
|
||||
behavior. The overriding function must then use the ``override`` keyword in the
|
||||
function header as shown in this example:
|
||||
|
||||
::
|
||||
|
||||
pragma solidity >=0.5.0 <0.7.0;
|
||||
|
||||
contract Base
|
||||
{
|
||||
function foo() public {}
|
||||
}
|
||||
|
||||
contract Middle is Base {}
|
||||
|
||||
contract Inherited is Middle
|
||||
{
|
||||
function foo() public override {}
|
||||
}
|
||||
|
||||
For multiple inheritance, the most derived base contracts that define the same
|
||||
function must be specified explicitly after the ``override`` keyword.
|
||||
In other words, you have to specify all base contracts that define the same function and have not yet been overridden by another base contract (on some path through the inheritance graph).
|
||||
Additionally, if a contract inherits the same function from multiple (unrelated)
|
||||
bases, it has to explicitly override it:
|
||||
|
||||
::
|
||||
|
||||
pragma solidity >=0.5.0 <0.7.0;
|
||||
|
||||
contract Base1
|
||||
{
|
||||
function foo() public {}
|
||||
}
|
||||
|
||||
contract Base2
|
||||
{
|
||||
function foo() public {}
|
||||
}
|
||||
|
||||
contract Inherited is Base1, Base2
|
||||
{
|
||||
// Derives from multiple bases defining foo(), so we must explicitly
|
||||
// override it
|
||||
function foo() public override(Base1, Base2) {}
|
||||
}
|
||||
|
||||
A function defined in a common base contract does not have to be explicitly
|
||||
overridden when used with multiple inheritance:
|
||||
|
||||
::
|
||||
|
||||
pragma solidity >=0.5.0 <0.7.0;
|
||||
|
||||
contract A { function f() public pure{} }
|
||||
contract B is A {}
|
||||
contract C is A {}
|
||||
// No explicit override required
|
||||
contract D is B, C {}
|
||||
|
||||
.. _modifier-overriding:
|
||||
|
||||
.. index:: ! overriding;modifier
|
||||
|
||||
Modifier Overriding
|
||||
===================
|
||||
|
||||
Function modifiers can override each other. This works in the same way as
|
||||
function overriding (except that there is no overloading for modifiers). The
|
||||
``override`` keyword must be used in the overriding contract:
|
||||
|
||||
::
|
||||
|
||||
pragma solidity >=0.5.0 <0.7.0;
|
||||
|
||||
contract Base
|
||||
{
|
||||
modifier foo() {_;}
|
||||
}
|
||||
|
||||
contract Inherited is Base
|
||||
{
|
||||
modifier foo() override {_;}
|
||||
}
|
||||
|
||||
|
||||
In case of multiple inheritance, all direct base contracts must be specified
|
||||
explicitly:
|
||||
|
||||
::
|
||||
|
||||
pragma solidity >=0.5.0 <0.7.0;
|
||||
|
||||
contract Base1
|
||||
{
|
||||
modifier foo() {_;}
|
||||
}
|
||||
|
||||
contract Base2
|
||||
{
|
||||
modifier foo() {_;}
|
||||
}
|
||||
|
||||
contract Inherited is Base1, Base2
|
||||
{
|
||||
modifier foo() override(Base1, Base2) {_;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.. index:: ! constructor
|
||||
|
||||
.. _constructor:
|
||||
|
@ -67,6 +67,11 @@ Function Modifiers
|
||||
Function modifiers can be used to amend the semantics of functions in a declarative way
|
||||
(see :ref:`modifiers` in the contracts section).
|
||||
|
||||
Overloading, that is, having the same modifier name with different parameters,
|
||||
is not possible.
|
||||
|
||||
Like functions, modifiers can be :ref:`overridden <modifier-overriding>`.
|
||||
|
||||
::
|
||||
|
||||
pragma solidity >=0.4.22 <0.7.0;
|
||||
|
@ -98,11 +98,11 @@ Yes::
|
||||
|
||||
|
||||
contract B is A {
|
||||
function spam() public pure {
|
||||
function spam() public override pure {
|
||||
// ...
|
||||
}
|
||||
|
||||
function ham() public pure {
|
||||
function ham() public override pure {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
#include <libdevcore/Common.h>
|
||||
|
||||
#include <vector>
|
||||
@ -49,14 +50,27 @@ template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U&& _
|
||||
std::move(_b.begin(), _b.end(), std::back_inserter(_a));
|
||||
return _a;
|
||||
}
|
||||
/// Concatenate the contents of a container onto a multiset
|
||||
template <class U, class... T> std::multiset<T...>& operator+=(std::multiset<T...>& _a, U const& _b)
|
||||
{
|
||||
_a.insert(_b.begin(), _b.end());
|
||||
return _a;
|
||||
}
|
||||
/// Concatenate the contents of a container onto a multiset, move variant.
|
||||
template <class U, class... T> std::multiset<T...>& operator+=(std::multiset<T...>& _a, U&& _b)
|
||||
{
|
||||
for (auto&& x: _b)
|
||||
_a.insert(std::move(x));
|
||||
return _a;
|
||||
}
|
||||
/// Concatenate the contents of a container onto a set
|
||||
template <class T, class U> std::set<T>& operator+=(std::set<T>& _a, U const& _b)
|
||||
template <class U, class... T> std::set<T...>& operator+=(std::set<T...>& _a, U const& _b)
|
||||
{
|
||||
_a.insert(_b.begin(), _b.end());
|
||||
return _a;
|
||||
}
|
||||
/// Concatenate the contents of a container onto a set, move variant.
|
||||
template <class T, class U> std::set<T>& operator+=(std::set<T>& _a, U&& _b)
|
||||
template <class U, class... T> std::set<T...>& operator+=(std::set<T...>& _a, U&& _b)
|
||||
{
|
||||
for (auto&& x: _b)
|
||||
_a.insert(std::move(x));
|
||||
@ -97,18 +111,43 @@ inline std::set<T> operator+(std::set<T>&& _a, U&& _b)
|
||||
ret += std::forward<U>(_b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Remove one set from another one.
|
||||
template <class T>
|
||||
inline std::set<T>& operator-=(std::set<T>& _a, std::set<T> const& _b)
|
||||
template <class... T>
|
||||
inline std::set<T...>& operator-=(std::set<T...>& _a, std::set<T...> const& _b)
|
||||
{
|
||||
for (auto const& x: _b)
|
||||
_a.erase(x);
|
||||
return _a;
|
||||
}
|
||||
|
||||
template <class... T>
|
||||
inline std::set<T...> operator-(std::set<T...> const& _a, std::set<T...> const& _b)
|
||||
{
|
||||
auto result = _a;
|
||||
result -= _b;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace dev
|
||||
{
|
||||
|
||||
template <class T, class U>
|
||||
T convertContainer(U const& _from)
|
||||
{
|
||||
return T{_from.cbegin(), _from.cend()};
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
T convertContainer(U&& _from)
|
||||
{
|
||||
return T{
|
||||
std::make_move_iterator(_from.begin()),
|
||||
std::make_move_iterator(_from.end())
|
||||
};
|
||||
}
|
||||
|
||||
// String conversion functions, mainly to/from hex/nibble/byte representations.
|
||||
|
||||
enum class WhenError
|
||||
@ -262,6 +301,12 @@ bool contains(T const& _t, V const& _v)
|
||||
return std::end(_t) != std::find(std::begin(_t), std::end(_t), _v);
|
||||
}
|
||||
|
||||
template <class T, class Predicate>
|
||||
bool contains_if(T const& _t, Predicate const& _p)
|
||||
{
|
||||
return std::end(_t) != std::find_if(std::begin(_t), std::end(_t), _p);
|
||||
}
|
||||
|
||||
/// Function that iterates over a vector, calling a function on each of its
|
||||
/// elements. If that function returns a vector, the element is replaced by
|
||||
/// the returned vector. During the iteration, the original vector is only valid
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <libsolidity/analysis/TypeChecker.h>
|
||||
#include <liblangutil/ErrorReporter.h>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
|
||||
using namespace std;
|
||||
@ -33,12 +34,103 @@ using namespace dev;
|
||||
using namespace langutil;
|
||||
using namespace dev::solidity;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Helper struct to do a search by name
|
||||
struct MatchByName
|
||||
{
|
||||
string const& m_name;
|
||||
bool operator()(CallableDeclaration const* _callable)
|
||||
{
|
||||
return _callable->name() == m_name;
|
||||
}
|
||||
};
|
||||
|
||||
vector<ASTPointer<UserDefinedTypeName>> sortByContract(vector<ASTPointer<UserDefinedTypeName>> const& _list)
|
||||
{
|
||||
auto sorted = _list;
|
||||
|
||||
sort(sorted.begin(), sorted.end(),
|
||||
[] (ASTPointer<UserDefinedTypeName> _a, ASTPointer<UserDefinedTypeName> _b) {
|
||||
if (!_a || !_b)
|
||||
return _a < _b;
|
||||
|
||||
Declaration const* aDecl = _a->annotation().referencedDeclaration;
|
||||
Declaration const* bDecl = _b->annotation().referencedDeclaration;
|
||||
|
||||
if (!aDecl || !bDecl)
|
||||
return aDecl < bDecl;
|
||||
|
||||
return aDecl->id() < bDecl->id();
|
||||
}
|
||||
);
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool hasEqualNameAndParameters(T const& _a, T const& _b)
|
||||
{
|
||||
return
|
||||
_a.name() == _b.name() &&
|
||||
FunctionType(_a).asCallableFunction(false)->hasEqualParameterTypes(
|
||||
*FunctionType(_b).asCallableFunction(false)
|
||||
);
|
||||
}
|
||||
|
||||
vector<ContractDefinition const*> resolveDirectBaseContracts(ContractDefinition const& _contract)
|
||||
{
|
||||
vector<ContractDefinition const*> resolvedContracts;
|
||||
|
||||
for (ASTPointer<InheritanceSpecifier> const& specifier: _contract.baseContracts())
|
||||
{
|
||||
Declaration const* baseDecl =
|
||||
specifier->name().annotation().referencedDeclaration;
|
||||
auto contract = dynamic_cast<ContractDefinition const*>(baseDecl);
|
||||
solAssert(contract, "contract is null");
|
||||
resolvedContracts.emplace_back(contract);
|
||||
}
|
||||
|
||||
return resolvedContracts;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool ContractLevelChecker::LessFunction::operator()(ModifierDefinition const* _a, ModifierDefinition const* _b) const
|
||||
{
|
||||
return _a->name() < _b->name();
|
||||
}
|
||||
|
||||
bool ContractLevelChecker::LessFunction::operator()(FunctionDefinition const* _a, FunctionDefinition const* _b) const
|
||||
{
|
||||
if (_a->name() != _b->name())
|
||||
return _a->name() < _b->name();
|
||||
|
||||
return boost::lexicographical_compare(
|
||||
FunctionType(*_a).asCallableFunction(false)->parameterTypes(),
|
||||
FunctionType(*_b).asCallableFunction(false)->parameterTypes(),
|
||||
[](auto const& _paramTypeA, auto const& _paramTypeB)
|
||||
{
|
||||
return _paramTypeA->richIdentifier() < _paramTypeB->richIdentifier();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
bool ContractLevelChecker::LessFunction::operator()(ContractDefinition const* _a, ContractDefinition const* _b) const
|
||||
{
|
||||
if (!_a || !_b)
|
||||
return _a < _b;
|
||||
|
||||
return _a->id() < _b->id();
|
||||
}
|
||||
|
||||
bool ContractLevelChecker::check(ContractDefinition const& _contract)
|
||||
{
|
||||
checkDuplicateFunctions(_contract);
|
||||
checkDuplicateEvents(_contract);
|
||||
checkIllegalOverrides(_contract);
|
||||
checkAmbiguousOverrides(_contract);
|
||||
checkAbstractFunctions(_contract);
|
||||
checkBaseConstructorArguments(_contract);
|
||||
checkConstructor(_contract);
|
||||
@ -111,9 +203,7 @@ void ContractLevelChecker::findDuplicateDefinitions(map<string, vector<T>> const
|
||||
SecondarySourceLocation ssl;
|
||||
|
||||
for (size_t j = i + 1; j < overloads.size(); ++j)
|
||||
if (FunctionType(*overloads[i]).asCallableFunction(false)->hasEqualParameterTypes(
|
||||
*FunctionType(*overloads[j]).asCallableFunction(false))
|
||||
)
|
||||
if (hasEqualNameAndParameters(*overloads[i], *overloads[j]))
|
||||
{
|
||||
ssl.append("Other declaration is here:", overloads[j]->location());
|
||||
reported.insert(j);
|
||||
@ -135,50 +225,52 @@ void ContractLevelChecker::findDuplicateDefinitions(map<string, vector<T>> const
|
||||
|
||||
void ContractLevelChecker::checkIllegalOverrides(ContractDefinition const& _contract)
|
||||
{
|
||||
// TODO unify this at a later point. for this we need to put the constness and the access specifier
|
||||
// into the types
|
||||
map<string, vector<FunctionDefinition const*>> functions;
|
||||
map<string, ModifierDefinition const*> modifiers;
|
||||
FunctionMultiSet const& funcSet = inheritedFunctions(&_contract);
|
||||
ModifierMultiSet const& modSet = inheritedModifiers(&_contract);
|
||||
|
||||
// We search from derived to base, so the stored item causes the error.
|
||||
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
|
||||
checkModifierOverrides(funcSet, modSet, _contract.functionModifiers());
|
||||
|
||||
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||
{
|
||||
for (FunctionDefinition const* function: contract->definedFunctions())
|
||||
{
|
||||
if (function->isConstructor())
|
||||
continue; // constructors can neither be overridden nor override anything
|
||||
string const& name = function->name();
|
||||
if (modifiers.count(name))
|
||||
m_errorReporter.typeError(modifiers[name]->location(), "Override changes function to modifier.");
|
||||
if (contains_if(modSet, MatchByName{function->name()}))
|
||||
m_errorReporter.typeError(function->location(), "Override changes modifier to function.");
|
||||
|
||||
for (FunctionDefinition const* overriding: functions[name])
|
||||
checkFunctionOverride(*overriding, *function);
|
||||
// Skip if not overridable
|
||||
if (!function->isOverridable())
|
||||
continue;
|
||||
|
||||
functions[name].push_back(function);
|
||||
}
|
||||
for (ModifierDefinition const* modifier: contract->functionModifiers())
|
||||
{
|
||||
string const& name = modifier->name();
|
||||
ModifierDefinition const*& override = modifiers[name];
|
||||
if (!override)
|
||||
override = modifier;
|
||||
else if (ModifierType(*override) != ModifierType(*modifier))
|
||||
m_errorReporter.typeError(override->location(), "Override changes modifier signature.");
|
||||
if (!functions[name].empty())
|
||||
m_errorReporter.typeError(override->location(), "Override changes modifier to function.");
|
||||
}
|
||||
// No inheriting functions found
|
||||
if (funcSet.find(function) == funcSet.cend() && function->overrides())
|
||||
m_errorReporter.typeError(
|
||||
function->overrides()->location(),
|
||||
"Function has override specified but does not override anything."
|
||||
);
|
||||
|
||||
checkOverrideList(funcSet, *function);
|
||||
}
|
||||
}
|
||||
|
||||
void ContractLevelChecker::checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super)
|
||||
bool ContractLevelChecker::checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super)
|
||||
{
|
||||
FunctionTypePointer functionType = FunctionType(_function).asCallableFunction(false);
|
||||
FunctionTypePointer superType = FunctionType(_super).asCallableFunction(false);
|
||||
|
||||
bool success = true;
|
||||
|
||||
if (!functionType->hasEqualParameterTypes(*superType))
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (!_function.overrides())
|
||||
{
|
||||
overrideError(_function, _super, "Overriding function is missing 'override' specifier.");
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!functionType->hasEqualReturnTypes(*superType))
|
||||
{
|
||||
overrideError(_function, _super, "Overriding function return types differ.");
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (!_function.annotation().superFunction)
|
||||
_function.annotation().superFunction = &_super;
|
||||
@ -191,9 +283,13 @@ void ContractLevelChecker::checkFunctionOverride(FunctionDefinition const& _func
|
||||
_super.visibility() == FunctionDefinition::Visibility::External &&
|
||||
_function.visibility() == FunctionDefinition::Visibility::Public
|
||||
))
|
||||
{
|
||||
overrideError(_function, _super, "Overriding function visibility differs.");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (_function.stateMutability() != _super.stateMutability())
|
||||
{
|
||||
overrideError(
|
||||
_function,
|
||||
_super,
|
||||
@ -203,9 +299,38 @@ void ContractLevelChecker::checkFunctionOverride(FunctionDefinition const& _func
|
||||
stateMutabilityToString(_function.stateMutability()) +
|
||||
"\"."
|
||||
);
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void ContractLevelChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message)
|
||||
void ContractLevelChecker::overrideListError(FunctionDefinition const& function, set<ContractDefinition const*, LessFunction> _secondary, string const& _message1, string const& _message2)
|
||||
{
|
||||
// Using a set rather than a vector so the order is always the same
|
||||
set<string> names;
|
||||
SecondarySourceLocation ssl;
|
||||
for (Declaration const* c: _secondary)
|
||||
{
|
||||
ssl.append("This contract: ", c->location());
|
||||
names.insert(c->name());
|
||||
}
|
||||
string contractSingularPlural = "contract ";
|
||||
if (_secondary.size() > 1)
|
||||
contractSingularPlural = "contracts ";
|
||||
|
||||
m_errorReporter.typeError(
|
||||
function.overrides() ? function.overrides()->location() : function.location(),
|
||||
ssl,
|
||||
_message1 +
|
||||
contractSingularPlural +
|
||||
_message2 +
|
||||
joinHumanReadable(names, ", ", " and ") +
|
||||
"."
|
||||
);
|
||||
}
|
||||
|
||||
void ContractLevelChecker::overrideError(CallableDeclaration const& function, CallableDeclaration const& super, string message)
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
function.location(),
|
||||
@ -510,3 +635,231 @@ void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void ContractLevelChecker::checkAmbiguousOverrides(ContractDefinition const& _contract) const
|
||||
{
|
||||
vector<FunctionDefinition const*> contractFuncs = _contract.definedFunctions();
|
||||
|
||||
auto const resolvedBases = resolveDirectBaseContracts(_contract);
|
||||
|
||||
FunctionMultiSet inheritedFuncs = inheritedFunctions(&_contract);;
|
||||
|
||||
// Check the sets of the most-inherited functions
|
||||
for (auto it = inheritedFuncs.cbegin(); it != inheritedFuncs.cend(); it = inheritedFuncs.upper_bound(*it))
|
||||
{
|
||||
auto [begin,end] = inheritedFuncs.equal_range(*it);
|
||||
|
||||
// Only one function
|
||||
if (next(begin) == end)
|
||||
continue;
|
||||
|
||||
// Not an overridable function
|
||||
if (!(*it)->isOverridable())
|
||||
{
|
||||
for (begin++; begin != end; begin++)
|
||||
solAssert(!(*begin)->isOverridable(), "All functions in range expected to be non-overridable!");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Function has been explicitly overridden
|
||||
if (contains_if(
|
||||
contractFuncs,
|
||||
[&] (FunctionDefinition const* _f) {
|
||||
return hasEqualNameAndParameters(*_f, **it);
|
||||
}
|
||||
))
|
||||
continue;
|
||||
|
||||
set<FunctionDefinition const*> ambiguousFunctions;
|
||||
SecondarySourceLocation ssl;
|
||||
|
||||
for (;begin != end; begin++)
|
||||
{
|
||||
ambiguousFunctions.insert(*begin);
|
||||
ssl.append("Definition here: ", (*begin)->location());
|
||||
}
|
||||
|
||||
// Make sure the functions are not from the same base contract
|
||||
if (ambiguousFunctions.size() == 1)
|
||||
continue;
|
||||
|
||||
m_errorReporter.typeError(
|
||||
_contract.location(),
|
||||
ssl,
|
||||
"Derived contract must override function \"" +
|
||||
(*it)->name() +
|
||||
"\". Function with the same name and parameter types defined in two or more base classes."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
set<ContractDefinition const*, ContractLevelChecker::LessFunction> ContractLevelChecker::resolveOverrideList(OverrideSpecifier const& _overrides) const
|
||||
{
|
||||
set<ContractDefinition const*, LessFunction> resolved;
|
||||
|
||||
for (ASTPointer<UserDefinedTypeName> const& override: _overrides.overrides())
|
||||
{
|
||||
Declaration const* decl = override->annotation().referencedDeclaration;
|
||||
solAssert(decl, "Expected declaration to be resolved.");
|
||||
|
||||
// If it's not a contract it will be caught
|
||||
// in the reference resolver
|
||||
if (ContractDefinition const* contract = dynamic_cast<decltype(contract)>(decl))
|
||||
resolved.insert(contract);
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
|
||||
void ContractLevelChecker::checkModifierOverrides(FunctionMultiSet const& _funcSet, ModifierMultiSet const& _modSet, std::vector<ModifierDefinition const*> _modifiers)
|
||||
{
|
||||
for (ModifierDefinition const* modifier: _modifiers)
|
||||
{
|
||||
if (contains_if(_funcSet, MatchByName{modifier->name()}))
|
||||
m_errorReporter.typeError(
|
||||
modifier->location(),
|
||||
"Override changes function to modifier."
|
||||
);
|
||||
|
||||
auto [begin,end] = _modSet.equal_range(modifier);
|
||||
|
||||
// Skip if no modifiers found in bases
|
||||
if (begin == end)
|
||||
continue;
|
||||
|
||||
if (!modifier->overrides())
|
||||
overrideError(*modifier, **begin, "Overriding modifier is missing 'override' specifier.");
|
||||
|
||||
for (; begin != end; begin++)
|
||||
if (ModifierType(**begin) != ModifierType(*modifier))
|
||||
m_errorReporter.typeError(
|
||||
modifier->location(),
|
||||
"Override changes modifier signature."
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ContractLevelChecker::checkOverrideList(FunctionMultiSet const& _funcSet, FunctionDefinition const& _function)
|
||||
{
|
||||
set<ContractDefinition const*, LessFunction> specifiedContracts =
|
||||
_function.overrides() ?
|
||||
resolveOverrideList(*_function.overrides()) :
|
||||
decltype(specifiedContracts){};
|
||||
|
||||
// Check for duplicates in override list
|
||||
if (_function.overrides() && specifiedContracts.size() != _function.overrides()->overrides().size())
|
||||
{
|
||||
// Sort by contract id to find duplicate for error reporting
|
||||
vector<ASTPointer<UserDefinedTypeName>> list =
|
||||
sortByContract(_function.overrides()->overrides());
|
||||
|
||||
// Find duplicates and output error
|
||||
for (size_t i = 1; i < list.size(); i++)
|
||||
{
|
||||
Declaration const* aDecl = list[i]->annotation().referencedDeclaration;
|
||||
Declaration const* bDecl = list[i-1]->annotation().referencedDeclaration;
|
||||
if (!aDecl || !bDecl)
|
||||
continue;
|
||||
|
||||
if (aDecl->id() == bDecl->id())
|
||||
{
|
||||
SecondarySourceLocation ssl;
|
||||
ssl.append("First occurrence here: ", list[i-1]->location());
|
||||
m_errorReporter.typeError(
|
||||
list[i]->location(),
|
||||
ssl,
|
||||
"Duplicate contract \"" +
|
||||
joinHumanReadable(list[i]->namePath(), ".") +
|
||||
"\" found in override list of \"" +
|
||||
_function.name() +
|
||||
"\"."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decltype(specifiedContracts) expectedContracts;
|
||||
|
||||
// Build list of expected contracts
|
||||
for (auto [begin, end] = _funcSet.equal_range(&_function); begin != end; begin++)
|
||||
{
|
||||
// Validate the override
|
||||
if (!checkFunctionOverride(_function, **begin))
|
||||
break;
|
||||
|
||||
expectedContracts.insert((*begin)->annotation().contract);
|
||||
}
|
||||
|
||||
decltype(specifiedContracts) missingContracts;
|
||||
decltype(specifiedContracts) surplusContracts;
|
||||
|
||||
// If we expect only one contract, no contract needs to be specified
|
||||
if (expectedContracts.size() > 1)
|
||||
missingContracts = expectedContracts - specifiedContracts;
|
||||
|
||||
surplusContracts = specifiedContracts - expectedContracts;
|
||||
|
||||
if (!missingContracts.empty())
|
||||
overrideListError(
|
||||
_function,
|
||||
missingContracts,
|
||||
"Function needs to specify overridden ",
|
||||
""
|
||||
);
|
||||
|
||||
if (!surplusContracts.empty())
|
||||
overrideListError(
|
||||
_function,
|
||||
surplusContracts,
|
||||
"Invalid ",
|
||||
"specified in override list: "
|
||||
);
|
||||
}
|
||||
|
||||
ContractLevelChecker::FunctionMultiSet const& ContractLevelChecker::inheritedFunctions(ContractDefinition const* _contract) const
|
||||
{
|
||||
if (!m_inheritedFunctions.count(_contract))
|
||||
{
|
||||
FunctionMultiSet set;
|
||||
|
||||
for (auto const* base: resolveDirectBaseContracts(*_contract))
|
||||
{
|
||||
std::set<FunctionDefinition const*, LessFunction> tmpSet =
|
||||
convertContainer<decltype(tmpSet)>(base->definedFunctions());
|
||||
|
||||
for (auto const& func: inheritedFunctions(base))
|
||||
tmpSet.insert(func);
|
||||
|
||||
set += tmpSet;
|
||||
}
|
||||
|
||||
m_inheritedFunctions[_contract] = set;
|
||||
}
|
||||
|
||||
return m_inheritedFunctions[_contract];
|
||||
}
|
||||
|
||||
ContractLevelChecker::ModifierMultiSet const& ContractLevelChecker::inheritedModifiers(ContractDefinition const* _contract) const
|
||||
{
|
||||
auto const& result = m_contractBaseModifiers.find(_contract);
|
||||
|
||||
if (result != m_contractBaseModifiers.cend())
|
||||
return result->second;
|
||||
|
||||
ModifierMultiSet set;
|
||||
|
||||
for (auto const* base: resolveDirectBaseContracts(*_contract))
|
||||
{
|
||||
std::set<ModifierDefinition const*, LessFunction> tmpSet =
|
||||
convertContainer<decltype(tmpSet)>(base->functionModifiers());
|
||||
|
||||
for (auto const& mod: inheritedModifiers(base))
|
||||
tmpSet.insert(mod);
|
||||
|
||||
set += tmpSet;
|
||||
}
|
||||
|
||||
return m_contractBaseModifiers[_contract] = set;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <libsolidity/ast/ASTForward.h>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace langutil
|
||||
{
|
||||
@ -41,6 +42,7 @@ namespace solidity
|
||||
class ContractLevelChecker
|
||||
{
|
||||
public:
|
||||
|
||||
/// @param _errorReporter provides the error logging functionality.
|
||||
explicit ContractLevelChecker(langutil::ErrorReporter& _errorReporter):
|
||||
m_errorReporter(_errorReporter)
|
||||
@ -51,6 +53,16 @@ public:
|
||||
bool check(ContractDefinition const& _contract);
|
||||
|
||||
private:
|
||||
struct LessFunction
|
||||
{
|
||||
bool operator()(ModifierDefinition const* _a, ModifierDefinition const* _b) const;
|
||||
bool operator()(FunctionDefinition const* _a, FunctionDefinition const* _b) const;
|
||||
bool operator()(ContractDefinition const* _a, ContractDefinition const* _b) const;
|
||||
};
|
||||
|
||||
using FunctionMultiSet = std::multiset<FunctionDefinition const*, LessFunction>;
|
||||
using ModifierMultiSet = std::multiset<ModifierDefinition const*, LessFunction>;
|
||||
|
||||
/// Checks that two functions defined in this contract with the same name have different
|
||||
/// arguments and that there is at most one constructor.
|
||||
void checkDuplicateFunctions(ContractDefinition const& _contract);
|
||||
@ -58,10 +70,12 @@ private:
|
||||
template <class T>
|
||||
void findDuplicateDefinitions(std::map<std::string, std::vector<T>> const& _definitions, std::string _message);
|
||||
void checkIllegalOverrides(ContractDefinition const& _contract);
|
||||
/// Reports a type error with an appropriate message if overridden function signature differs.
|
||||
/// Returns false and reports a type error with an appropriate
|
||||
/// message if overridden function signature differs.
|
||||
/// Also stores the direct super function in the AST annotations.
|
||||
void checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super);
|
||||
void overrideError(FunctionDefinition const& function, FunctionDefinition const& super, std::string message);
|
||||
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 checkAbstractFunctions(ContractDefinition const& _contract);
|
||||
void checkBaseConstructorArguments(ContractDefinition const& _contract);
|
||||
void annotateBaseConstructorArguments(
|
||||
@ -80,8 +94,25 @@ private:
|
||||
void checkLibraryRequirements(ContractDefinition const& _contract);
|
||||
/// Checks base contracts for ABI compatibility
|
||||
void checkBaseABICompatibility(ContractDefinition const& _contract);
|
||||
/// Checks for functions in different base contracts which conflict with each
|
||||
/// other and thus need to be overridden explicitly.
|
||||
void checkAmbiguousOverrides(ContractDefinition const& _contract) const;
|
||||
/// Resolves an override list of UserDefinedTypeNames to a list of contracts.
|
||||
std::set<ContractDefinition const*, LessFunction> resolveOverrideList(OverrideSpecifier const& _overrides) const;
|
||||
|
||||
void checkModifierOverrides(FunctionMultiSet const& _funcSet, ModifierMultiSet const& _modSet, std::vector<ModifierDefinition const*> _modifiers);
|
||||
void checkOverrideList(FunctionMultiSet const& _funcSet, FunctionDefinition const& _function);
|
||||
|
||||
/// Returns all functions of bases that have not yet been overwritten.
|
||||
/// May contain the same function multiple times when used with shared bases.
|
||||
FunctionMultiSet const& inheritedFunctions(ContractDefinition const* _contract) const;
|
||||
ModifierMultiSet const& inheritedModifiers(ContractDefinition const* _contract) const;
|
||||
|
||||
langutil::ErrorReporter& m_errorReporter;
|
||||
|
||||
/// Cache for inheritedFunctions().
|
||||
std::map<ContractDefinition const*, FunctionMultiSet> mutable m_inheritedFunctions;
|
||||
std::map<ContractDefinition const*, ModifierMultiSet> mutable m_contractBaseModifiers;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -570,6 +570,7 @@ bool DeclarationRegistrationHelper::visit(ContractDefinition& _contract)
|
||||
m_globalContext.setCurrentContract(_contract);
|
||||
m_scopes[nullptr]->registerDeclaration(*m_globalContext.currentThis(), nullptr, false, true);
|
||||
m_scopes[nullptr]->registerDeclaration(*m_globalContext.currentSuper(), nullptr, false, true);
|
||||
m_currentContract = &_contract;
|
||||
|
||||
registerDeclaration(_contract, true);
|
||||
_contract.annotation().canonicalName = currentCanonicalName();
|
||||
@ -578,6 +579,7 @@ bool DeclarationRegistrationHelper::visit(ContractDefinition& _contract)
|
||||
|
||||
void DeclarationRegistrationHelper::endVisit(ContractDefinition&)
|
||||
{
|
||||
m_currentContract = nullptr;
|
||||
closeCurrentScope();
|
||||
}
|
||||
|
||||
@ -615,6 +617,7 @@ bool DeclarationRegistrationHelper::visit(FunctionDefinition& _function)
|
||||
{
|
||||
registerDeclaration(_function, true);
|
||||
m_currentFunction = &_function;
|
||||
_function.annotation().contract = m_currentContract;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,7 @@ private:
|
||||
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& m_scopes;
|
||||
ASTNode const* m_currentScope = nullptr;
|
||||
VariableScope* m_currentFunction = nullptr;
|
||||
ContractDefinition const* m_currentContract = nullptr;
|
||||
langutil::ErrorReporter& m_errorReporter;
|
||||
GlobalContext& m_globalContext;
|
||||
};
|
||||
|
@ -60,6 +60,27 @@ void PostTypeChecker::endVisit(ContractDefinition const&)
|
||||
m_constVariableDependencies.clear();
|
||||
}
|
||||
|
||||
void PostTypeChecker::endVisit(OverrideSpecifier const& _overrideSpecifier)
|
||||
{
|
||||
for (ASTPointer<UserDefinedTypeName> const& override: _overrideSpecifier.overrides())
|
||||
{
|
||||
Declaration const* decl = override->annotation().referencedDeclaration;
|
||||
solAssert(decl, "Expected declaration to be resolved.");
|
||||
|
||||
if (dynamic_cast<ContractDefinition const*>(decl))
|
||||
continue;
|
||||
|
||||
TypeType const* actualTypeType = dynamic_cast<TypeType const*>(decl->type());
|
||||
|
||||
m_errorReporter.typeError(
|
||||
override->location(),
|
||||
"Expected contract but got " +
|
||||
actualTypeType->actualType()->toString(true) +
|
||||
"."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool PostTypeChecker::visit(VariableDeclaration const& _variable)
|
||||
{
|
||||
solAssert(!m_currentConstVariable, "");
|
||||
|
@ -37,6 +37,7 @@ namespace solidity
|
||||
/**
|
||||
* This module performs analyses on the AST that are done after type checking and assignments of types:
|
||||
* - whether there are circular references in constant state variables
|
||||
* - whether override specifiers are actually contracts
|
||||
* @TODO factor out each use-case into an individual class (but do the traversal only once)
|
||||
*/
|
||||
class PostTypeChecker: private ASTConstVisitor
|
||||
@ -53,6 +54,7 @@ private:
|
||||
|
||||
bool visit(ContractDefinition const& _contract) override;
|
||||
void endVisit(ContractDefinition const& _contract) override;
|
||||
void endVisit(OverrideSpecifier const& _overrideSpecifier) override;
|
||||
|
||||
bool visit(VariableDeclaration const& _variable) override;
|
||||
void endVisit(VariableDeclaration const& _variable) override;
|
||||
|
@ -596,21 +596,25 @@ public:
|
||||
ASTPointer<ASTString> const& _name,
|
||||
Declaration::Visibility _visibility,
|
||||
ASTPointer<ParameterList> const& _parameters,
|
||||
ASTPointer<OverrideSpecifier> const& _overrides = nullptr,
|
||||
ASTPointer<ParameterList> const& _returnParameters = ASTPointer<ParameterList>()
|
||||
):
|
||||
Declaration(_location, _name, _visibility),
|
||||
m_parameters(_parameters),
|
||||
m_overrides(_overrides),
|
||||
m_returnParameters(_returnParameters)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& parameters() const { return m_parameters->parameters(); }
|
||||
ASTPointer<OverrideSpecifier> const& overrides() const { return m_overrides; }
|
||||
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; }
|
||||
|
||||
protected:
|
||||
ASTPointer<ParameterList> m_parameters;
|
||||
ASTPointer<OverrideSpecifier> m_overrides;
|
||||
ASTPointer<ParameterList> m_returnParameters;
|
||||
};
|
||||
|
||||
@ -656,12 +660,11 @@ public:
|
||||
ASTPointer<ParameterList> const& _returnParameters,
|
||||
ASTPointer<Block> const& _body
|
||||
):
|
||||
CallableDeclaration(_location, _name, _visibility, _parameters, _returnParameters),
|
||||
CallableDeclaration(_location, _name, _visibility, _parameters, _overrides, _returnParameters),
|
||||
Documented(_documentation),
|
||||
ImplementationOptional(_body != nullptr),
|
||||
m_stateMutability(_stateMutability),
|
||||
m_isConstructor(_isConstructor),
|
||||
m_overrides(_overrides),
|
||||
m_functionModifiers(_modifiers),
|
||||
m_body(_body)
|
||||
{}
|
||||
@ -671,8 +674,8 @@ public:
|
||||
|
||||
StateMutability stateMutability() const { return m_stateMutability; }
|
||||
bool isConstructor() const { return m_isConstructor; }
|
||||
ASTPointer<OverrideSpecifier> const& overrides() const { return m_overrides; }
|
||||
bool isFallback() const { return !m_isConstructor && name().empty(); }
|
||||
bool isOverridable() const { return !isFallback() && !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; }
|
||||
@ -700,7 +703,6 @@ public:
|
||||
private:
|
||||
StateMutability m_stateMutability;
|
||||
bool m_isConstructor;
|
||||
ASTPointer<OverrideSpecifier> m_overrides;
|
||||
std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers;
|
||||
ASTPointer<Block> m_body;
|
||||
};
|
||||
@ -814,9 +816,10 @@ public:
|
||||
ASTPointer<ASTString> const& _name,
|
||||
ASTPointer<ASTString> const& _documentation,
|
||||
ASTPointer<ParameterList> const& _parameters,
|
||||
ASTPointer<OverrideSpecifier> const& _overrides,
|
||||
ASTPointer<Block> const& _body
|
||||
):
|
||||
CallableDeclaration(_location, _name, Visibility::Internal, _parameters),
|
||||
CallableDeclaration(_location, _name, Visibility::Internal, _parameters, _overrides),
|
||||
Documented(_documentation),
|
||||
m_body(_body)
|
||||
{
|
||||
|
@ -109,6 +109,8 @@ struct FunctionDefinitionAnnotation: ASTAnnotation, DocumentedAnnotation
|
||||
/// The function this function overrides, if any. This is always the closest
|
||||
/// in the linearized inheritance hierarchy.
|
||||
FunctionDefinition const* superFunction = nullptr;
|
||||
/// Pointer to the contract this function is defined in
|
||||
ContractDefinition const* contract = nullptr;
|
||||
};
|
||||
|
||||
struct EventDefinitionAnnotation: ASTAnnotation, DocumentedAnnotation
|
||||
|
@ -262,6 +262,8 @@ void ModifierDefinition::accept(ASTVisitor& _visitor)
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
m_parameters->accept(_visitor);
|
||||
if (m_overrides)
|
||||
m_overrides->accept(_visitor);
|
||||
m_body->accept(_visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
@ -272,6 +274,8 @@ void ModifierDefinition::accept(ASTConstVisitor& _visitor) const
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
m_parameters->accept(_visitor);
|
||||
if (m_overrides)
|
||||
m_overrides->accept(_visitor);
|
||||
m_body->accept(_visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
|
@ -808,9 +808,15 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
|
||||
}
|
||||
else
|
||||
parameters = createEmptyParameterList();
|
||||
|
||||
ASTPointer<OverrideSpecifier> overrides;
|
||||
|
||||
if (m_scanner->currentToken() == Token::Override)
|
||||
overrides = parseOverrideSpecifier();
|
||||
|
||||
ASTPointer<Block> block = parseBlock();
|
||||
nodeFactory.setEndPositionFromNode(block);
|
||||
return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, block);
|
||||
return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, overrides, block);
|
||||
}
|
||||
|
||||
ASTPointer<EventDefinition> Parser::parseEventDefinition()
|
||||
|
@ -40,6 +40,7 @@ contract MultiSigWalletWithDailyLimit is MultiSigWallet {
|
||||
/// @param transactionId Transaction ID.
|
||||
function executeTransaction(uint transactionId)
|
||||
public
|
||||
override
|
||||
notExecuted(transactionId)
|
||||
{
|
||||
Transaction storage tx = transactions[transactionId];
|
||||
|
@ -12,7 +12,7 @@ contract thirdPartyPContractAbstract {
|
||||
contract ptokenDB is tokenDB {}
|
||||
|
||||
contract premium is module, safeMath {
|
||||
function replaceModule(address payable addr) external returns (bool success) {
|
||||
function replaceModule(address payable addr) external override returns (bool success) {
|
||||
require( super.isModuleHandler(msg.sender) );
|
||||
require( db.replaceOwner(addr) );
|
||||
super._replaceModule(addr);
|
||||
|
@ -9,14 +9,14 @@ contract provider is module, safeMath, announcementTypes {
|
||||
/*
|
||||
module callbacks
|
||||
*/
|
||||
function connectModule() external returns (bool success) {
|
||||
function connectModule() external override returns (bool success) {
|
||||
require( super.isModuleHandler(msg.sender) );
|
||||
super._connectModule();
|
||||
(bool _success, uint256 currentSchellingRound) = moduleHandler(moduleHandlerAddress).getCurrentSchellingRoundID();
|
||||
require( _success );
|
||||
return true;
|
||||
}
|
||||
function transferEvent(address payable from, address payable to, uint256 value) external returns (bool success) {
|
||||
function transferEvent(address payable from, address payable to, uint256 value) external override returns (bool success) {
|
||||
/*
|
||||
Transaction completed. This function is only available for the modulehandler.
|
||||
It should be checked if the sender or the acceptor does not connect to the provider or it is not a provider itself if so than the change should be recorded.
|
||||
@ -31,7 +31,7 @@ contract provider is module, safeMath, announcementTypes {
|
||||
transferEvent_(to, value, false);
|
||||
return true;
|
||||
}
|
||||
function newSchellingRoundEvent(uint256 roundID, uint256 reward) external returns (bool success) {
|
||||
function newSchellingRoundEvent(uint256 roundID, uint256 reward) external override returns (bool success) {
|
||||
/*
|
||||
New schelling round. This function is only available for the moduleHandler.
|
||||
We are recording the new schelling round and we are storing the whole current quantity of the tokens.
|
||||
|
@ -9,7 +9,7 @@ contract publisher is announcementTypes, module, safeMath {
|
||||
/*
|
||||
module callbacks
|
||||
*/
|
||||
function transferEvent(address payable from, address payable to, uint256 value) external returns (bool success) {
|
||||
function transferEvent(address payable from, address payable to, uint256 value) external override returns (bool success) {
|
||||
/*
|
||||
Transaction completed. This function is available only for moduleHandler
|
||||
If a transaction is carried out from or to an address which participated in the objection of an announcement, its objection purport is automatically set
|
||||
|
@ -134,13 +134,13 @@ contract schelling is module, announcementTypes, schellingVars {
|
||||
/*
|
||||
module callbacks
|
||||
*/
|
||||
function replaceModule(address payable addr) external returns (bool) {
|
||||
function replaceModule(address payable addr) external override returns (bool) {
|
||||
require( super.isModuleHandler(msg.sender) );
|
||||
require( db.replaceOwner(addr) );
|
||||
super._replaceModule(addr);
|
||||
return true;
|
||||
}
|
||||
function transferEvent(address payable from, address payable to, uint256 value) external returns (bool) {
|
||||
function transferEvent(address payable from, address payable to, uint256 value) external override returns (bool) {
|
||||
/*
|
||||
Transaction completed. This function can be called only by the ModuleHandler.
|
||||
If this contract is the receiver, the amount will be added to the prize pool of the current round.
|
||||
|
@ -15,7 +15,7 @@ contract token is safeMath, module, announcementTypes {
|
||||
/*
|
||||
module callbacks
|
||||
*/
|
||||
function replaceModule(address payable addr) external returns (bool success) {
|
||||
function replaceModule(address payable addr) external override returns (bool success) {
|
||||
require( super.isModuleHandler(msg.sender) );
|
||||
require( db.replaceOwner(addr) );
|
||||
super._replaceModule(addr);
|
||||
|
@ -28,6 +28,7 @@ contract CategoricalEvent is Event {
|
||||
/// @return Sender's winnings
|
||||
function redeemWinnings()
|
||||
public
|
||||
override
|
||||
returns (uint winnings)
|
||||
{
|
||||
// Winning outcome has to be set
|
||||
@ -45,6 +46,7 @@ contract CategoricalEvent is Event {
|
||||
/// @return Event hash
|
||||
function getEventHash()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (bytes32)
|
||||
{
|
||||
|
@ -47,6 +47,7 @@ contract ScalarEvent is Event {
|
||||
/// @return Sender's winnings
|
||||
function redeemWinnings()
|
||||
public
|
||||
override
|
||||
returns (uint winnings)
|
||||
{
|
||||
// Winning outcome has to be set
|
||||
@ -79,6 +80,7 @@ contract ScalarEvent is Event {
|
||||
/// @return Event hash
|
||||
function getEventHash()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (bytes32)
|
||||
{
|
||||
|
@ -24,6 +24,7 @@ contract LMSRMarketMaker is MarketMaker {
|
||||
/// @return Cost
|
||||
function calcCost(Market market, uint8 outcomeTokenIndex, uint outcomeTokenCount)
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (uint cost)
|
||||
{
|
||||
@ -59,6 +60,7 @@ contract LMSRMarketMaker is MarketMaker {
|
||||
/// @return Profit
|
||||
function calcProfit(Market market, uint8 outcomeTokenIndex, uint outcomeTokenCount)
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (uint profit)
|
||||
{
|
||||
@ -85,6 +87,7 @@ contract LMSRMarketMaker is MarketMaker {
|
||||
/// @return Marginal price of an outcome as a fixed point number
|
||||
function calcMarginalPrice(Market market, uint8 outcomeTokenIndex)
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (uint price)
|
||||
{
|
||||
|
@ -56,6 +56,7 @@ contract StandardMarket is Market {
|
||||
/// @param _funding Funding amount
|
||||
function fund(uint _funding)
|
||||
public
|
||||
override
|
||||
isCreator
|
||||
atStage(Stages.MarketCreated)
|
||||
{
|
||||
@ -70,6 +71,7 @@ contract StandardMarket is Market {
|
||||
|
||||
/// @dev Allows market creator to close the markets by transferring all remaining outcome tokens to the creator
|
||||
function close()
|
||||
override
|
||||
public
|
||||
isCreator
|
||||
atStage(Stages.MarketFunded)
|
||||
@ -85,6 +87,7 @@ contract StandardMarket is Market {
|
||||
/// @return Fee amount
|
||||
function withdrawFees()
|
||||
public
|
||||
override
|
||||
isCreator
|
||||
returns (uint fees)
|
||||
{
|
||||
@ -101,6 +104,7 @@ contract StandardMarket is Market {
|
||||
/// @return Cost in collateral tokens
|
||||
function buy(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint maxCost)
|
||||
public
|
||||
override
|
||||
atStage(Stages.MarketFunded)
|
||||
returns (uint cost)
|
||||
{
|
||||
@ -131,6 +135,7 @@ contract StandardMarket is Market {
|
||||
/// @return Profit in collateral tokens
|
||||
function sell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit)
|
||||
public
|
||||
override
|
||||
atStage(Stages.MarketFunded)
|
||||
returns (uint profit)
|
||||
{
|
||||
@ -161,6 +166,7 @@ contract StandardMarket is Market {
|
||||
/// @return Cost to short sell outcome in collateral tokens
|
||||
function shortSell(uint8 outcomeTokenIndex, uint outcomeTokenCount, uint minProfit)
|
||||
public
|
||||
override
|
||||
returns (uint cost)
|
||||
{
|
||||
// Buy all outcomes
|
||||
@ -186,6 +192,7 @@ contract StandardMarket is Market {
|
||||
/// @return Fee for trade
|
||||
function calcMarketFee(uint outcomeTokenCost)
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (uint)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ contract StandardMarketFactory is MarketFactory {
|
||||
/// @return Market contract
|
||||
function createMarket(Event eventContract, MarketMaker marketMaker, uint24 fee)
|
||||
public
|
||||
override
|
||||
returns (Market market)
|
||||
{
|
||||
market = new StandardMarket(msg.sender, eventContract, marketMaker, fee);
|
||||
|
@ -72,6 +72,7 @@ contract CentralizedOracle is Oracle {
|
||||
/// @return Is outcome set?
|
||||
function isOutcomeSet()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
@ -82,6 +83,7 @@ contract CentralizedOracle is Oracle {
|
||||
/// @return Outcome
|
||||
function getOutcome()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (int)
|
||||
{
|
||||
|
@ -44,6 +44,7 @@ contract DifficultyOracle is Oracle {
|
||||
/// @return Is outcome set?
|
||||
function isOutcomeSet()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
@ -55,6 +56,7 @@ contract DifficultyOracle is Oracle {
|
||||
/// @return Outcome
|
||||
function getOutcome()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (int)
|
||||
{
|
||||
|
@ -151,6 +151,7 @@ contract FutarchyOracle is Oracle {
|
||||
/// @return Is outcome set?
|
||||
function isOutcomeSet()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
@ -161,6 +162,7 @@ contract FutarchyOracle is Oracle {
|
||||
/// @return Outcome
|
||||
function getOutcome()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (int)
|
||||
{
|
||||
|
@ -70,6 +70,7 @@ contract MajorityOracle is Oracle {
|
||||
/// @return Is outcome set?
|
||||
function isOutcomeSet()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
@ -81,6 +82,7 @@ contract MajorityOracle is Oracle {
|
||||
/// @return Outcome
|
||||
function getOutcome()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (int)
|
||||
{
|
||||
|
@ -84,6 +84,7 @@ contract SignedMessageOracle is Oracle {
|
||||
/// @return Is outcome set?
|
||||
function isOutcomeSet()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
@ -94,6 +95,7 @@ contract SignedMessageOracle is Oracle {
|
||||
/// @return Outcome
|
||||
function getOutcome()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (int)
|
||||
{
|
||||
|
@ -174,6 +174,7 @@ contract UltimateOracle is Oracle {
|
||||
/// @return Is outcome set?
|
||||
function isOutcomeSet()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
@ -185,6 +186,7 @@ contract UltimateOracle is Oracle {
|
||||
/// @return Outcome
|
||||
function getOutcome()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (int)
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ contract StandardToken is Token {
|
||||
/// @return Was transfer successful?
|
||||
function transfer(address to, uint value)
|
||||
public
|
||||
override
|
||||
returns (bool)
|
||||
{
|
||||
if ( !balances[msg.sender].safeToSub(value)
|
||||
@ -41,6 +42,7 @@ contract StandardToken is Token {
|
||||
/// @return Was transfer successful?
|
||||
function transferFrom(address from, address to, uint value)
|
||||
public
|
||||
override
|
||||
returns (bool)
|
||||
{
|
||||
if ( !balances[from].safeToSub(value)
|
||||
@ -60,6 +62,7 @@ contract StandardToken is Token {
|
||||
/// @return Was approval successful?
|
||||
function approve(address spender, uint value)
|
||||
public
|
||||
override
|
||||
returns (bool)
|
||||
{
|
||||
allowances[msg.sender][spender] = value;
|
||||
@ -73,6 +76,7 @@ contract StandardToken is Token {
|
||||
/// @return Remaining allowance for spender
|
||||
function allowance(address owner, address spender)
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (uint)
|
||||
{
|
||||
@ -84,6 +88,7 @@ contract StandardToken is Token {
|
||||
/// @return Balance of owner
|
||||
function balanceOf(address owner)
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (uint)
|
||||
{
|
||||
@ -94,6 +99,7 @@ contract StandardToken is Token {
|
||||
/// @return Total supply
|
||||
function totalSupply()
|
||||
public
|
||||
override
|
||||
view
|
||||
returns (uint)
|
||||
{
|
||||
|
@ -55,11 +55,11 @@ contract Registrar is NameRegister {
|
||||
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 view returns (address o_address);
|
||||
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 name(address _owner) public view returns (string memory o_name);
|
||||
function name(address _owner) public override view returns (string memory o_name);
|
||||
}
|
||||
|
||||
contract AuctionSystem {
|
||||
@ -119,7 +119,7 @@ contract GlobalRegistrar is Registrar, AuctionSystem {
|
||||
// TODO: Populate with hall-of-fame.
|
||||
}
|
||||
|
||||
function onAuctionEnd(string memory _name) internal {
|
||||
function onAuctionEnd(string memory _name) internal override {
|
||||
Auction storage auction = m_auctions[_name];
|
||||
Record storage record = m_toRecord[_name];
|
||||
address previousOwner = record.owner;
|
||||
@ -204,11 +204,11 @@ contract GlobalRegistrar is Registrar, AuctionSystem {
|
||||
return true;
|
||||
}
|
||||
|
||||
function owner(string memory _name) public view returns (address) { return m_toRecord[_name].owner; }
|
||||
function addr(string memory _name) public view returns (address) { return m_toRecord[_name].primary; }
|
||||
function subRegistrar(string memory _name) public view returns (address) { return m_toRecord[_name].subRegistrar; }
|
||||
function content(string memory _name) public view returns (bytes32) { return m_toRecord[_name].content; }
|
||||
function name(address _addr) public view returns (string memory o_name) { return m_toName[_addr]; }
|
||||
function owner(string memory _name) public override view returns (address) { return m_toRecord[_name].owner; }
|
||||
function addr(string memory _name) public override view returns (address) { return m_toRecord[_name].primary; }
|
||||
function subRegistrar(string memory _name) public override view returns (address) { return m_toRecord[_name].subRegistrar; }
|
||||
function content(string memory _name) public override view returns (bytes32) { return m_toRecord[_name].content; }
|
||||
function name(address _addr) public override view returns (string memory o_name) { return m_toName[_addr]; }
|
||||
|
||||
mapping (address => string) m_toName;
|
||||
mapping (string => Record) m_toRecord;
|
||||
|
@ -111,10 +111,10 @@ contract FixedFeeRegistrar is Registrar {
|
||||
o_content = rec.content;
|
||||
o_owner = rec.owner;
|
||||
}
|
||||
function addr(string memory _name) public view returns (address) { return m_record(_name).addr; }
|
||||
function subRegistrar(string memory _name) public view returns (address) { return m_record(_name).subRegistrar; }
|
||||
function content(string memory _name) public view returns (bytes32) { return m_record(_name).content; }
|
||||
function owner(string memory _name) public view returns (address) { return m_record(_name).owner; }
|
||||
function addr(string memory _name) public override view returns (address) { return m_record(_name).addr; }
|
||||
function subRegistrar(string memory _name) public override view returns (address) { return m_record(_name).subRegistrar; }
|
||||
function content(string memory _name) public override view returns (bytes32) { return m_record(_name).content; }
|
||||
function owner(string memory _name) public override view returns (address) { return m_record(_name).owner; }
|
||||
|
||||
Record[2**253] m_recordData;
|
||||
function m_record(string memory _name) view internal returns (Record storage o_record) {
|
||||
|
@ -128,7 +128,7 @@ contract multiowned {
|
||||
}
|
||||
|
||||
// Replaces an owner `_from` with another `_to`.
|
||||
function changeOwner(address _from, address _to) onlymanyowners(keccak256(msg.data)) external {
|
||||
function changeOwner(address _from, address _to) onlymanyowners(keccak256(msg.data)) public {
|
||||
if (isOwner(_to)) return;
|
||||
uint ownerIndex = m_ownerIndex[uint(_from)];
|
||||
if (ownerIndex == 0) return;
|
||||
@ -347,7 +347,7 @@ contract multisig {
|
||||
// FUNCTIONS
|
||||
|
||||
// TODO: document
|
||||
function changeOwner(address _from, address _to) external;
|
||||
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);
|
||||
}
|
||||
@ -374,6 +374,9 @@ contract Wallet is multisig, multiowned, daylimit {
|
||||
multiowned(_owners, _required) daylimit(_daylimit) {
|
||||
}
|
||||
|
||||
function changeOwner(address _from, address _to) public override(multiowned, multisig) {
|
||||
multiowned.changeOwner(_from, _to);
|
||||
}
|
||||
// destroys the contract sending everything to `_to`.
|
||||
function kill(address payable _to) onlymanyowners(keccak256(msg.data)) external {
|
||||
selfdestruct(_to);
|
||||
@ -390,7 +393,7 @@ contract Wallet is multisig, multiowned, daylimit {
|
||||
// If not, goes into multisig process. We provide a hash on return to allow the sender to provide
|
||||
// shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value
|
||||
// and _data arguments). They still get the option of using them if they want, anyways.
|
||||
function execute(address _to, uint _value, bytes calldata _data) external onlyowner returns (bytes32 _r) {
|
||||
function execute(address _to, uint _value, bytes calldata _data) external override onlyowner returns (bytes32 _r) {
|
||||
// first, take the opportunity to check that we're under the daily limit.
|
||||
if (underLimit(_value)) {
|
||||
emit SingleTransact(msg.sender, _value, _to, _data);
|
||||
@ -410,7 +413,7 @@ contract Wallet is multisig, multiowned, daylimit {
|
||||
|
||||
// confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order
|
||||
// to determine the body of the transaction from the hash provided.
|
||||
function confirm(bytes32 _h) onlymanyowners(_h) public returns (bool) {
|
||||
function confirm(bytes32 _h) onlymanyowners(_h) public override returns (bool) {
|
||||
if (m_txs[_h].to != 0x0000000000000000000000000000000000000000) {
|
||||
m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data);
|
||||
emit MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data);
|
||||
@ -421,7 +424,7 @@ contract Wallet is multisig, multiowned, daylimit {
|
||||
|
||||
// INTERNAL METHODS
|
||||
|
||||
function clearPending() internal {
|
||||
function clearPending() internal override {
|
||||
uint length = m_pendingIndex.length;
|
||||
for (uint i = 0; i < length; ++i)
|
||||
delete m_txs[m_pendingIndex[i]];
|
||||
|
@ -397,7 +397,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
}
|
||||
|
||||
|
||||
function receiveEther() public returns (bool) {
|
||||
function receiveEther() public override returns (bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -409,7 +409,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
bytes memory _transactionData,
|
||||
uint _debatingPeriod,
|
||||
bool _newCurator
|
||||
) onlyTokenholders public payable returns (uint _proposalID) {
|
||||
) onlyTokenholders public override payable returns (uint _proposalID) {
|
||||
|
||||
// Sanity check
|
||||
if (_newCurator && (
|
||||
@ -479,7 +479,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
address payable _recipient,
|
||||
uint _amount,
|
||||
bytes memory _transactionData
|
||||
) public view returns (bool _codeChecksOut) {
|
||||
) public override view returns (bool _codeChecksOut) {
|
||||
Proposal storage p = proposals[_proposalID];
|
||||
return p.proposalHash == keccak256(abi.encodePacked(_recipient, _amount, _transactionData));
|
||||
}
|
||||
@ -488,7 +488,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
function vote(
|
||||
uint _proposalID,
|
||||
bool _supportsProposal
|
||||
) onlyTokenholders public returns (uint _voteID) {
|
||||
) onlyTokenholders public override returns (uint _voteID) {
|
||||
|
||||
Proposal storage p = proposals[_proposalID];
|
||||
if (p.votedYes[msg.sender]
|
||||
@ -521,7 +521,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
function executeProposal(
|
||||
uint _proposalID,
|
||||
bytes memory _transactionData
|
||||
) public returns (bool _success) {
|
||||
) public override returns (bool _success) {
|
||||
|
||||
Proposal storage p = proposals[_proposalID];
|
||||
|
||||
@ -622,7 +622,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
function splitDAO(
|
||||
uint _proposalID,
|
||||
address payable _newCurator
|
||||
) onlyTokenholders public returns (bool _success) {
|
||||
) onlyTokenholders public override returns (bool _success) {
|
||||
|
||||
Proposal storage p = proposals[_proposalID];
|
||||
|
||||
@ -694,7 +694,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
return true;
|
||||
}
|
||||
|
||||
function newContract(address payable _newContract) public {
|
||||
function newContract(address payable _newContract) public override {
|
||||
if (msg.sender != address(this) || !allowedRecipients[_newContract]) return;
|
||||
// move all ether
|
||||
(bool success,) = _newContract.call.value(address(this).balance)("");
|
||||
@ -710,7 +710,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
}
|
||||
|
||||
|
||||
function retrieveDAOReward(bool _toMembers) external returns (bool _success) {
|
||||
function retrieveDAOReward(bool _toMembers) external override returns (bool _success) {
|
||||
DAO dao = DAO(msg.sender);
|
||||
|
||||
if ((rewardToken[msg.sender] * DAOrewardAccount.accumulatedInput()) /
|
||||
@ -735,12 +735,13 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
return true;
|
||||
}
|
||||
|
||||
function getMyReward() public returns (bool _success) {
|
||||
function getMyReward() public override returns (bool _success) {
|
||||
return withdrawRewardFor(msg.sender);
|
||||
}
|
||||
|
||||
|
||||
function withdrawRewardFor(address payable _account) noEther internal returns (bool _success) {
|
||||
function withdrawRewardFor(address payable _account) noEther internal
|
||||
override returns (bool _success) {
|
||||
if ((balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply < paidOut[_account])
|
||||
revert();
|
||||
|
||||
@ -756,7 +757,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
}
|
||||
|
||||
|
||||
function transfer(address _to, uint256 _value) public returns (bool success) {
|
||||
function transfer(address _to, uint256 _value) public override returns (bool success) {
|
||||
if (isFueled
|
||||
&& now > closingTime
|
||||
&& !isBlocked(msg.sender)
|
||||
@ -771,14 +772,15 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
}
|
||||
|
||||
|
||||
function transferWithoutReward(address _to, uint256 _value) public returns (bool success) {
|
||||
function transferWithoutReward(address _to, uint256 _value) public override returns (bool success) {
|
||||
if (!getMyReward())
|
||||
revert();
|
||||
return transfer(_to, _value);
|
||||
}
|
||||
|
||||
|
||||
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
|
||||
function transferFrom(address _from, address _to, uint256 _value) public
|
||||
override returns (bool success) {
|
||||
if (isFueled
|
||||
&& now > closingTime
|
||||
&& !isBlocked(_from)
|
||||
@ -797,7 +799,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
address payable _from,
|
||||
address _to,
|
||||
uint256 _value
|
||||
) public returns (bool success) {
|
||||
) public override returns (bool success) {
|
||||
|
||||
if (!withdrawRewardFor(_from))
|
||||
revert();
|
||||
@ -820,7 +822,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
}
|
||||
|
||||
|
||||
function changeProposalDeposit(uint _proposalDeposit) external {
|
||||
function changeProposalDeposit(uint _proposalDeposit) external override {
|
||||
if (msg.sender != address(this) || _proposalDeposit > (actualBalance() + rewardToken[address(this)])
|
||||
/ maxDepositDivisor) {
|
||||
|
||||
@ -830,7 +832,8 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
}
|
||||
|
||||
|
||||
function changeAllowedRecipients(address _recipient, bool _allowed) external returns (bool _success) {
|
||||
function changeAllowedRecipients(address _recipient, bool _allowed) external
|
||||
override returns (bool _success) {
|
||||
if (msg.sender != curator)
|
||||
revert();
|
||||
allowedRecipients[_recipient] = _allowed;
|
||||
@ -862,7 +865,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
}
|
||||
|
||||
|
||||
function halveMinQuorum() public returns (bool _success) {
|
||||
function halveMinQuorum() public override returns (bool _success) {
|
||||
// this can only be called after `quorumHalvingPeriod` has passed or at anytime after
|
||||
// fueling by the curator with a delay of at least `minProposalDebatePeriod`
|
||||
// between the calls
|
||||
@ -891,16 +894,16 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
);
|
||||
}
|
||||
|
||||
function numberOfProposals() public view returns (uint _numberOfProposals) {
|
||||
function numberOfProposals() public view override returns (uint _numberOfProposals) {
|
||||
// Don't count index 0. It's used by isBlocked() and exists from start
|
||||
return proposals.length - 1;
|
||||
}
|
||||
|
||||
function getNewDAOAddress(uint _proposalID) public view returns (address _newDAO) {
|
||||
function getNewDAOAddress(uint _proposalID) public override view returns (address _newDAO) {
|
||||
return address(proposals[_proposalID].splitData[0].newDAO);
|
||||
}
|
||||
|
||||
function isBlocked(address _account) internal returns (bool) {
|
||||
function isBlocked(address _account) internal override returns (bool) {
|
||||
if (blocked[_account] == 0)
|
||||
return false;
|
||||
Proposal storage p = proposals[blocked[_account]];
|
||||
@ -912,7 +915,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
|
||||
}
|
||||
}
|
||||
|
||||
function unblockMe() public returns (bool) {
|
||||
function unblockMe() public override returns (bool) {
|
||||
return isBlocked(msg.sender);
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ contract ManagedAccount is ManagedAccountInterface{
|
||||
accumulatedInput += msg.value;
|
||||
}
|
||||
|
||||
function payOut(address payable _recipient, uint _amount) public returns (bool) {
|
||||
function payOut(address payable _recipient, uint _amount) public override returns (bool) {
|
||||
if (msg.sender != owner || (payOwnerOnly && _recipient != owner))
|
||||
revert();
|
||||
(bool success,) = _recipient.call.value(_amount)("");
|
||||
|
@ -94,11 +94,11 @@ contract Token is TokenInterface {
|
||||
// inadvertently also transferred ether
|
||||
modifier noEther() {if (msg.value > 0) revert(); _; }
|
||||
|
||||
function balanceOf(address _owner) public view returns (uint256 balance) {
|
||||
function balanceOf(address _owner) public override view returns (uint256 balance) {
|
||||
return balances[_owner];
|
||||
}
|
||||
|
||||
function transfer(address _to, uint256 _amount) public returns (bool success) {
|
||||
function transfer(address _to, uint256 _amount) public override returns (bool success) {
|
||||
if (balances[msg.sender] >= _amount && _amount > 0) {
|
||||
balances[msg.sender] -= _amount;
|
||||
balances[_to] += _amount;
|
||||
@ -113,7 +113,7 @@ contract Token is TokenInterface {
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _amount
|
||||
) public returns (bool success) {
|
||||
) public override returns (bool success) {
|
||||
|
||||
if (balances[_from] >= _amount
|
||||
&& allowed[_from][msg.sender] >= _amount
|
||||
@ -129,7 +129,7 @@ contract Token is TokenInterface {
|
||||
}
|
||||
}
|
||||
|
||||
function approve(address _spender, uint256 _amount) public returns (bool success) {
|
||||
function approve(address _spender, uint256 _amount) public override returns (bool success) {
|
||||
allowed[msg.sender][_spender] = _amount;
|
||||
emit Approval(msg.sender, _spender, _amount);
|
||||
return true;
|
||||
@ -144,7 +144,7 @@ contract Token is TokenInterface {
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
|
||||
function allowance(address _owner, address _spender) public override view returns (uint256 remaining) {
|
||||
return allowed[_owner][_spender];
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,8 @@ contract TokenCreation is TokenCreationInterface, Token {
|
||||
|
||||
}
|
||||
|
||||
function createTokenProxy(address payable _tokenHolder) payable public returns (bool success) {
|
||||
function createTokenProxy(address payable _tokenHolder) payable public
|
||||
override returns (bool success) {
|
||||
if (now < closingTime && msg.value > 0
|
||||
&& (privateCreation == 0x0000000000000000000000000000000000000000 || privateCreation == msg.sender)) {
|
||||
|
||||
@ -119,7 +120,7 @@ contract TokenCreation is TokenCreationInterface, Token {
|
||||
revert();
|
||||
}
|
||||
|
||||
function refund() public {
|
||||
function refund() public override {
|
||||
if (now > closingTime && !isFueled) {
|
||||
// Get extraBalance - will only succeed when called for the first time
|
||||
if (address(extraBalance).balance >= extraBalance.accumulatedInput())
|
||||
@ -136,7 +137,7 @@ contract TokenCreation is TokenCreationInterface, Token {
|
||||
}
|
||||
}
|
||||
|
||||
function divisor() public view returns (uint divisor) {
|
||||
function divisor() public override view returns (uint divisor) {
|
||||
// The number of (base unit) tokens per wei is calculated
|
||||
// as `msg.value` * 20 / `divisor`
|
||||
// The fueling period starts with a 1:1 ratio
|
||||
|
@ -219,14 +219,14 @@ BOOST_AUTO_TEST_CASE(metadata_relevant_sources_imports)
|
||||
pragma solidity >=0.0;
|
||||
import "./A";
|
||||
contract B is A {
|
||||
function g(function(uint) external returns (uint) x) public {}
|
||||
function g(function(uint) external returns (uint) x) public override {}
|
||||
}
|
||||
)";
|
||||
char const* sourceCodeC = R"(
|
||||
pragma solidity >=0.0;
|
||||
import "./B";
|
||||
contract C is B {
|
||||
function g(function(uint) external returns (uint) x) public {}
|
||||
function g(function(uint) external returns (uint) x) public override {}
|
||||
}
|
||||
)";
|
||||
compilerStack.setSources({
|
||||
|
@ -2113,7 +2113,7 @@ BOOST_AUTO_TEST_CASE(virtual_function_calls)
|
||||
function g() public returns (uint i) { return 1; }
|
||||
}
|
||||
contract Derived is Base {
|
||||
function g() public returns (uint i) { return 2; }
|
||||
function g() public override returns (uint i) { return 2; }
|
||||
}
|
||||
)";
|
||||
ALSO_VIA_YUL(
|
||||
@ -2175,10 +2175,10 @@ 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 returns (uint r) { return 2; } }
|
||||
contract Base is BaseBase { function g() public override returns (uint r) { return 2; } }
|
||||
contract Derived is Base {
|
||||
function f() public returns (uint r) { return BaseBase.g(); }
|
||||
function g() public returns (uint r) { return 3; }
|
||||
function g() public override returns (uint r) { return 3; }
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "Derived");
|
||||
@ -2243,7 +2243,7 @@ BOOST_AUTO_TEST_CASE(virtual_function_usage_in_constructor_arguments)
|
||||
}
|
||||
contract Derived is Base() {
|
||||
function getA() public returns (uint r) { return m_a; }
|
||||
function overridden() public returns (uint r) { return 2; }
|
||||
function overridden() public override returns (uint r) { return 2; }
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "Derived");
|
||||
@ -2335,7 +2335,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_overriding)
|
||||
modifier mod { _; }
|
||||
}
|
||||
contract C is A {
|
||||
modifier mod { if (false) _; }
|
||||
modifier mod override { if (false) _; }
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
@ -2356,8 +2356,8 @@ BOOST_AUTO_TEST_CASE(function_modifier_calling_functions_in_creation_context)
|
||||
function getData() public returns (uint r) { return data; }
|
||||
}
|
||||
contract C is A {
|
||||
modifier mod1 { f4(); _; }
|
||||
function f3() public { data |= 0x300; }
|
||||
modifier mod1 override { f4(); _; }
|
||||
function f3() public override { data |= 0x300; }
|
||||
function f4() public { data |= 0x4000; }
|
||||
}
|
||||
)";
|
||||
@ -2375,7 +2375,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_for_constructor)
|
||||
function getData() public returns (uint r) { return data; }
|
||||
}
|
||||
contract C is A {
|
||||
modifier mod1 { data |= 4; _; }
|
||||
modifier mod1 override { data |= 4; _; }
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
@ -2483,9 +2483,9 @@ 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 returns (uint r) { return super.f() | 2; } }
|
||||
contract C is A { function f() public returns (uint r) { return super.f() | 4; } }
|
||||
contract D is B, C { function f() public returns (uint r) { return super.f() | 8; } }
|
||||
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 D is B, C { function f() public override(B, C) returns (uint r) { return super.f() | 8; } }
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "D");
|
||||
ABI_CHECK(callContractFunction("f()"), encodeArgs(1 | 2 | 4 | 8));
|
||||
@ -2495,9 +2495,9 @@ 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 returns (uint r) { return super.f() | 2; } }
|
||||
contract C is A { function f() public returns (uint r) { return super.f() | 4; } }
|
||||
contract D is B, C { uint data; constructor() public { data = super.f() | 8; } function f() public returns (uint r) { return data; } }
|
||||
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 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");
|
||||
ABI_CHECK(callContractFunction("f()"), encodeArgs(1 | 2 | 4 | 8));
|
||||
@ -6018,9 +6018,11 @@ BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes)
|
||||
|
||||
contract init_fix is init, fix {
|
||||
function checkOk() public returns (bool) { return ok; }
|
||||
function isOk() public override (init, fix) returns (bool) { return super.isOk(); }
|
||||
}
|
||||
contract fix_init is fix, init {
|
||||
function checkOk() public returns (bool) { return ok; }
|
||||
function isOk() public override (init, fix) returns (bool) { return super.isOk(); }
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "init_fix");
|
||||
@ -7983,7 +7985,7 @@ BOOST_AUTO_TEST_CASE(inherited_function) {
|
||||
char const* sourceCode = R"(
|
||||
contract A { function f() internal returns (uint) { return 1; } }
|
||||
contract B is A {
|
||||
function f() internal returns (uint) { return 2; }
|
||||
function f() internal override returns (uint) { return 2; }
|
||||
function g() public returns (uint) {
|
||||
return A.f();
|
||||
}
|
||||
@ -7998,7 +8000,7 @@ 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 B is A {
|
||||
function f(uint[] memory a) public returns (uint) { return a[1]; }
|
||||
function f(uint[] memory a) public override returns (uint) { return a[1]; }
|
||||
function g() public returns (uint) {
|
||||
uint[] memory m = new uint[](2);
|
||||
m[0] = 42;
|
||||
@ -8015,7 +8017,7 @@ BOOST_AUTO_TEST_CASE(inherited_function_calldata_memory) {
|
||||
BOOST_AUTO_TEST_CASE(inherited_function_calldata_memory_interface) {
|
||||
char const* sourceCode = R"(
|
||||
interface I { function f(uint[] calldata a) external returns (uint); }
|
||||
contract A is I { function f(uint[] memory a) public returns (uint) { return 42; } }
|
||||
contract A is I { function f(uint[] memory a) public override returns (uint) { return 42; } }
|
||||
contract B {
|
||||
function f(uint[] memory a) public returns (uint) { return a[1]; }
|
||||
function g() public returns (uint) {
|
||||
@ -8032,7 +8034,7 @@ BOOST_AUTO_TEST_CASE(inherited_function_calldata_memory_interface) {
|
||||
BOOST_AUTO_TEST_CASE(inherited_function_calldata_calldata_interface) {
|
||||
char const* sourceCode = R"(
|
||||
interface I { function f(uint[] calldata a) external returns (uint); }
|
||||
contract A is I { function f(uint[] calldata a) external returns (uint) { return 42; } }
|
||||
contract A is I { function f(uint[] calldata a) external override returns (uint) { return 42; } }
|
||||
contract B {
|
||||
function f(uint[] memory a) public returns (uint) { return a[1]; }
|
||||
function g() public returns (uint) {
|
||||
@ -12471,7 +12473,7 @@ BOOST_AUTO_TEST_CASE(interface_contract)
|
||||
}
|
||||
|
||||
contract A is I {
|
||||
function f() public returns (bool) {
|
||||
function f() public override returns (bool) {
|
||||
return g();
|
||||
}
|
||||
|
||||
@ -14479,7 +14481,7 @@ BOOST_AUTO_TEST_CASE(external_public_override)
|
||||
function f() external returns (uint) { return 1; }
|
||||
}
|
||||
contract B is A {
|
||||
function f() public returns (uint) { return 2; }
|
||||
function f() public override returns (uint) { return 2; }
|
||||
function g() public returns (uint) { return f(); }
|
||||
}
|
||||
)";
|
||||
@ -14647,7 +14649,7 @@ BOOST_AUTO_TEST_CASE(contract_name)
|
||||
}
|
||||
}
|
||||
contract D is C {
|
||||
function name() public pure returns (string memory) {
|
||||
function name() public override pure returns (string memory) {
|
||||
return type(D).name;
|
||||
}
|
||||
function name2() public pure returns (string memory) {
|
||||
|
@ -65,7 +65,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract)
|
||||
SourceUnit const* sourceUnit = nullptr;
|
||||
char const* text = R"(
|
||||
contract base { function foo() public; }
|
||||
contract derived is base { function foo() public {} }
|
||||
contract derived is base { function foo() public override {} }
|
||||
)";
|
||||
sourceUnit = parseAndAnalyse(text);
|
||||
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
|
||||
|
@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(type_identifiers)
|
||||
// TypeType is tested with contract
|
||||
|
||||
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$__$");
|
||||
|
||||
SourceUnit su({}, {});
|
||||
|
@ -11,11 +11,11 @@ contract BaseBase {
|
||||
}
|
||||
|
||||
contract Base is BaseBase {
|
||||
function init(uint a, uint b) public {
|
||||
function init(uint a, uint b) public override {
|
||||
x = a;
|
||||
y = b;
|
||||
}
|
||||
function init(uint a) public {
|
||||
function init(uint a) public override {
|
||||
x = a;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ contract C is X {
|
||||
// explicit call via base
|
||||
//x = super.g();
|
||||
}
|
||||
function g() public returns (uint x) {
|
||||
function g() public override returns (uint x) {
|
||||
x = 3;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
contract B { function f() 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".
|
||||
|
@ -6,8 +6,8 @@ contract A {
|
||||
function i(uint[] calldata) external payable {}
|
||||
}
|
||||
contract B is A {
|
||||
function f(uint[] memory) public pure {}
|
||||
function g(uint[] memory) public view { dummy; }
|
||||
function h(uint[] memory) public { dummy = 42; }
|
||||
function i(uint[] memory) public payable {}
|
||||
function f(uint[] memory) public override pure {}
|
||||
function g(uint[] memory) public override view { dummy; }
|
||||
function h(uint[] memory) public override { dummy = 42; }
|
||||
function i(uint[] memory) public override payable {}
|
||||
}
|
||||
|
@ -6,21 +6,17 @@ contract A {
|
||||
function i(uint[] calldata) external payable {}
|
||||
}
|
||||
contract B is A {
|
||||
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[] memory) public pure {}
|
||||
function g(uint[] memory) public view { dummy; }
|
||||
function h(uint[] memory) public { dummy = 42; }
|
||||
function i(uint[] memory) public payable {}
|
||||
function f(uint[] calldata) external override pure {}
|
||||
function g(uint[] calldata) external override view { dummy; }
|
||||
function h(uint[] calldata) external override { dummy = 42; }
|
||||
function i(uint[] calldata) external override payable {}
|
||||
function f(uint[] memory) public override pure {}
|
||||
function g(uint[] memory) public override view { dummy; }
|
||||
function h(uint[] memory) public override { dummy = 42; }
|
||||
function i(uint[] memory) public override payable {}
|
||||
}
|
||||
// ----
|
||||
// DeclarationError: (268-312): Function with same name and arguments defined twice.
|
||||
// DeclarationError: (317-369): Function with same name and arguments defined twice.
|
||||
// DeclarationError: (374-426): Function with same name and arguments defined twice.
|
||||
// DeclarationError: (431-478): Function with same name and arguments defined twice.
|
||||
// TypeError: (268-312): Overriding function visibility differs.
|
||||
// TypeError: (317-369): Overriding function visibility differs.
|
||||
// TypeError: (374-426): Overriding function visibility differs.
|
||||
// TypeError: (431-478): Overriding function visibility differs.
|
||||
// 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.
|
||||
|
@ -6,8 +6,8 @@ interface I {
|
||||
}
|
||||
contract C is I {
|
||||
uint dummy;
|
||||
function f(uint[] memory) public pure {}
|
||||
function g(uint[] memory) public view { dummy; }
|
||||
function h(uint[] memory) public { dummy = 42; }
|
||||
function i(uint[] memory) public payable {}
|
||||
function f(uint[] memory) public override pure {}
|
||||
function g(uint[] memory) public override view { dummy; }
|
||||
function h(uint[] memory) public override { dummy = 42; }
|
||||
function i(uint[] memory) public override payable {}
|
||||
}
|
||||
|
@ -2,11 +2,11 @@ interface I {
|
||||
function f(uint[] calldata) external pure;
|
||||
}
|
||||
contract A is I {
|
||||
function f(uint[] memory) public pure {}
|
||||
function f(uint[] memory) public override pure {}
|
||||
}
|
||||
contract C {
|
||||
function f() public {
|
||||
I i = I(new A());
|
||||
i.f(new uint[](1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ interface I {
|
||||
}
|
||||
contract C is I {
|
||||
uint dummy;
|
||||
function f(S memory) public pure {}
|
||||
function g(S memory) public view { dummy; }
|
||||
function h(S memory) public { dummy = 42; }
|
||||
function i(S memory) public payable {}
|
||||
function f(S memory) public override pure {}
|
||||
function g(S memory) public override view { dummy; }
|
||||
function h(S memory) public override { dummy = 42; }
|
||||
function i(S memory) public override payable {}
|
||||
}
|
||||
// ----
|
||||
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||
|
@ -8,10 +8,10 @@ contract A {
|
||||
function i(S calldata) external payable {}
|
||||
}
|
||||
contract B is A {
|
||||
function f(S memory) public pure {}
|
||||
function g(S memory) public view { dummy; }
|
||||
function h(S memory) public { dummy = 42; }
|
||||
function i(S memory) public payable {}
|
||||
function f(S memory) public override pure {}
|
||||
function g(S memory) public override view { dummy; }
|
||||
function h(S memory) public override { dummy = 42; }
|
||||
function i(S memory) public override payable {}
|
||||
}
|
||||
// ----
|
||||
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||
|
@ -7,4 +7,5 @@ contract B is I {
|
||||
function f() public pure returns (uint, uint) {}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (182-230): Overriding function is missing 'override' specifier.
|
||||
// TypeError: (182-230): Overriding function return types differ.
|
||||
|
@ -2,6 +2,6 @@ contract A {
|
||||
function f() external pure {}
|
||||
}
|
||||
contract B is A {
|
||||
function f() public pure {
|
||||
function f() public override pure {
|
||||
}
|
||||
}
|
||||
|
@ -4,4 +4,3 @@ contract A {
|
||||
}
|
||||
// ----
|
||||
// DeclarationError: (17-61): Function with same name and arguments defined twice.
|
||||
// TypeError: (17-61): Overriding function visibility differs.
|
||||
|
@ -6,4 +6,4 @@ contract B {
|
||||
}
|
||||
contract C is A, B {}
|
||||
// ----
|
||||
// TypeError: (81-123): Overriding function visibility differs.
|
||||
// TypeError: (126-147): Derived contract must override function "f". Function with the same name and parameter types defined in two or more base classes.
|
||||
|
@ -1,5 +1,11 @@
|
||||
contract X {
|
||||
contract A {
|
||||
int public testvar;
|
||||
function test() internal returns (uint256);
|
||||
function test2() internal returns (uint256);
|
||||
}
|
||||
contract X is A {
|
||||
int public override testvar;
|
||||
function test() internal override returns (uint256);
|
||||
function test2() internal override(A) returns (uint256);
|
||||
}
|
||||
// ----
|
||||
|
@ -0,0 +1,14 @@
|
||||
contract A {
|
||||
int public testvar;
|
||||
function foo() internal returns (uint256);
|
||||
}
|
||||
contract B {
|
||||
function foo() internal returns (uint256);
|
||||
function test() internal returns (uint256);
|
||||
}
|
||||
contract X is A, B {
|
||||
int public override testvar;
|
||||
function test() internal override returns (uint256);
|
||||
}
|
||||
// ----
|
||||
// TypeError: (184-290): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes.
|
@ -0,0 +1,20 @@
|
||||
contract A {
|
||||
function foo() internal returns (uint256);
|
||||
}
|
||||
|
||||
contract B is A {
|
||||
function foo() internal override returns (uint256);
|
||||
}
|
||||
|
||||
contract C is B {
|
||||
function foo() internal override returns (uint256);
|
||||
}
|
||||
|
||||
contract D is C {
|
||||
function foo() internal override returns (uint256);
|
||||
}
|
||||
|
||||
contract X is D {
|
||||
function foo() internal override returns (uint256);
|
||||
}
|
||||
// ----
|
@ -1,9 +1,21 @@
|
||||
contract A {
|
||||
int public testvar;
|
||||
function foo() internal returns (uint256);
|
||||
function test(uint8 _a) internal returns (uint256);
|
||||
}
|
||||
contract B {
|
||||
function foo() internal returns (uint256);
|
||||
function test() internal returns (uint256);
|
||||
}
|
||||
contract C {
|
||||
function foo() internal returns (uint256);
|
||||
}
|
||||
contract X {
|
||||
contract D {
|
||||
function foo() internal returns (uint256);
|
||||
}
|
||||
contract X is A, B, C, D {
|
||||
int public override testvar;
|
||||
function test() internal override returns (uint256);
|
||||
function foo() internal override(X, A) returns (uint256);
|
||||
function foo() internal override(A, B, C, D) returns (uint256);
|
||||
}
|
||||
// ----
|
||||
|
@ -0,0 +1,15 @@
|
||||
contract A {
|
||||
int public testvar;
|
||||
function foo() internal returns (uint256);
|
||||
function test(uint8 _a) internal returns (uint256);
|
||||
}
|
||||
contract B {
|
||||
function foo() internal returns (uint256);
|
||||
}
|
||||
|
||||
contract C is A {
|
||||
}
|
||||
contract D is A, B, C {
|
||||
function foo() internal override(A, B) returns (uint256);
|
||||
}
|
||||
// ----
|
@ -0,0 +1,26 @@
|
||||
contract A {
|
||||
int public testvar;
|
||||
function foo() internal returns (uint256);
|
||||
function test(uint8 _a) internal returns (uint256);
|
||||
}
|
||||
contract B {
|
||||
function foo() internal returns (uint256);
|
||||
function test() internal returns (uint256);
|
||||
}
|
||||
contract C {
|
||||
function foo() internal returns (uint256);
|
||||
}
|
||||
contract D {
|
||||
function foo() internal returns (uint256);
|
||||
function test() internal returns (uint256);
|
||||
}
|
||||
contract X is A, B, C, D {
|
||||
int public override testvar;
|
||||
function test() internal override(B, D, D) returns (uint256);
|
||||
function foo() internal override(A, C, B, B, B, D ,D) returns (uint256);
|
||||
}
|
||||
// ----
|
||||
// TypeError: (498-499): Duplicate contract "D" found in override list of "test".
|
||||
// TypeError: (563-564): Duplicate contract "B" found in override list of "foo".
|
||||
// TypeError: (566-567): Duplicate contract "B" found in override list of "foo".
|
||||
// TypeError: (572-573): Duplicate contract "D" found in override list of "foo".
|
@ -0,0 +1,24 @@
|
||||
contract A {
|
||||
int public testvar;
|
||||
function foo() internal returns (uint256);
|
||||
function test(uint8 _a) internal returns (uint256);
|
||||
}
|
||||
contract B {
|
||||
function foo() internal returns (uint256);
|
||||
function test() internal returns (uint256);
|
||||
}
|
||||
contract C {
|
||||
function foo() internal returns (uint256);
|
||||
}
|
||||
contract D {
|
||||
function foo() internal returns (uint256);
|
||||
function test() internal returns (uint256);
|
||||
}
|
||||
contract X is A, B, C, D {
|
||||
int public override testvar;
|
||||
function test() internal override(B, D, C) returns (uint256);
|
||||
function foo() internal override(A, C) returns (uint256);
|
||||
}
|
||||
// ----
|
||||
// TypeError: (483-500): Invalid contract specified in override list: C.
|
||||
// TypeError: (545-559): Function needs to specify overridden contracts B and D.
|
@ -0,0 +1,6 @@
|
||||
contract A {
|
||||
int public testvar;
|
||||
function foo() internal override(N, Z) returns (uint256);
|
||||
}
|
||||
// ----
|
||||
// DeclarationError: (68-69): Identifier not found or not unique.
|
@ -0,0 +1,14 @@
|
||||
contract A {
|
||||
int public testvar;
|
||||
function foo() internal returns (uint256);
|
||||
}
|
||||
contract B {
|
||||
function foo() internal returns (uint8);
|
||||
function test() internal returns (uint256);
|
||||
}
|
||||
contract X is A, B {
|
||||
int public override testvar;
|
||||
function test() internal override returns (uint256);
|
||||
}
|
||||
// ----
|
||||
// TypeError: (182-288): Derived contract must override function "foo". Function with the same name and parameter types defined in two or more base classes.
|
@ -0,0 +1,15 @@
|
||||
contract I {
|
||||
function set() public {}
|
||||
}
|
||||
contract A is I {
|
||||
uint a;
|
||||
function set() public override { a = 1; super.set(); a = 2; }
|
||||
}
|
||||
contract B is I {
|
||||
uint b;
|
||||
function set() public override { b = 1; super.set(); b = 2; }
|
||||
|
||||
}
|
||||
contract X is A, B {
|
||||
function set() public override(A, B) { super.set(); }
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
contract I {
|
||||
function f() external {}
|
||||
}
|
||||
contract A is I {
|
||||
function f() external override {}
|
||||
}
|
||||
contract B is I {}
|
||||
contract C is A, B {
|
||||
function f() external override(A, I) {}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
contract I {
|
||||
function f() external {}
|
||||
}
|
||||
contract A is I {}
|
||||
contract B is I {}
|
||||
contract C is A, B {}
|
@ -0,0 +1,26 @@
|
||||
contract A {
|
||||
int public testvar;
|
||||
function foo() internal returns (uint256);
|
||||
function test(uint8 _a) internal returns (uint256);
|
||||
}
|
||||
contract B {
|
||||
function foo() internal returns (uint256);
|
||||
function test() internal returns (uint256);
|
||||
}
|
||||
contract C {
|
||||
function foo() internal returns (uint256);
|
||||
}
|
||||
contract D {
|
||||
function foo() internal returns (uint256);
|
||||
}
|
||||
contract X is A, B, C, D {
|
||||
struct MyStruct { int abc; }
|
||||
enum ENUM { F,G,H }
|
||||
|
||||
int public override testvar;
|
||||
function test() internal override returns (uint256);
|
||||
function foo() internal override(MyStruct, ENUM, A, B, C, D) returns (uint256);
|
||||
}
|
||||
// ----
|
||||
// TypeError: (552-560): Expected contract but got struct X.MyStruct.
|
||||
// TypeError: (562-566): Expected contract but got enum X.ENUM.
|
@ -1,4 +1,5 @@
|
||||
contract B { function f() 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".
|
||||
|
@ -2,9 +2,9 @@ contract A {
|
||||
function f() external pure {}
|
||||
}
|
||||
contract B is A {
|
||||
function f() public pure {
|
||||
function f() public override pure {
|
||||
super.f();
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (106-113): Member "f" not found or not visible after argument-dependent lookup in contract super B.
|
||||
// TypeError: (115-122): Member "f" not found or not visible after argument-dependent lookup in contract super B.
|
||||
|
@ -1,4 +1,5 @@
|
||||
contract A { modifier mod(uint a) { _; } }
|
||||
contract B is A { modifier mod(uint8 a) { _; } }
|
||||
// ----
|
||||
// TypeError: (61-89): Overriding modifier is missing 'override' specifier.
|
||||
// TypeError: (61-89): Override changes modifier signature.
|
||||
|
@ -1,2 +1,2 @@
|
||||
contract A { modifier mod(uint a) { _; } }
|
||||
contract B is A { modifier mod(uint a) { _; } }
|
||||
contract B is A { modifier mod(uint a) override { _; } }
|
||||
|
@ -2,4 +2,4 @@ contract A { modifier mod(uint a) { _; } }
|
||||
contract B is A { function mod(uint a) public { } }
|
||||
// ----
|
||||
// DeclarationError: (61-92): Identifier already declared.
|
||||
// TypeError: (13-40): Override changes modifier to function.
|
||||
// TypeError: (61-92): Override changes modifier to function.
|
||||
|
@ -1,5 +1,6 @@
|
||||
contract base { function foo() public; }
|
||||
contract derived is base { function foo() public {} }
|
||||
contract derived is base { function foo() public override {} }
|
||||
contract wrong is derived { function foo() public; }
|
||||
// ----
|
||||
// TypeError: (123-145): Redeclaring an already implemented function as abstract
|
||||
// TypeError: (132-154): Overriding function is missing 'override' specifier.
|
||||
// TypeError: (132-154): Redeclaring an already implemented function as abstract
|
||||
|
@ -2,6 +2,7 @@ contract root { function rootFunction() public {} }
|
||||
contract inter1 is root { function f() public {} }
|
||||
contract inter2 is root { function f() public {} }
|
||||
contract derived is root, inter2, inter1 {
|
||||
function g() public { f(); rootFunction(); }
|
||||
function g() public { f(); rootFunction(); }
|
||||
function f() override(inter1, inter2) public {}
|
||||
}
|
||||
// ----
|
||||
|
@ -1,4 +1,5 @@
|
||||
contract B { function f() internal {} }
|
||||
contract C is B { function f() public {} }
|
||||
// ----
|
||||
// TypeError: (58-80): Overriding function is missing 'override' specifier.
|
||||
// TypeError: (58-80): Overriding function visibility differs.
|
||||
|
@ -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 C is A, B { }
|
||||
contract C is A, B { function f() public override (A, B) { A.f(); } }
|
||||
// ----
|
||||
// Warning: (35-42): Unused local variable.
|
||||
|
@ -3,5 +3,5 @@ contract A {
|
||||
function() external { x = 1; }
|
||||
}
|
||||
contract C is A {
|
||||
function() external { x = 2; }
|
||||
function() override external { x = 2; }
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ contract Vehicle {
|
||||
function f(bytes calldata) external returns (uint256 r) {r = 1;}
|
||||
}
|
||||
contract Bike is Vehicle {
|
||||
function f(bytes calldata) 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
|
||||
|
@ -2,7 +2,7 @@ contract base {
|
||||
function f(uint a) public returns (uint) { }
|
||||
}
|
||||
contract test is base {
|
||||
function f(uint a) public returns (uint8) { }
|
||||
function f(uint a) public override returns (uint8) { }
|
||||
}
|
||||
// ----
|
||||
// TypeError: (95-140): Overriding function return types differ.
|
||||
// TypeError: (95-149): Overriding function return types differ.
|
||||
|
@ -4,4 +4,3 @@ contract C {
|
||||
}
|
||||
// ----
|
||||
// DeclarationError: (17-66): Function with same name and arguments defined twice.
|
||||
// TypeError: (17-66): Overriding function return types differ.
|
||||
|
@ -1,4 +1,5 @@
|
||||
contract B { function f() payable 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".
|
||||
|
@ -1,4 +1,5 @@
|
||||
contract B { function f() 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".
|
||||
|
@ -2,7 +2,7 @@ interface I {
|
||||
function f() external;
|
||||
}
|
||||
contract C is I {
|
||||
function f() public {
|
||||
function f() public override {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
|
@ -5,7 +5,7 @@ interface I {
|
||||
function() external;
|
||||
}
|
||||
contract C is I {
|
||||
function f() public {
|
||||
function f() public override {
|
||||
}
|
||||
}
|
||||
// ----
|
||||
|
@ -2,6 +2,6 @@ interface I {
|
||||
function f() external;
|
||||
}
|
||||
contract C is I {
|
||||
function f() public {
|
||||
function f() public override {
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ contract a {
|
||||
function f() public;
|
||||
}
|
||||
contract b is a {
|
||||
function f() public { super.f(); }
|
||||
function f() public override { super.f(); }
|
||||
}
|
||||
// ----
|
||||
// TypeError: (84-91): Member "f" not found or not visible after argument-dependent lookup in contract super b.
|
||||
// TypeError: (93-100): Member "f" not found or not visible after argument-dependent lookup in contract super b.
|
||||
|
@ -2,11 +2,11 @@ contract a {
|
||||
function f() public;
|
||||
}
|
||||
contract b is a {
|
||||
function f() public { super.f(); }
|
||||
function f() public override { super.f(); }
|
||||
}
|
||||
contract c is a,b {
|
||||
// No error here.
|
||||
function f() public { super.f(); }
|
||||
function f() public override(a, b) { super.f(); }
|
||||
}
|
||||
// ----
|
||||
// TypeError: (84-91): Member "f" not found or not visible after argument-dependent lookup in contract super b.
|
||||
// TypeError: (93-100): Member "f" not found or not visible after argument-dependent lookup in contract super b.
|
||||
|
@ -2,5 +2,5 @@ interface D {
|
||||
function f() view external;
|
||||
}
|
||||
contract C is D {
|
||||
function f() view external {}
|
||||
function f() override view external {}
|
||||
}
|
||||
|
@ -4,13 +4,13 @@ contract D {
|
||||
function g() public pure {}
|
||||
}
|
||||
contract C1 is D {
|
||||
function f() public {}
|
||||
function g() public view {}
|
||||
function f() public override {}
|
||||
function g() public override view {}
|
||||
}
|
||||
contract C2 is D {
|
||||
function g() public {}
|
||||
function g() public override {}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (118-140): Overriding function changes state mutability from "view" to "nonpayable".
|
||||
// TypeError: (145-172): Overriding function changes state mutability from "pure" to "view".
|
||||
// TypeError: (198-220): Overriding function changes state mutability from "pure" to "nonpayable".
|
||||
// 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".
|
||||
|
@ -3,5 +3,5 @@ contract D {
|
||||
function f() public { x = 2; }
|
||||
}
|
||||
contract C is D {
|
||||
function f() public {}
|
||||
function f() public override {}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user