diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index dfeb28db2..540a4f14e 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -95,6 +95,26 @@ void CompilerUtils::revertWithStringData(Type const& _argumentType) m_context << Instruction::REVERT; } +void CompilerUtils::returnDataToArray() +{ + if (m_context.evmVersion().supportsReturndata()) + { + m_context << Instruction::RETURNDATASIZE; + m_context.appendInlineAssembly(R"({ + switch v case 0 { + v := 0x60 + } default { + v := mload(0x40) + mstore(0x40, add(v, and(add(returndatasize(), 0x3f), not(0x1f)))) + mstore(v, returndatasize()) + returndatacopy(add(v, 0x20), 0, returndatasize()) + } + })", {"v"}); + } + else + pushZeroPointer(); +} + void CompilerUtils::accessCalldataTail(Type const& _type) { solAssert(_type.dataStoredIn(DataLocation::CallData), ""); diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 8c9f1dc43..90ea8a156 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -67,6 +67,10 @@ public: /// Stack post: void revertWithStringData(Type const& _argumentType); + /// Allocates a new array and copies the return data to it. + /// If the EVM does not support return data, creates an empty array. + void returnDataToArray(); + /// Computes the absolute calldata offset of a tail given a base reference and the (absolute) /// offset of the tail pointer. Performs bounds checks. If @a _type is a dynamically sized array it also /// returns the array length on the stack. diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 57a0cb189..bc4a6de8e 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -2189,24 +2189,7 @@ void ExpressionCompiler::appendExternalFunctionCall( // an internal helper function e.g. for ``send`` and ``transfer``. In that // case we're only interested in the success condition, not the return data. if (!_functionType.returnParameterTypes().empty()) - { - if (haveReturndatacopy) - { - m_context << Instruction::RETURNDATASIZE; - m_context.appendInlineAssembly(R"({ - switch v case 0 { - v := 0x60 - } default { - v := mload(0x40) - mstore(0x40, add(v, and(add(returndatasize(), 0x3f), not(0x1f)))) - mstore(v, returndatasize()) - returndatacopy(add(v, 0x20), 0, returndatasize()) - } - })", {"v"}); - } - else - utils().pushZeroPointer(); - } + utils().returnDataToArray(); } else if (funKind == FunctionType::Kind::RIPEMD160) {