mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Support payable keyword for functions
This commit is contained in:
		
							parent
							
								
									e2b787cdd0
								
							
						
					
					
						commit
						a34f2f1a31
					
				| @ -540,6 +540,7 @@ public: | |||||||
| 		bool _isDeclaredConst, | 		bool _isDeclaredConst, | ||||||
| 		std::vector<ASTPointer<ModifierInvocation>> const& _modifiers, | 		std::vector<ASTPointer<ModifierInvocation>> const& _modifiers, | ||||||
| 		ASTPointer<ParameterList> const& _returnParameters, | 		ASTPointer<ParameterList> const& _returnParameters, | ||||||
|  | 		bool _isPayable, | ||||||
| 		ASTPointer<Block> const& _body | 		ASTPointer<Block> const& _body | ||||||
| 	): | 	): | ||||||
| 		CallableDeclaration(_location, _name, _visibility, _parameters, _returnParameters), | 		CallableDeclaration(_location, _name, _visibility, _parameters, _returnParameters), | ||||||
| @ -547,6 +548,7 @@ public: | |||||||
| 		ImplementationOptional(_body != nullptr), | 		ImplementationOptional(_body != nullptr), | ||||||
| 		m_isConstructor(_isConstructor), | 		m_isConstructor(_isConstructor), | ||||||
| 		m_isDeclaredConst(_isDeclaredConst), | 		m_isDeclaredConst(_isDeclaredConst), | ||||||
|  | 		m_isPayable(_isPayable), | ||||||
| 		m_functionModifiers(_modifiers), | 		m_functionModifiers(_modifiers), | ||||||
| 		m_body(_body) | 		m_body(_body) | ||||||
| 	{} | 	{} | ||||||
| @ -556,6 +558,7 @@ public: | |||||||
| 
 | 
 | ||||||
| 	bool isConstructor() const { return m_isConstructor; } | 	bool isConstructor() const { return m_isConstructor; } | ||||||
| 	bool isDeclaredConst() const { return m_isDeclaredConst; } | 	bool isDeclaredConst() const { return m_isDeclaredConst; } | ||||||
|  | 	bool isPayable() const { return m_isPayable; } | ||||||
| 	std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; } | 	std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; } | ||||||
| 	std::vector<ASTPointer<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); } | 	std::vector<ASTPointer<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); } | ||||||
| 	Block const& body() const { return *m_body; } | 	Block const& body() const { return *m_body; } | ||||||
| @ -578,6 +581,7 @@ public: | |||||||
| private: | private: | ||||||
| 	bool m_isConstructor; | 	bool m_isConstructor; | ||||||
| 	bool m_isDeclaredConst; | 	bool m_isDeclaredConst; | ||||||
|  | 	bool m_isPayable; | ||||||
| 	std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers; | 	std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers; | ||||||
| 	ASTPointer<Block> m_body; | 	ASTPointer<Block> m_body; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1653,6 +1653,7 @@ TypePointer TupleType::closestTemporaryType(TypePointer const& _targetType) cons | |||||||
| FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal): | FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal): | ||||||
| 	m_location(_isInternal ? Location::Internal : Location::External), | 	m_location(_isInternal ? Location::Internal : Location::External), | ||||||
| 	m_isConstant(_function.isDeclaredConst()), | 	m_isConstant(_function.isDeclaredConst()), | ||||||
|  | 	m_isPayable(_function.isPayable()), | ||||||
| 	m_declaration(&_function) | 	m_declaration(&_function) | ||||||
| { | { | ||||||
| 	TypePointers params; | 	TypePointers params; | ||||||
|  | |||||||
| @ -905,6 +905,7 @@ public: | |||||||
| 	} | 	} | ||||||
| 	bool hasDeclaration() const { return !!m_declaration; } | 	bool hasDeclaration() const { return !!m_declaration; } | ||||||
| 	bool isConstant() const { return m_isConstant; } | 	bool isConstant() const { return m_isConstant; } | ||||||
|  | 	bool isPayable() const { return m_isPayable; } | ||||||
| 	/// @return A shared pointer of an ASTString.
 | 	/// @return A shared pointer of an ASTString.
 | ||||||
