[Sol - Yul] Add support for built-in logN().

This commit is contained in:
Alexander Arlt 2020-04-24 16:33:43 -05:00
parent ed6c6b3170
commit 66edaf43f4
2 changed files with 108 additions and 65 deletions

View File

@ -818,6 +818,33 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
define(_functionCall) << "selfdestruct(" << expressionAsType(*arguments.front(), *parameterTypes.front()) << ")\n"; define(_functionCall) << "selfdestruct(" << expressionAsType(*arguments.front(), *parameterTypes.front()) << ")\n";
break; break;
} }
case FunctionType::Kind::Log0:
case FunctionType::Kind::Log1:
case FunctionType::Kind::Log2:
case FunctionType::Kind::Log3:
case FunctionType::Kind::Log4:
{
unsigned logNumber = int(functionType->kind()) - int(FunctionType::Kind::Log0);
solAssert(arguments.size() == logNumber + 1, "");
ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector());
string indexedArgs;
for (unsigned arg = 0; arg < logNumber; ++arg)
indexedArgs += ", " + expressionAsType(*arguments[arg + 1], *(parameterTypes[arg + 1]));
Whiskers templ(R"({
let <pos> := <freeMemory>
let <end> := <encode>(<pos>, <nonIndexedArgs>)
<log>(<pos>, sub(<end>, <pos>) <indexedArgs>)
})");
templ("pos", m_context.newYulVariable());
templ("end", m_context.newYulVariable());
templ("freeMemory", freeMemory());
templ("encode", abi.tupleEncoder({arguments.front()->annotation().type},{parameterTypes.front()}));
templ("nonIndexedArgs", IRVariable(*arguments.front()).commaSeparatedList());
templ("log", "log" + to_string(logNumber));
templ("indexedArgs", indexedArgs);
m_code << templ.render();
break;
}
default: default:
solUnimplemented("FunctionKind " + toString(static_cast<int>(functionType->kind())) + " not yet implemented"); solUnimplemented("FunctionKind " + toString(static_cast<int>(functionType->kind())) + " not yet implemented");
} }

View File

