mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #12431 from ethereum/fixFun2
Safer constructors for FunctionType
This commit is contained in:
commit
e3bb5ab7b2
@ -73,24 +73,24 @@ inline vector<shared_ptr<MagicVariableDeclaration const>> constructMagicVariable
|
||||
|
||||
return {
|
||||
magicVarDecl("abi", TypeProvider::magic(MagicType::Kind::ABI)),
|
||||
magicVarDecl("addmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, false, StateMutability::Pure)),
|
||||
magicVarDecl("assert", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Assert, false, StateMutability::Pure)),
|
||||
magicVarDecl("addmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, StateMutability::Pure)),
|
||||
magicVarDecl("assert", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Assert, StateMutability::Pure)),
|
||||
magicVarDecl("block", TypeProvider::magic(MagicType::Kind::Block)),
|
||||
magicVarDecl("blockhash", TypeProvider::function(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)),
|
||||
magicVarDecl("ecrecover", TypeProvider::function(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)),
|
||||
magicVarDecl("gasleft", TypeProvider::function(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, false, StateMutability::View)),
|
||||
magicVarDecl("keccak256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)),
|
||||
magicVarDecl("blockhash", TypeProvider::function(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, StateMutability::View)),
|
||||
magicVarDecl("ecrecover", TypeProvider::function(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, StateMutability::Pure)),
|
||||
magicVarDecl("gasleft", TypeProvider::function(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, StateMutability::View)),
|
||||
magicVarDecl("keccak256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, StateMutability::Pure)),
|
||||
magicVarDecl("msg", TypeProvider::magic(MagicType::Kind::Message)),
|
||||
magicVarDecl("mulmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)),
|
||||
magicVarDecl("mulmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, StateMutability::Pure)),
|
||||
magicVarDecl("now", TypeProvider::uint256()),
|
||||
magicVarDecl("require", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)),
|
||||
magicVarDecl("require", TypeProvider::function(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)),
|
||||
magicVarDecl("revert", TypeProvider::function(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)),
|
||||
magicVarDecl("revert", TypeProvider::function(strings{"string memory"}, strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)),
|
||||
magicVarDecl("ripemd160", TypeProvider::function(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, false, StateMutability::Pure)),
|
||||
magicVarDecl("require", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Require, StateMutability::Pure)),
|
||||
magicVarDecl("require", TypeProvider::function(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, StateMutability::Pure)),
|
||||
magicVarDecl("revert", TypeProvider::function(strings(), strings(), FunctionType::Kind::Revert, StateMutability::Pure)),
|
||||
magicVarDecl("revert", TypeProvider::function(strings{"string memory"}, strings(), FunctionType::Kind::Revert, StateMutability::Pure)),
|
||||
magicVarDecl("ripemd160", TypeProvider::function(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, StateMutability::Pure)),
|
||||
magicVarDecl("selfdestruct", TypeProvider::function(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)),
|
||||
magicVarDecl("sha256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, false, StateMutability::Pure)),
|
||||
magicVarDecl("sha3", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)),
|
||||
magicVarDecl("sha256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, StateMutability::Pure)),
|
||||
magicVarDecl("sha3", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, StateMutability::Pure)),
|
||||
magicVarDecl("suicide", TypeProvider::function(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)),
|
||||
magicVarDecl("tx", TypeProvider::magic(MagicType::Kind::Transaction)),
|
||||
// Accepts a MagicType that can be any contract type or an Integer type and returns a
|
||||
@ -99,8 +99,8 @@ inline vector<shared_ptr<MagicVariableDeclaration const>> constructMagicVariable
|
||||
strings{},
|
||||
strings{},
|
||||
FunctionType::Kind::MetaType,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
StateMutability::Pure,
|
||||
FunctionType::Options::withArbitraryParameters()
|
||||
)),
|
||||
};
|
||||
}
|
||||
|
@ -2885,7 +2885,6 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
|
||||
strings(1, ""),
|
||||
strings(1, ""),
|
||||
FunctionType::Kind::ObjectCreation,
|
||||
false,
|
||||
StateMutability::Pure
|
||||
);
|
||||
_newExpression.annotation().isPure = true;
|
||||
|
@ -445,13 +445,18 @@ FunctionType const* TypeProvider::function(
|
||||
strings const& _parameterTypes,
|
||||
strings const& _returnParameterTypes,
|
||||
FunctionType::Kind _kind,
|
||||
bool _arbitraryParameters,
|
||||
StateMutability _stateMutability
|
||||
StateMutability _stateMutability,
|
||||
FunctionType::Options _options
|
||||
)
|
||||
{
|
||||
// Can only use this constructor for "arbitraryParameters".
|
||||
solAssert(!_options.valueSet && !_options.gasSet && !_options.saltSet && !_options.bound);
|
||||
return createAndGet<FunctionType>(
|
||||
_parameterTypes, _returnParameterTypes,
|
||||
_kind, _arbitraryParameters, _stateMutability
|
||||
_parameterTypes,
|
||||
_returnParameterTypes,
|
||||
_kind,
|
||||
_stateMutability,
|
||||
std::move(_options)
|
||||
);
|
||||
}
|
||||
|
||||
@ -461,13 +466,9 @@ FunctionType const* TypeProvider::function(
|
||||
strings _parameterNames,
|
||||
strings _returnParameterNames,
|
||||
FunctionType::Kind _kind,
|
||||
bool _arbitraryParameters,
|
||||
StateMutability _stateMutability,
|
||||
Declaration const* _declaration,
|
||||
bool _gasSet,
|
||||
bool _valueSet,
|
||||
bool _bound,
|
||||
bool _saltSet
|
||||
FunctionType::Options _options
|
||||
)
|
||||
{
|
||||
return createAndGet<FunctionType>(
|
||||
@ -476,13 +477,9 @@ FunctionType const* TypeProvider::function(
|
||||
_parameterNames,
|
||||
_returnParameterNames,
|
||||
_kind,
|
||||
_arbitraryParameters,
|
||||
_stateMutability,
|
||||
_declaration,
|
||||
_gasSet,
|
||||
_valueSet,
|
||||
_bound,
|
||||
_saltSet
|
||||
std::move(_options)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -149,8 +149,8 @@ public:
|
||||
strings const& _parameterTypes,
|
||||
strings const& _returnParameterTypes,
|
||||
FunctionType::Kind _kind = FunctionType::Kind::Internal,
|
||||
bool _arbitraryParameters = false,
|
||||
StateMutability _stateMutability = StateMutability::NonPayable
|
||||
StateMutability _stateMutability = StateMutability::NonPayable,
|
||||
FunctionType::Options _options = {}
|
||||
);
|
||||
|
||||
/// @returns a highly customized FunctionType, use with care.
|
||||
@ -160,13 +160,9 @@ public:
|
||||
strings _parameterNames = strings{},
|
||||
strings _returnParameterNames = strings{},
|
||||
FunctionType::Kind _kind = FunctionType::Kind::Internal,
|
||||
bool _arbitraryParameters = false,
|
||||
StateMutability _stateMutability = StateMutability::NonPayable,
|
||||
Declaration const* _declaration = nullptr,
|
||||
bool _gasSet = false,
|
||||
bool _valueSet = false,
|
||||
bool _bound = false,
|
||||
bool _saltSet = false
|
||||
FunctionType::Options _options = {}
|
||||
);
|
||||
|
||||
/// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does
|
||||
|
@ -470,15 +470,15 @@ MemberList::MemberMap AddressType::nativeMembers(ASTNode const*) const
|
||||
{"balance", TypeProvider::uint256()},
|
||||
{"code", TypeProvider::array(DataLocation::Memory)},
|
||||
{"codehash", TypeProvider::fixedBytes(32)},
|
||||
{"call", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)},
|
||||
{"callcode", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)},
|
||||
{"delegatecall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, false, StateMutability::NonPayable)},
|
||||
{"staticcall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)}
|
||||
{"call", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, StateMutability::Payable)},
|
||||
{"callcode", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, StateMutability::Payable)},
|
||||
{"delegatecall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, StateMutability::NonPayable)},
|
||||
{"staticcall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, StateMutability::View)}
|
||||
};
|
||||
if (m_stateMutability == StateMutability::Payable)
|
||||
{
|
||||
members.emplace_back(MemberList::Member{"send", TypeProvider::function(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send, false, StateMutability::NonPayable)});
|
||||
members.emplace_back(MemberList::Member{"transfer", TypeProvider::function(strings{"uint"}, strings(), FunctionType::Kind::Transfer, false, StateMutability::NonPayable)});
|
||||
members.emplace_back(MemberList::Member{"send", TypeProvider::function(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send, StateMutability::NonPayable)});
|
||||
members.emplace_back(MemberList::Member{"transfer", TypeProvider::function(strings{"uint"}, strings(), FunctionType::Kind::Transfer, StateMutability::NonPayable)});
|
||||
}
|
||||
return members;
|
||||
}
|
||||
@ -2848,7 +2848,6 @@ FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _c
|
||||
parameterNames,
|
||||
strings{""},
|
||||
Kind::Creation,
|
||||
false,
|
||||
stateMutability
|
||||
);
|
||||
}
|
||||
@ -2942,11 +2941,11 @@ string FunctionType::richIdentifier() const
|
||||
}
|
||||
id += "_" + stateMutabilityToString(m_stateMutability);
|
||||
id += identifierList(m_parameterTypes) + "returns" + identifierList(m_returnParameterTypes);
|
||||
if (m_gasSet)
|
||||
if (gasSet())
|
||||
id += "gas";
|
||||
if (m_valueSet)
|
||||
if (valueSet())
|
||||
id += "value";
|
||||
if (m_saltSet)
|
||||
if (saltSet())
|
||||
id += "salt";
|
||||
if (bound())
|
||||
id += "bound_to" + identifierList(selfType());
|
||||
@ -3094,11 +3093,11 @@ bool FunctionType::nameable() const
|
||||
{
|
||||
return
|
||||
(m_kind == Kind::Internal || m_kind == Kind::External) &&
|
||||
!m_bound &&
|
||||
!m_arbitraryParameters &&
|
||||
!m_gasSet &&
|
||||
!m_valueSet &&
|
||||
!m_saltSet;
|
||||
!bound() &&
|
||||
!takesArbitraryParameters() &&
|
||||
!gasSet() &&
|
||||
!valueSet() &&
|
||||
!saltSet();
|
||||
}
|
||||
|
||||
vector<tuple<string, Type const*>> FunctionType::makeStackItems() const
|
||||
@ -3140,11 +3139,11 @@ vector<tuple<string, Type const*>> FunctionType::makeStackItems() const
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_gasSet)
|
||||
if (gasSet())
|
||||
slots.emplace_back("gas", TypeProvider::uint256());
|
||||
if (m_valueSet)
|
||||
if (valueSet())
|
||||
slots.emplace_back("value", TypeProvider::uint256());
|
||||
if (m_saltSet)
|
||||
if (saltSet())
|
||||
slots.emplace_back("salt", TypeProvider::fixedBytes(32));
|
||||
if (bound())
|
||||
slots.emplace_back("self", m_parameterTypes.front());
|
||||
@ -3176,13 +3175,13 @@ FunctionTypePointer FunctionType::interfaceFunctionType() const
|
||||
if (variable && retParamTypes.get().empty())
|
||||
return FunctionTypePointer();
|
||||
|
||||
solAssert(!takesArbitraryParameters());
|
||||
return TypeProvider::function(
|
||||
paramTypes,
|
||||
retParamTypes,
|
||||
m_parameterNames,
|
||||
m_returnParameterNames,
|
||||
m_kind,
|
||||
m_arbitraryParameters,
|
||||
m_stateMutability,
|
||||
m_declaration
|
||||
);
|
||||
@ -3237,12 +3236,9 @@ MemberList::MemberMap FunctionType::nativeMembers(ASTNode const* _scope) const
|
||||
strings(1, ""),
|
||||
strings(1, ""),
|
||||
Kind::SetValue,
|
||||
false,
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
m_gasSet,
|
||||
m_valueSet,
|
||||
m_saltSet
|
||||
Options::fromFunctionType(*this)
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -3255,12 +3251,9 @@ MemberList::MemberMap FunctionType::nativeMembers(ASTNode const* _scope) const
|
||||
strings(1, ""),
|
||||
strings(1, ""),
|
||||
Kind::SetGas,
|
||||
false,
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
m_gasSet,
|
||||
m_valueSet,
|
||||
m_saltSet
|
||||
Options::fromFunctionType(*this)
|
||||
)
|
||||
);
|
||||
return members;
|
||||
@ -3288,7 +3281,7 @@ MemberList::MemberMap FunctionType::nativeMembers(ASTNode const* _scope) const
|
||||
|
||||
Type const* FunctionType::encodingType() const
|
||||
{
|
||||
if (m_gasSet || m_valueSet)
|
||||
if (gasSet() || valueSet())
|
||||
return nullptr;
|
||||
// Only external functions can be encoded, internal functions cannot leave code boundaries.
|
||||
if (m_kind == Kind::External)
|
||||
@ -3307,7 +3300,7 @@ TypeResult FunctionType::interfaceType(bool /*_inLibrary*/) const
|
||||
|
||||
Type const* FunctionType::mobileType() const
|
||||
{
|
||||
if (m_valueSet || m_gasSet || m_saltSet || m_bound)
|
||||
if (valueSet() || gasSet() || saltSet() || bound())
|
||||
return nullptr;
|
||||
|
||||
// return function without parameter names
|
||||
@ -3317,13 +3310,9 @@ Type const* FunctionType::mobileType() const
|
||||
strings(m_parameterTypes.size()),
|
||||
strings(m_returnParameterNames.size()),
|
||||
m_kind,
|
||||
m_arbitraryParameters,
|
||||
m_stateMutability,
|
||||
m_declaration,
|
||||
m_gasSet,
|
||||
m_valueSet,
|
||||
m_bound,
|
||||
m_saltSet
|
||||
Options::fromFunctionType(*this)
|
||||
);
|
||||
}
|
||||
|
||||
@ -3409,7 +3398,7 @@ bool FunctionType::equalExcludingStateMutability(FunctionType const& _other) con
|
||||
return false;
|
||||
|
||||
//@todo this is ugly, but cannot be prevented right now
|
||||
if (m_gasSet != _other.m_gasSet || m_valueSet != _other.m_valueSet || m_saltSet != _other.m_saltSet)
|
||||
if (gasSet() != _other.gasSet() || valueSet() != _other.valueSet() || saltSet() != _other.saltSet())
|
||||
return false;
|
||||
|
||||
if (bound() != _other.bound())
|
||||
@ -3520,41 +3509,39 @@ TypePointers FunctionType::parseElementaryTypeVector(strings const& _types)
|
||||
Type const* FunctionType::copyAndSetCallOptions(bool _setGas, bool _setValue, bool _setSalt) const
|
||||
{
|
||||
solAssert(m_kind != Kind::Declaration, "");
|
||||
Options options = Options::fromFunctionType(*this);
|
||||
if (_setGas) options.gasSet = true;
|
||||
if (_setValue) options.valueSet = true;
|
||||
if (_setSalt) options.saltSet = true;
|
||||
return TypeProvider::function(
|
||||
m_parameterTypes,
|
||||
m_returnParameterTypes,
|
||||
m_parameterNames,
|
||||
m_returnParameterNames,
|
||||
m_kind,
|
||||
m_arbitraryParameters,
|
||||
m_stateMutability,
|
||||
m_declaration,
|
||||
m_gasSet || _setGas,
|
||||
m_valueSet || _setValue,
|
||||
m_saltSet || _setSalt,
|
||||
m_bound
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
FunctionTypePointer FunctionType::asBoundFunction() const
|
||||
{
|
||||
solAssert(!m_parameterTypes.empty(), "");
|
||||
solAssert(!m_gasSet, "");
|
||||
solAssert(!m_valueSet, "");
|
||||
solAssert(!m_saltSet, "");
|
||||
solAssert(!gasSet(), "");
|
||||
solAssert(!valueSet(), "");
|
||||
solAssert(!saltSet(), "");
|
||||
Options options = Options::fromFunctionType(*this);
|
||||
options.bound = true;
|
||||
return TypeProvider::function(
|
||||
m_parameterTypes,
|
||||
m_returnParameterTypes,
|
||||
m_parameterNames,
|
||||
m_returnParameterNames,
|
||||
m_kind,
|
||||
m_arbitraryParameters,
|
||||
m_stateMutability,
|
||||
m_declaration,
|
||||
m_gasSet,
|
||||
m_valueSet,
|
||||
m_saltSet,
|
||||
true
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
@ -3592,13 +3579,9 @@ FunctionTypePointer FunctionType::asExternallyCallableFunction(bool _inLibrary)
|
||||
m_parameterNames,
|
||||
m_returnParameterNames,
|
||||
kind,
|
||||
m_arbitraryParameters,
|
||||
m_stateMutability,
|
||||
m_declaration,
|
||||
m_gasSet,
|
||||
m_valueSet,
|
||||
m_saltSet,
|
||||
m_bound
|
||||
Options::fromFunctionType(*this)
|
||||
);
|
||||
}
|
||||
|
||||
@ -3803,7 +3786,6 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
|
||||
strings{string{}},
|
||||
strings{string{}},
|
||||
FunctionType::Kind::Wrap,
|
||||
false, /*_arbitraryParameters */
|
||||
StateMutability::Pure
|
||||
)
|
||||
);
|
||||
@ -3815,7 +3797,6 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
|
||||
strings{string{}},
|
||||
strings{string{}},
|
||||
FunctionType::Kind::Unwrap,
|
||||
false, /* _arbitraryParameters */
|
||||
StateMutability::Pure
|
||||
)
|
||||
);
|
||||
@ -3830,8 +3811,9 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
|
||||
strings{},
|
||||
strings{string()},
|
||||
FunctionType::Kind::BytesConcat,
|
||||
/* _arbitraryParameters */ true,
|
||||
StateMutability::Pure
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
FunctionType::Options::withArbitraryParameters()
|
||||
));
|
||||
|
||||
return members;
|
||||
@ -3954,7 +3936,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
return MemberList::MemberMap({
|
||||
{"coinbase", TypeProvider::payableAddress()},
|
||||
{"timestamp", TypeProvider::uint256()},
|
||||
{"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)},
|
||||
{"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, StateMutability::View)},
|
||||
{"difficulty", TypeProvider::uint256()},
|
||||
{"number", TypeProvider::uint256()},
|
||||
{"gaslimit", TypeProvider::uint256()},
|
||||
@ -3982,8 +3964,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
strings{},
|
||||
strings{1, ""},
|
||||
FunctionType::Kind::ABIEncode,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
FunctionType::Options::withArbitraryParameters()
|
||||
)},
|
||||
{"encodePacked", TypeProvider::function(
|
||||
TypePointers{},
|
||||
@ -3991,8 +3974,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
strings{},
|
||||
strings{1, ""},
|
||||
FunctionType::Kind::ABIEncodePacked,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
FunctionType::Options::withArbitraryParameters()
|
||||
)},
|
||||
{"encodeWithSelector", TypeProvider::function(
|
||||
TypePointers{TypeProvider::fixedBytes(4)},
|
||||
@ -4000,8 +3984,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
strings{1, ""},
|
||||
strings{1, ""},
|
||||
FunctionType::Kind::ABIEncodeWithSelector,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
FunctionType::Options::withArbitraryParameters()
|
||||
)},
|
||||
{"encodeCall", TypeProvider::function(
|
||||
TypePointers{},
|
||||
@ -4009,8 +3994,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
strings{},
|
||||
strings{1, ""},
|
||||
FunctionType::Kind::ABIEncodeCall,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
FunctionType::Options::withArbitraryParameters()
|
||||
)},
|
||||
{"encodeWithSignature", TypeProvider::function(
|
||||
TypePointers{TypeProvider::array(DataLocation::Memory, true)},
|
||||
@ -4018,8 +4004,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
strings{1, ""},
|
||||
strings{1, ""},
|
||||
FunctionType::Kind::ABIEncodeWithSignature,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
FunctionType::Options::withArbitraryParameters()
|
||||
)},
|
||||
{"decode", TypeProvider::function(
|
||||
TypePointers(),
|
||||
@ -4027,8 +4014,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
||||
strings{},
|
||||
strings{},
|
||||
FunctionType::Kind::ABIDecode,
|
||||
true,
|
||||
StateMutability::Pure
|
||||
StateMutability::Pure,
|
||||
nullptr,
|
||||
FunctionType::Options::withArbitraryParameters()
|
||||
)}
|
||||
});
|
||||
case Kind::MetaType:
|
||||
|
@ -1247,6 +1247,38 @@ public:
|
||||
/// Cannot be called.
|
||||
Declaration,
|
||||
};
|
||||
struct Options
|
||||
{
|
||||
/// true iff the function takes an arbitrary number of arguments of arbitrary types
|
||||
bool arbitraryParameters = false;
|
||||
/// true iff the gas value to be used is on the stack
|
||||
bool gasSet = false;
|
||||
/// true iff the value to be sent is on the stack
|
||||
bool valueSet = false;
|
||||
/// iff the salt value (for create2) to be used is on the stack
|
||||
bool saltSet = false;
|
||||
/// true iff the function is called as arg1.fun(arg2, ..., argn).
|
||||
/// This is achieved through the "using for" directive.
|
||||
bool bound = false;
|
||||
|
||||
static Options withArbitraryParameters()
|
||||
{
|
||||
Options result;
|
||||
result.arbitraryParameters = true;
|
||||
return result;
|
||||
}
|
||||
static Options fromFunctionType(FunctionType const& _type)
|
||||
{
|
||||
Options result;
|
||||
result.arbitraryParameters = _type.takesArbitraryParameters();
|
||||
result.gasSet = _type.gasSet();
|
||||
result.valueSet = _type.valueSet();
|
||||
result.saltSet = _type.saltSet();
|
||||
result.bound = _type.bound();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Creates the type of a function.
|
||||
/// @arg _kind must be Kind::Internal, Kind::External or Kind::Declaration.
|
||||
@ -1263,18 +1295,21 @@ public:
|
||||
strings const& _parameterTypes,
|
||||
strings const& _returnParameterTypes,
|
||||
Kind _kind,
|
||||
bool _arbitraryParameters = false,
|
||||
StateMutability _stateMutability = StateMutability::NonPayable
|
||||
StateMutability _stateMutability = StateMutability::NonPayable,
|
||||
Options _options = Options{false, false, false, false, false}
|
||||
): FunctionType(
|
||||
parseElementaryTypeVector(_parameterTypes),
|
||||
parseElementaryTypeVector(_returnParameterTypes),
|
||||
strings(_parameterTypes.size(), ""),
|
||||
strings(_returnParameterTypes.size(), ""),
|
||||
_kind,
|
||||
_arbitraryParameters,
|
||||
_stateMutability
|
||||
_stateMutability,
|
||||
nullptr,
|
||||
std::move(_options)
|
||||
)
|
||||
{
|
||||
// In this constructor, only the "arbitrary Parameters" option should be used.
|
||||
solAssert(!bound() && !gasSet() && !valueSet() && !saltSet());
|
||||
}
|
||||
|
||||
/// Detailed constructor, use with care.
|
||||
@ -1284,13 +1319,9 @@ public:
|
||||
strings _parameterNames = strings(),
|
||||
strings _returnParameterNames = strings(),
|
||||
Kind _kind = Kind::Internal,
|
||||
bool _arbitraryParameters = false,
|
||||
StateMutability _stateMutability = StateMutability::NonPayable,
|
||||
Declaration const* _declaration = nullptr,
|
||||
bool _gasSet = false,
|
||||
bool _valueSet = false,
|
||||
bool _saltSet = false,
|
||||
bool _bound = false
|
||||
Options _options = Options{false, false, false, false, false}
|
||||
):
|
||||
m_parameterTypes(std::move(_parameterTypes)),
|
||||
m_returnParameterTypes(std::move(_returnParameterTypes)),
|
||||
@ -1298,12 +1329,8 @@ public:
|
||||
m_returnParameterNames(std::move(_returnParameterNames)),
|
||||
m_kind(_kind),
|
||||
m_stateMutability(_stateMutability),
|
||||
m_arbitraryParameters(_arbitraryParameters),
|
||||
m_gasSet(_gasSet),
|
||||
m_valueSet(_valueSet),
|
||||
m_bound(_bound),
|
||||
m_declaration(_declaration),
|
||||
m_saltSet(_saltSet)
|
||||
m_options(std::move(_options))
|
||||
{
|
||||
solAssert(
|
||||
m_parameterNames.size() == m_parameterTypes.size(),
|
||||
@ -1314,7 +1341,7 @@ public:
|
||||
"Return parameter names list must match return parameter types list!"
|
||||
);
|
||||
solAssert(
|
||||
!m_bound || !m_parameterTypes.empty(),
|
||||
!bound() || !m_parameterTypes.empty(),
|
||||
"Attempted construction of bound function without self type"
|
||||
);
|
||||
}
|
||||
@ -1408,7 +1435,7 @@ public:
|
||||
/// The only functions that do not pad are hash functions, the low-level call functions
|
||||
/// and abi.encodePacked.
|
||||
bool padArguments() const;
|
||||
bool takesArbitraryParameters() const { return m_arbitraryParameters; }
|
||||
bool takesArbitraryParameters() const { return m_options.arbitraryParameters; }
|
||||
/// true iff the function takes a single bytes parameter and it is passed on without padding.
|
||||
bool takesSinglePackedBytesParameter() const
|
||||
{
|
||||
@ -1427,10 +1454,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool gasSet() const { return m_gasSet; }
|
||||
bool valueSet() const { return m_valueSet; }
|
||||
bool saltSet() const { return m_saltSet; }
|
||||
bool bound() const { return m_bound; }
|
||||
bool gasSet() const { return m_options.gasSet; }
|
||||
bool valueSet() const { return m_options.valueSet; }
|
||||
bool saltSet() const { return m_options.saltSet; }
|
||||
bool bound() const { return m_options.bound; }
|
||||
|
||||
/// @returns a copy of this type, where gas or value are set manually. This will never set one
|
||||
/// of the parameters to false.
|
||||
@ -1458,15 +1485,8 @@ private:
|
||||
std::vector<std::string> m_returnParameterNames;
|
||||
Kind const m_kind;
|
||||
StateMutability m_stateMutability = StateMutability::NonPayable;
|
||||
/// true if the function takes an arbitrary number of arguments of arbitrary types
|
||||
bool const m_arbitraryParameters = false;
|
||||
bool const m_gasSet = false; ///< true iff the gas value to be used is on the stack
|
||||
bool const m_valueSet = false; ///< true iff the value to be sent is on the stack
|
||||
/// true iff the function is called as arg1.fun(arg2, ..., argn).
|
||||
/// This is achieved through the "using for" directive.
|
||||
bool const m_bound = false;
|
||||
Declaration const* m_declaration = nullptr;
|
||||
bool m_saltSet = false; ///< true iff the salt value to be used is on the stack
|
||||
Options const m_options;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -780,6 +780,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
break;
|
||||
case FunctionType::Kind::Send:
|
||||
case FunctionType::Kind::Transfer:
|
||||
{
|
||||
_functionCall.expression().accept(*this);
|
||||
// Provide the gas stipend manually at first because we may send zero ether.
|
||||
// Will be zeroed if we send more than zero ether.
|
||||
@ -788,6 +789,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
// gas <- gas * !value
|
||||
m_context << Instruction::SWAP1 << Instruction::DUP2;
|
||||
m_context << Instruction::ISZERO << Instruction::MUL << Instruction::SWAP1;
|
||||
FunctionType::Options callOptions;
|
||||
callOptions.valueSet = true;
|
||||
callOptions.gasSet = true;
|
||||
appendExternalFunctionCall(
|
||||
FunctionType(
|
||||
TypePointers{},
|
||||
@ -795,11 +799,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
strings(),
|
||||
strings(),
|
||||
FunctionType::Kind::BareCall,
|
||||
false,
|
||||
StateMutability::NonPayable,
|
||||
nullptr,
|
||||
true,
|
||||
true
|
||||
callOptions
|
||||
),
|
||||
{},
|
||||
false
|
||||
@ -812,6 +814,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
m_context.appendConditionalRevert(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FunctionType::Kind::Selfdestruct:
|
||||
acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), true);
|
||||
m_context << Instruction::SELFDESTRUCT;
|
||||
|
Loading…
Reference in New Issue
Block a user