| 	/// Can contain a nullptr in which case indicates absence of documentation
 | 	/// Can contain a nullptr in which case indicates absence of documentation
 | ||||||
| 	ASTPointer<ASTString> documentation() const; | 	ASTPointer<ASTString> documentation() const; | ||||||
| @ -942,6 +943,7 @@ private: | |||||||
| 	bool const m_valueSet = false; ///< true iff the value to be sent is on the stack
 | 	bool const m_valueSet = false; ///< true iff the value to be sent is on the stack
 | ||||||
| 	bool const m_bound = false; ///< true iff the function is called as arg1.fun(arg2, ..., argn)
 | 	bool const m_bound = false; ///< true iff the function is called as arg1.fun(arg2, ..., argn)
 | ||||||
| 	bool m_isConstant = false; | 	bool m_isConstant = false; | ||||||
|  | 	bool m_isPayable = false; | ||||||
| 	Declaration const* m_declaration = nullptr; | 	Declaration const* m_declaration = nullptr; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -243,6 +243,14 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac | |||||||
| 	if (fallback) | 	if (fallback) | ||||||
| 	{ | 	{ | ||||||
| 		eth::AssemblyItem returnTag = m_context.pushNewTag(); | 		eth::AssemblyItem returnTag = m_context.pushNewTag(); | ||||||
|  | 
 | ||||||
|  | 		// Reject transaction if value is not accepted, but was received
 | ||||||
|  | 		if (!fallback->isPayable()) | ||||||
|  | 		{ | ||||||
|  | 			m_context << Instruction::CALLVALUE; | ||||||
|  | 			m_context.appendConditionalJumpTo(m_context.errorTag()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		fallback->accept(*this); | 		fallback->accept(*this); | ||||||
| 		m_context << returnTag; | 		m_context << returnTag; | ||||||
| 		appendReturnValuePacker(FunctionType(*fallback).returnParameterTypes(), _contract.isLibrary()); | 		appendReturnValuePacker(FunctionType(*fallback).returnParameterTypes(), _contract.isLibrary()); | ||||||
| @ -255,8 +263,17 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac | |||||||
| 		FunctionTypePointer const& functionType = it.second; | 		FunctionTypePointer const& functionType = it.second; | ||||||
| 		solAssert(functionType->hasDeclaration(), ""); | 		solAssert(functionType->hasDeclaration(), ""); | ||||||
| 		CompilerContext::LocationSetter locationSetter(m_context, functionType->declaration()); | 		CompilerContext::LocationSetter locationSetter(m_context, functionType->declaration()); | ||||||
|  | 
 | ||||||
| 		m_context << callDataUnpackerEntryPoints.at(it.first); | 		m_context << callDataUnpackerEntryPoints.at(it.first); | ||||||
| 		eth::AssemblyItem returnTag = m_context.pushNewTag(); | 		eth::AssemblyItem returnTag = m_context.pushNewTag(); | ||||||
|  | 
 | ||||||
|  | 		// Reject transaction if value is not accepted, but was received
 | ||||||
|  | 		if (!functionType->isPayable()) | ||||||
|  | 		{ | ||||||
|  | 			m_context << Instruction::CALLVALUE; | ||||||
|  | 			m_context.appendConditionalJumpTo(m_context.errorTag()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		m_context << CompilerUtils::dataStartOffset; | 		m_context << CompilerUtils::dataStartOffset; | ||||||
| 		appendCalldataUnpacker(functionType->parameterTypes()); | 		appendCalldataUnpacker(functionType->parameterTypes()); | ||||||
| 		m_context.appendJumpTo(m_context.functionEntryLabel(functionType->declaration())); | 		m_context.appendJumpTo(m_context.functionEntryLabel(functionType->declaration())); | ||||||
|  | |||||||
| @ -52,6 +52,7 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef) | |||||||
| 		method["type"] = "function"; | 		method["type"] = "function"; | ||||||
| 		method["name"] = it.second->declaration().name(); | 		method["name"] = it.second->declaration().name(); | ||||||
| 		method["constant"] = it.second->isConstant(); | 		method["constant"] = it.second->isConstant(); | ||||||
|  | 		method["payable"] = it.second->isPayable(); | ||||||
| 		method["inputs"] = populateParameters( | 		method["inputs"] = populateParameters( | ||||||
| 			externalFunctionType->parameterNames(), | 			externalFunctionType->parameterNames(), | ||||||
| 			externalFunctionType->parameterTypeNames(_contractDef.isLibrary()) | 			externalFunctionType->parameterTypeNames(_contractDef.isLibrary()) | ||||||
| @ -72,6 +73,7 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef) | |||||||
| 			externalFunction->parameterNames(), | 			externalFunction->parameterNames(), | ||||||
| 			externalFunction->parameterTypeNames(_contractDef.isLibrary()) | 			externalFunction->parameterTypeNames(_contractDef.isLibrary()) | ||||||
| 		); | 		); | ||||||
|  | 		method["payable"] = externalFunction->isPayable(); | ||||||
| 		abi.append(method); | 		abi.append(method); | ||||||
| 	} | 	} | ||||||
| 	if (_contractDef.fallbackFunction()) | 	if (_contractDef.fallbackFunction()) | ||||||
|  | |||||||
| @ -326,6 +326,12 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* | |||||||
| 		else | 		else | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
|  | 	bool isPayable = false; | ||||||
|  | 	if (m_scanner->currentToken() == Token::Payable) | ||||||
|  | 	{ | ||||||
|  | 	        isPayable = true; | ||||||
|  | 	        m_scanner->next(); | ||||||
|  | 	} | ||||||
| 	ASTPointer<ParameterList> returnParameters; | 	ASTPointer<ParameterList> returnParameters; | ||||||
| 	if (m_scanner->currentToken() == Token::Returns) | 	if (m_scanner->currentToken() == Token::Returns) | ||||||
| 	{ | 	{ | ||||||
| @ -354,6 +360,7 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* | |||||||
| 		isDeclaredConst, | 		isDeclaredConst, | ||||||
| 		modifiers, | 		modifiers, | ||||||
| 		returnParameters, | 		returnParameters, | ||||||
|  | 		isPayable, | ||||||
| 		block | 		block | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
|  | |||||||
| @ -166,6 +166,7 @@ namespace solidity | |||||||
| 	K(Memory, "memory", 0)                                             \ | 	K(Memory, "memory", 0)                                             \ | ||||||
| 	K(Modifier, "modifier", 0)                                         \ | 	K(Modifier, "modifier", 0)                                         \ | ||||||
| 	K(New, "new", 0)                                                   \ | 	K(New, "new", 0)                                                   \ | ||||||
|  | 	K(Payable, "payable", 0)                                           \ | ||||||
| 	K(Public, "public", 0)                                             \ | 	K(Public, "public", 0)                                             \ | ||||||
| 	K(Pragma, "pragma", 0)                                             \ | 	K(Pragma, "pragma", 0)                                             \ | ||||||
| 	K(Private, "private", 0)                                           \ | 	K(Private, "private", 0)                                           \ | ||||||
| @ -229,7 +230,6 @@ namespace solidity | |||||||
| 	K(Let, "let", 0)                                                   \ | 	K(Let, "let", 0)                                                   \ | ||||||
| 	K(Match, "match", 0)                                               \ | 	K(Match, "match", 0)                                               \ | ||||||
| 	K(Of, "of", 0)                                                     \ | 	K(Of, "of", 0)                                                     \ | ||||||
| 	K(Payable, "payable", 0)                                           \ |  | ||||||
| 	K(Relocatable, "relocatable", 0)                                   \ | 	K(Relocatable, "relocatable", 0)                                   \ | ||||||
| 	K(Static, "static", 0)                                             \ | 	K(Static, "static", 0)                                             \ | ||||||
| 	K(Switch, "switch", 0)                                             \ | 	K(Switch, "switch", 0)                                             \ | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user