diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/codegen/CompilerContext.cpp | 20 | ||||
-rw-r--r-- | libsolidity/codegen/CompilerContext.h | 5 | ||||
-rw-r--r-- | libsolidity/codegen/CompilerUtils.cpp | 1 | ||||
-rw-r--r-- | libsolidity/codegen/ContractCompiler.cpp | 2 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 9 |
5 files changed, 26 insertions, 11 deletions
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 47333046..2cd256f3 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -262,12 +262,20 @@ CompilerContext& CompilerContext::appendRevert() return *this << u256(0) << u256(0) << Instruction::REVERT; } -CompilerContext& CompilerContext::appendConditionalRevert() -{ - *this << Instruction::ISZERO; - eth::AssemblyItem afterTag = appendConditionalJump(); - appendRevert(); - *this << afterTag; +CompilerContext& CompilerContext::appendConditionalRevert(bool _forwardReturnData) +{ + if (_forwardReturnData) + appendInlineAssembly(R"({ + if condition { + returndatacopy(0, 0, returndatasize()) + revert(0, returndatasize()) + } + })", {"condition"}); + else + appendInlineAssembly(R"({ + if condition { revert(0, 0) } + })", {"condition"}); + *this << Instruction::POP; return *this; } diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 7b663277..c6f2f3be 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -156,8 +156,9 @@ public: CompilerContext& appendConditionalInvalid(); /// Appends a REVERT(0, 0) call CompilerContext& appendRevert(); - /// Appends a conditional REVERT(0, 0) call - CompilerContext& appendConditionalRevert(); + /// Appends a conditional REVERT-call, either forwarding the RETURNDATA or providing the + /// empty string. Consumes the condition. + CompilerContext& appendConditionalRevert(bool _forwardReturnData = false); /// Appends a JUMP to a specific tag CompilerContext& appendJumpTo(eth::AssemblyItem const& _tag) { m_asm->appendJump(_tag); return *this; } /// Appends pushing of a new tag and @returns the new tag. diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 79aef7b0..34337d7d 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -691,6 +691,7 @@ void CompilerUtils::convertType( solAssert(enumType.numberOfMembers() > 0, "empty enum should have caused a parser error."); m_context << u256(enumType.numberOfMembers() - 1) << Instruction::DUP2 << Instruction::GT; if (_asPartOfArgumentDecoding) + // TODO: error message? m_context.appendConditionalRevert(); else m_context.appendConditionalInvalid(); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 5cb37103..0889ac7c 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -128,6 +128,7 @@ void ContractCompiler::appendCallValueCheck() { // Throw if function is not payable but call contained ether. m_context << Instruction::CALLVALUE; + // TODO: error message? m_context.appendConditionalRevert(); } @@ -327,6 +328,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac m_context << Instruction::STOP; } else + // TODO: error message here? m_context.appendRevert(); for (auto const& it: interfaceFunctions) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index cb92b030..3f521f2d 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -608,7 +608,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << Instruction::CREATE; // Check if zero (out of stack or not enough balance). m_context << Instruction::DUP1 << Instruction::ISZERO; - m_context.appendConditionalRevert(); + // TODO: Can we bubble up here? There might be different reasons for failure, I think. + m_context.appendConditionalRevert(true); if (function.valueSet()) m_context << swapInstruction(1) << Instruction::POP; break; @@ -670,8 +671,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) if (function.kind() == FunctionType::Kind::Transfer) { // Check if zero (out of stack or not enough balance). + // TODO: bubble up here, but might also be different error. m_context << Instruction::ISZERO; - m_context.appendConditionalRevert(); + m_context.appendConditionalRevert(true); } break; case FunctionType::Kind::Selfdestruct: @@ -1823,6 +1825,7 @@ void ExpressionCompiler::appendExternalFunctionCall( if (funKind == FunctionType::Kind::External || funKind == FunctionType::Kind::CallCode || funKind == FunctionType::Kind::DelegateCall) { m_context << Instruction::DUP1 << Instruction::EXTCODESIZE << Instruction::ISZERO; + // TODO: error message? m_context.appendConditionalRevert(); existenceChecked = true; } @@ -1865,7 +1868,7 @@ void ExpressionCompiler::appendExternalFunctionCall( { //Propagate error condition (if CALL pushes 0 on stack). m_context << Instruction::ISZERO; - m_context.appendConditionalRevert(); + m_context.appendConditionalRevert(true); } utils().popStackSlots(remainsSize); |