Add appendCallValueCheck

This commit is contained in:
Alex Beregszaszi 2016-11-17 17:23:31 +00:00
parent a35ca910c7
commit 910269a29f
2 changed files with 14 additions and 20 deletions

View File

@ -102,6 +102,13 @@ void ContractCompiler::initializeContext(
m_context.resetVisitedNodes(&_contract); 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) void ContractCompiler::appendInitAndConstructorCode(ContractDefinition const& _contract)
{ {
// Determine the arguments that are used for the base constructors. // Determine the arguments that are used for the base constructors.
@ -138,11 +145,7 @@ void ContractCompiler::appendInitAndConstructorCode(ContractDefinition const& _c
else if (auto c = m_context.nextConstructor(_contract)) else if (auto c = m_context.nextConstructor(_contract))
appendBaseConstructor(*c); appendBaseConstructor(*c);
else else
{ appendCallValueCheck();
// Throw if function is not payable but call contained ether.
m_context << Instruction::CALLVALUE;
m_context.appendConditionalJumpTo(m_context.errorTag());
}
} }
size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _contract) size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _contract)
@ -191,11 +194,8 @@ void ContractCompiler::appendConstructor(FunctionDefinition const& _constructor)
{ {
CompilerContext::LocationSetter locationSetter(m_context, _constructor); CompilerContext::LocationSetter locationSetter(m_context, _constructor);
if (!_constructor.isPayable()) if (!_constructor.isPayable())
{ appendCallValueCheck();
// Throw if function is not payable but call contained ether.
m_context << Instruction::CALLVALUE;
m_context.appendConditionalJumpTo(m_context.errorTag());
}
// copy constructor arguments from code to memory and then to stack, they are supplied after the actual program // copy constructor arguments from code to memory and then to stack, they are supplied after the actual program
if (!_constructor.parameters().empty()) if (!_constructor.parameters().empty())
{ {
@ -263,11 +263,8 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
if (fallback) if (fallback)
{ {
if (!fallback->isPayable()) if (!fallback->isPayable())
{ appendCallValueCheck();
// Throw if function is not payable but call contained ether.
m_context << Instruction::CALLVALUE;
m_context.appendConditionalJumpTo(m_context.errorTag());
}
eth::AssemblyItem returnTag = m_context.pushNewTag(); eth::AssemblyItem returnTag = m_context.pushNewTag();
fallback->accept(*this); fallback->accept(*this);
m_context << returnTag; m_context << returnTag;
@ -286,11 +283,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
// We have to allow this for libraries, because value of the previous // We have to allow this for libraries, because value of the previous
// call is still visible in the delegatecall. // call is still visible in the delegatecall.
if (!functionType->isPayable() && !_contract.isLibrary()) if (!functionType->isPayable() && !_contract.isLibrary())
{ appendCallValueCheck();
// Throw if function is not payable but call contained ether.
m_context << Instruction::CALLVALUE;
m_context.appendConditionalJumpTo(m_context.errorTag());
}
eth::AssemblyItem returnTag = m_context.pushNewTag(); eth::AssemblyItem returnTag = m_context.pushNewTag();
m_context << CompilerUtils::dataStartOffset; m_context << CompilerUtils::dataStartOffset;

View File

@ -80,6 +80,7 @@ private:
void appendBaseConstructor(FunctionDefinition const& _constructor); void appendBaseConstructor(FunctionDefinition const& _constructor);
void appendConstructor(FunctionDefinition const& _constructor); void appendConstructor(FunctionDefinition const& _constructor);
void appendFunctionSelector(ContractDefinition const& _contract); void appendFunctionSelector(ContractDefinition const& _contract);
void appendCallValueCheck();
/// Creates code that unpacks the arguments for the given function represented by a vector of TypePointers. /// 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. /// From memory if @a _fromMemory is true, otherwise from call data.
/// Expects source offset on the stack, which is removed. /// Expects source offset on the stack, which is removed.