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