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