diff options
author | Alex Beregszaszi <alex@rtfs.hu> | 2016-06-18 18:11:55 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2016-09-06 03:28:18 +0800 |
commit | a34f2f1a316d6093c14045ee8423d913ac01421d (patch) | |
tree | 79a97492be7e5a436498dc3a0a6ffe2174c36ab4 /libsolidity | |
parent | e2b787cdd0717bf074cc03634d580f7713568792 (diff) | |
download | dexon-solidity-a34f2f1a316d6093c14045ee8423d913ac01421d.tar.gz dexon-solidity-a34f2f1a316d6093c14045ee8423d913ac01421d.tar.zst dexon-solidity-a34f2f1a316d6093c14045ee8423d913ac01421d.zip |
Support payable keyword for functions
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/ast/AST.h | 4 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 1 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 2 | ||||
-rw-r--r-- | libsolidity/codegen/ContractCompiler.cpp | 17 | ||||
-rw-r--r-- | libsolidity/interface/InterfaceHandler.cpp | 2 | ||||
-rw-r--r-- | libsolidity/parsing/Parser.cpp | 7 | ||||
-rw-r--r-- | libsolidity/parsing/Token.h | 2 |
7 files changed, 34 insertions, 1 deletions
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 761d85fe..8fd1584d 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -540,6 +540,7 @@ public: bool _isDeclaredConst, std::vector<ASTPointer<ModifierInvocation>> const& _modifiers, ASTPointer<ParameterList> const& _returnParameters, + bool _isPayable, ASTPointer<Block> const& _body ): CallableDeclaration(_location, _name, _visibility, _parameters, _returnParameters), @@ -547,6 +548,7 @@ public: ImplementationOptional(_body != nullptr), m_isConstructor(_isConstructor), m_isDeclaredConst(_isDeclaredConst), + m_isPayable(_isPayable), m_functionModifiers(_modifiers), m_body(_body) {} @@ -556,6 +558,7 @@ public: bool isConstructor() const { return m_isConstructor; } 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<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); } Block const& body() const { return *m_body; } @@ -578,6 +581,7 @@ public: private: bool m_isConstructor; bool m_isDeclaredConst; + bool m_isPayable; std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers; ASTPointer<Block> m_body; }; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index d86a2caf..938dced6 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1653,6 +1653,7 @@ TypePointer TupleType::closestTemporaryType(TypePointer const& _targetType) cons FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal): m_location(_isInternal ? Location::Internal : Location::External), m_isConstant(_function.isDeclaredConst()), + m_isPayable(_function.isPayable()), m_declaration(&_function) { TypePointers params; diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 1282e5d8..c57f8db1 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -905,6 +905,7 @@ public: } bool hasDeclaration() const { return !!m_declaration; } bool isConstant() const { return m_isConstant; } + bool isPayable() const { return m_isPayable; } /// @return A shared pointer of an ASTString. /// Can contain a nullptr in which case indicates absence of documentation 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_bound = false; ///< true iff the function is called as arg1.fun(arg2, ..., argn) bool m_isConstant = false; + bool m_isPayable = false; Declaration const* m_declaration = nullptr; }; diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 9d77ccdc..eba85103 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -243,6 +243,14 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac if (fallback) { 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); m_context << returnTag; appendReturnValuePacker(FunctionType(*fallback).returnParameterTypes(), _contract.isLibrary()); @@ -255,8 +263,17 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac FunctionTypePointer const& functionType = it.second; solAssert(functionType->hasDeclaration(), ""); CompilerContext::LocationSetter locationSetter(m_context, functionType->declaration()); + m_context << callDataUnpackerEntryPoints.at(it.first); 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; appendCalldataUnpacker(functionType->parameterTypes()); m_context.appendJumpTo(m_context.functionEntryLabel(functionType->declaration())); diff --git a/libsolidity/interface/InterfaceHandler.cpp b/libsolidity/interface/InterfaceHandler.cpp index d39f8285..017753fc 100644 --- a/libsolidity/interface/InterfaceHandler.cpp +++ b/libsolidity/interface/InterfaceHandler.cpp @@ -52,6 +52,7 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef) method["type"] = "function"; method["name"] = it.second->declaration().name(); method["constant"] = it.second->isConstant(); + method["payable"] = it.second->isPayable(); method["inputs"] = populateParameters( externalFunctionType->parameterNames(), externalFunctionType->parameterTypeNames(_contractDef.isLibrary()) @@ -72,6 +73,7 @@ string InterfaceHandler::abiInterface(ContractDefinition const& _contractDef) externalFunction->parameterNames(), externalFunction->parameterTypeNames(_contractDef.isLibrary()) ); + method["payable"] = externalFunction->isPayable(); abi.append(method); } if (_contractDef.fallbackFunction()) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 1bffa5d7..1d76f80a 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -326,6 +326,12 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* else break; } + bool isPayable = false; + if (m_scanner->currentToken() == Token::Payable) + { + isPayable = true; + m_scanner->next(); + } ASTPointer<ParameterList> returnParameters; if (m_scanner->currentToken() == Token::Returns) { @@ -354,6 +360,7 @@ ASTPointer<FunctionDefinition> Parser::parseFunctionDefinition(ASTString const* isDeclaredConst, modifiers, returnParameters, + isPayable, block ); } diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h index 15d4860f..cc85b610 100644 --- a/libsolidity/parsing/Token.h +++ b/libsolidity/parsing/Token.h @@ -166,6 +166,7 @@ namespace solidity K(Memory, "memory", 0) \ K(Modifier, "modifier", 0) \ K(New, "new", 0) \ + K(Payable, "payable", 0) \ K(Public, "public", 0) \ K(Pragma, "pragma", 0) \ K(Private, "private", 0) \ @@ -229,7 +230,6 @@ namespace solidity K(Let, "let", 0) \ K(Match, "match", 0) \ K(Of, "of", 0) \ - K(Payable, "payable", 0) \ K(Relocatable, "relocatable", 0) \ K(Static, "static", 0) \ K(Switch, "switch", 0) \ |