aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp25
-rw-r--r--libsolidity/codegen/ContractCompiler.h1
-rw-r--r--libsolidity/interface/InterfaceHandler.cpp1
3 files changed, 17 insertions, 10 deletions
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 2e3f5d7f..8d60d6b3 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -102,6 +102,13 @@ void ContractCompiler::initializeContext(
m_context.resetVisitedNodes(&_contract);
}
+void ContractCompiler::appendCallValueCheck()
+{
+ // Throw if function is not payable but call contained ether.
+ m_context << Instruction::CALLVALUE;
+ m_context.appendConditionalJumpTo(m_context.errorTag());
+}
+
void ContractCompiler::appendInitAndConstructorCode(ContractDefinition const& _contract)
{
// Determine the arguments that are used for the base constructors.
@@ -137,6 +144,8 @@ void ContractCompiler::appendInitAndConstructorCode(ContractDefinition const& _c
appendConstructor(*constructor);
else if (auto c = m_context.nextConstructor(_contract))
appendBaseConstructor(*c);
+ else
+ appendCallValueCheck();
}
size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _contract)
@@ -184,6 +193,9 @@ void ContractCompiler::appendBaseConstructor(FunctionDefinition const& _construc
void ContractCompiler::appendConstructor(FunctionDefinition const& _constructor)
{
CompilerContext::LocationSetter locationSetter(m_context, _constructor);
+ if (!_constructor.isPayable())
+ appendCallValueCheck();
+
// copy constructor arguments from code to memory and then to stack, they are supplied after the actual program
if (!_constructor.parameters().empty())
{
@@ -251,11 +263,8 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
if (fallback)
{
if (!fallback->isPayable())
- {
- // Throw if function is not payable but call contained ether.
- m_context << Instruction::CALLVALUE;
- m_context.appendConditionalJumpTo(m_context.errorTag());
- }
+ appendCallValueCheck();
+
eth::AssemblyItem returnTag = m_context.pushNewTag();
fallback->accept(*this);
m_context << returnTag;
@@ -274,11 +283,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
// We have to allow this for libraries, because value of the previous
// call is still visible in the delegatecall.
if (!functionType->isPayable() && !_contract.isLibrary())
- {
- // Throw if function is not payable but call contained ether.
- m_context << Instruction::CALLVALUE;
- m_context.appendConditionalJumpTo(m_context.errorTag());
- }
+ appendCallValueCheck();
eth::AssemblyItem returnTag = m_context.pushNewTag();
m_context << CompilerUtils::dataStartOffset;
diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h
index 2244a3be..10febcf7 100644
--- a/libsolidity/codegen/ContractCompiler.h
+++ b/libsolidity/codegen/ContractCompiler.h
@@ -80,6 +80,7 @@ private:
void appendBaseConstructor(FunctionDefinition const& _constructor);
void appendConstructor(FunctionDefinition const& _constructor);
void appendFunctionSelector(ContractDefinition const& _contract);
+ void appendCallValueCheck();
/// Creates code that unpacks the arguments for the given function represented by a vector of TypePointers.
/// From memory if @a _fromMemory is true, otherwise from call data.
/// Expects source offset on the stack, which is removed.
diff --git a/libsolidity/interface/InterfaceHandler.cpp b/libsolidity/interface/InterfaceHandler.cpp
index 0f7b6c35..9944bb22 100644
--- a/libsolidity/interface/InterfaceHandler.cpp
+++ b/libsolidity/interface/InterfaceHandler.cpp
@@ -68,6 +68,7 @@ Json::Value InterfaceHandler::abiInterface(ContractDefinition const& _contractDe
method["type"] = "constructor";
auto externalFunction = FunctionType(*_contractDef.constructor(), false).interfaceFunctionType();
solAssert(!!externalFunction, "");
+ method["payable"] = externalFunction->isPayable();
method["inputs"] = populateParameters(
externalFunction->parameterNames(),
externalFunction->parameterTypeNames(_contractDef.isLibrary())