aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Beregszaszi <alex@rtfs.hu>2016-06-18 18:11:55 +0800
committerchriseth <c@ethdev.com>2016-09-06 03:28:18 +0800
commita34f2f1a316d6093c14045ee8423d913ac01421d (patch)
tree79a97492be7e5a436498dc3a0a6ffe2174c36ab4
parente2b787cdd0717bf074cc03634d580f7713568792 (diff)
downloaddexon-solidity-a34f2f1a316d6093c14045ee8423d913ac01421d.tar
dexon-solidity-a34f2f1a316d6093c14045ee8423d913ac01421d.tar.gz
dexon-solidity-a34f2f1a316d6093c14045ee8423d913ac01421d.tar.bz2
dexon-solidity-a34f2f1a316d6093c14045ee8423d913ac01421d.tar.lz
dexon-solidity-a34f2f1a316d6093c14045ee8423d913ac01421d.tar.xz
dexon-solidity-a34f2f1a316d6093c14045ee8423d913ac01421d.tar.zst
dexon-solidity-a34f2f1a316d6093c14045ee8423d913ac01421d.zip
Support payable keyword for functions
-rw-r--r--libsolidity/ast/AST.h4
-rw-r--r--libsolidity/ast/Types.cpp1
-rw-r--r--libsolidity/ast/Types.h2
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp17
-rw-r--r--libsolidity/interface/InterfaceHandler.cpp2
-rw-r--r--libsolidity/parsing/Parser.cpp7
-rw-r--r--libsolidity/parsing/Token.h2
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) \