@ -1126,12 +1126,14 @@ BOOST_AUTO_TEST_CASE(log0)
} }
} }
)"; )";
compileAndRun(sourceCode); ALSO_VIA_YUL(
callContractFunction("a()"); compileAndRun(sourceCode);
BOOST_REQUIRE_EQUAL(numLogs(), 1); callContractFunction("a()");
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_CHECK_EQUAL(numLogTopics(0), 0); BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_CHECK_EQUAL(numLogTopics(0), 0);
)
} }
BOOST_AUTO_TEST_CASE(log1) BOOST_AUTO_TEST_CASE(log1)
@ -1143,13 +1145,15 @@ BOOST_AUTO_TEST_CASE(log1)
} }
} }
)"; )";
compileAndRun(sourceCode); ALSO_VIA_YUL(
callContractFunction("a()"); compileAndRun(sourceCode);
BOOST_REQUIRE_EQUAL(numLogs(), 1); callContractFunction("a()");
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1); BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2))); BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2)));
)
} }
BOOST_AUTO_TEST_CASE(log2) BOOST_AUTO_TEST_CASE(log2)
@ -1161,14 +1165,16 @@ BOOST_AUTO_TEST_CASE(log2)
} }
} }
)"; )";
compileAndRun(sourceCode); ALSO_VIA_YUL(
callContractFunction("a()"); compileAndRun(sourceCode);
BOOST_REQUIRE_EQUAL(numLogs(), 1); callContractFunction("a()");
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogTopics(0), 2); BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
for (unsigned i = 0; i < 2; ++i) BOOST_REQUIRE_EQUAL(numLogTopics(0), 2);
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2))); for (unsigned i = 0; i < 2; ++i)
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
)
} }
BOOST_AUTO_TEST_CASE(log3) BOOST_AUTO_TEST_CASE(log3)
@ -1180,14 +1186,16 @@ BOOST_AUTO_TEST_CASE(log3)
} }
} }
)"; )";
compileAndRun(sourceCode); ALSO_VIA_YUL(
callContractFunction("a()"); compileAndRun(sourceCode);
BOOST_REQUIRE_EQUAL(numLogs(), 1); callContractFunction("a()");
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3); BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
for (unsigned i = 0; i < 3; ++i) BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2))); for (unsigned i = 0; i < 3; ++i)
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
)
} }
BOOST_AUTO_TEST_CASE(log4) BOOST_AUTO_TEST_CASE(log4)
@ -1199,14 +1207,16 @@ BOOST_AUTO_TEST_CASE(log4)
} }
} }
)"; )";
compileAndRun(sourceCode); ALSO_VIA_YUL(
callContractFunction("a()"); compileAndRun(sourceCode);
BOOST_REQUIRE_EQUAL(numLogs(), 1); callContractFunction("a()");
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogTopics(0), 4); BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
for (unsigned i = 0; i < 4; ++i) BOOST_REQUIRE_EQUAL(numLogTopics(0), 4);
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2))); for (unsigned i = 0; i < 4; ++i)
BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2)));
)
} }
BOOST_AUTO_TEST_CASE(log_in_constructor) BOOST_AUTO_TEST_CASE(log_in_constructor)
@ -1218,12 +1228,14 @@ BOOST_AUTO_TEST_CASE(log_in_constructor)
} }
} }
)"; )";
compileAndRun(sourceCode); ALSO_VIA_YUL(
BOOST_REQUIRE_EQUAL(numLogs(), 1); compileAndRun(sourceCode);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1); BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1)));
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2))); BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2)));
)
} }
BOOST_AUTO_TEST_CASE(selfdestruct) BOOST_AUTO_TEST_CASE(selfdestruct)
@ -1776,20 +1788,22 @@ BOOST_AUTO_TEST_CASE(event)
} }
} }
)"; )";
compileAndRun(sourceCode); ALSO_VIA_YUL(
u256 value(18); compileAndRun(sourceCode);
u256 id(0x1234); u256 value(18);
for (bool manually: {true, false}) u256 id(0x1234);
{ for (bool manually: {true, false})
callContractFunctionWithValue("deposit(bytes32,bool)", value, id, manually); {
BOOST_REQUIRE_EQUAL(numLogs(), 1); callContractFunctionWithValue("deposit(bytes32,bool)", value, id, manually);
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(value))); BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogTopics(0), 3); BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(value)));
BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("Deposit(address,bytes32,uint256)"))); BOOST_REQUIRE_EQUAL(numLogTopics(0), 3);
BOOST_CHECK_EQUAL(logTopic(0, 1), h256(m_sender, h256::AlignRight)); BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("Deposit(address,bytes32,uint256)")));
BOOST_CHECK_EQUAL(logTopic(0, 2), h256(id)); BOOST_CHECK_EQUAL(logTopic(0, 1), h256(m_sender, h256::AlignRight));
} BOOST_CHECK_EQUAL(logTopic(0, 2), h256(id));
}
)
} }
BOOST_AUTO_TEST_CASE(event_emit) BOOST_AUTO_TEST_CASE(event_emit)
@ -1803,7 +1817,7 @@ BOOST_AUTO_TEST_CASE(event_emit)
} }
)"; )";
ALSO_VIA_YUL( ALSO_VIA_YUL(
compileAndRun(sourceCode); compileAndRun(sourceCode);
u256 value(18); u256 value(18);
u256 id(0x1234); u256 id(0x1234);
callContractFunctionWithValue("deposit(bytes32)", value, id); callContractFunctionWithValue("deposit(bytes32)", value, id);
@ -1852,13 +1866,15 @@ BOOST_AUTO_TEST_CASE(event_access_through_base_name_emit)
} }
} }
)"; )";
compileAndRun(sourceCode); ALSO_VIA_YUL(
callContractFunction("f()"); compileAndRun(sourceCode);
BOOST_REQUIRE_EQUAL(numLogs(), 1); callContractFunction("f()");
BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); BOOST_REQUIRE_EQUAL(numLogs(), 1);
BOOST_CHECK(logData(0).empty()); BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress);
BOOST_REQUIRE_EQUAL(numLogTopics(0), 1); BOOST_CHECK(logData(0).empty());
BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("x()"))); BOOST_REQUIRE_EQUAL(numLogTopics(0), 1);
BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("x()")));
);
} }
BOOST_AUTO_TEST_CASE(events_with_same_name) BOOST_AUTO_TEST_CASE(events_with_same_name)