diff --git a/libevmcore/Instruction.h b/libevmcore/Instruction.h index a28e8f8da..5cf002c4c 100644 --- a/libevmcore/Instruction.h +++ b/libevmcore/Instruction.h @@ -215,6 +215,14 @@ inline Instruction swapInstruction(unsigned _number) return Instruction(unsigned(Instruction::SWAP1) + _number - 1); } +/// @returns the LOG<_number> instruction +inline Instruction logInstruction(unsigned _number) +{ + if (asserts(_number <= 4)) + BOOST_THROW_EXCEPTION(InvalidOpcode() << errinfo_comment("Invalid LOG instruction requested.")); + return Instruction(unsigned(Instruction::LOG0) + _number); +} + /// Information structure for a particular instruction. struct InstructionInfo { diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 7238a6a1b..6c40a0028 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -257,60 +257,22 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) m_context << u256(32) << u256(0) << eth::Instruction::SHA3; break; case Location::LOG0: - arguments.front()->accept(*this); - appendTypeConversion(*arguments.front()->getType(), *function.getParameterTypes().front(), true); - // @todo move this once we actually use memory - CompilerUtils(m_context).storeInMemory(0); - m_context << u256(32) << u256(0) << eth::Instruction::LOG0; - break; case Location::LOG1: - arguments[1]->accept(*this); - arguments[0]->accept(*this); - appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true); - appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true); - // @todo move this once we actually use memory - CompilerUtils(m_context).storeInMemory(0); - m_context << u256(32) << u256(0) << eth::Instruction::LOG1; - break; case Location::LOG2: - arguments[2]->accept(*this); - arguments[1]->accept(*this); - arguments[0]->accept(*this); - appendTypeConversion(*arguments[2]->getType(), *function.getParameterTypes()[2], true); - appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true); - appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true); - // @todo move this once we actually use memory - CompilerUtils(m_context).storeInMemory(0); - m_context << u256(32) << u256(0) << eth::Instruction::LOG2; - break; case Location::LOG3: - arguments[3]->accept(*this); - arguments[2]->accept(*this); - arguments[1]->accept(*this); - arguments[0]->accept(*this); - appendTypeConversion(*arguments[3]->getType(), *function.getParameterTypes()[3], true); - appendTypeConversion(*arguments[2]->getType(), *function.getParameterTypes()[2], true); - appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true); - appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true); - // @todo move this once we actually use memory - CompilerUtils(m_context).storeInMemory(0); - m_context << u256(32) << u256(0) << eth::Instruction::LOG3; - break; case Location::LOG4: - arguments[4]->accept(*this); - arguments[3]->accept(*this); - arguments[2]->accept(*this); - arguments[1]->accept(*this); - arguments[0]->accept(*this); - appendTypeConversion(*arguments[4]->getType(), *function.getParameterTypes()[4], true); - appendTypeConversion(*arguments[3]->getType(), *function.getParameterTypes()[3], true); - appendTypeConversion(*arguments[2]->getType(), *function.getParameterTypes()[2], true); - appendTypeConversion(*arguments[1]->getType(), *function.getParameterTypes()[1], true); - appendTypeConversion(*arguments[0]->getType(), *function.getParameterTypes()[0], true); + { + unsigned logNumber = int(function.getLocation()) - int(Location::LOG0); + for (int arg = logNumber; arg >= 0; --arg) + { + arguments[arg]->accept(*this); + appendTypeConversion(*arguments[arg]->getType(), *function.getParameterTypes()[arg], true); + } // @todo move this once we actually use memory CompilerUtils(m_context).storeInMemory(0); - m_context << u256(32) << u256(0) << eth::Instruction::LOG4; + m_context << u256(32) << u256(0) << eth::logInstruction(logNumber); break; + } case Location::ECRECOVER: case Location::SHA256: case Location::RIPEMD160: diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 1ddd26f75..bc184dfca 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -857,10 +857,8 @@ BOOST_AUTO_TEST_CASE(log0) " log0(1);\n" " }\n" "}\n"; - u256 amount(130); - compileAndRun(sourceCode, amount + 1); - u160 address(23); - callContractFunction("a()", address, amount); + compileAndRun(sourceCode); + callContractFunction("a()"); BOOST_CHECK_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1))); @@ -874,10 +872,8 @@ BOOST_AUTO_TEST_CASE(log1) " log1(1, 2);\n" " }\n" "}\n"; - u256 amount(130); - compileAndRun(sourceCode, amount + 1); - u160 address(23); - callContractFunction("a()", address, amount); + compileAndRun(sourceCode); + callContractFunction("a()"); BOOST_CHECK_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1))); @@ -892,10 +888,8 @@ BOOST_AUTO_TEST_CASE(log2) " log2(1, 2, 3);\n" " }\n" "}\n"; - u256 amount(130); - compileAndRun(sourceCode, amount + 1); - u160 address(23); - callContractFunction("a()", address, amount); + compileAndRun(sourceCode); + callContractFunction("a()"); BOOST_CHECK_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1))); @@ -911,10 +905,8 @@ BOOST_AUTO_TEST_CASE(log3) " log3(1, 2, 3, 4);\n" " }\n" "}\n"; - u256 amount(130); - compileAndRun(sourceCode, amount + 1); - u160 address(23); - callContractFunction("a()", address, amount); + compileAndRun(sourceCode); + callContractFunction("a()"); BOOST_CHECK_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1))); @@ -930,10 +922,8 @@ BOOST_AUTO_TEST_CASE(log4) " log4(1, 2, 3, 4, 5);\n" " }\n" "}\n"; - u256 amount(130); - compileAndRun(sourceCode, amount + 1); - u160 address(23); - callContractFunction("a()", address, amount); + compileAndRun(sourceCode); + callContractFunction("a()"); BOOST_CHECK_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1))); @@ -942,6 +932,21 @@ BOOST_AUTO_TEST_CASE(log4) BOOST_CHECK_EQUAL(m_logs[0].topics[i], h256(u256(i + 2))); } +BOOST_AUTO_TEST_CASE(log_in_constructor) +{ + char const* sourceCode = "contract test {\n" + " function test() {\n" + " log1(1, 2);\n" + " }\n" + "}\n"; + compileAndRun(sourceCode); + BOOST_CHECK_EQUAL(m_logs.size(), 1); + BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); + BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(1))); + BOOST_CHECK_EQUAL(m_logs[0].topics.size(), 1); + BOOST_CHECK_EQUAL(m_logs[0].topics[0], h256(u256(2))); +} + BOOST_AUTO_TEST_CASE(suicide) { char const* sourceCode = "contract test {\n"