diff --git a/Changelog.md b/Changelog.md index 9b3639916..c33f00807 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@ Compiler Features: * SMTChecker: Support ``addmod`` and ``mulmod``. * Optimizer: Optimize ``exp`` when base is -1. + * Code generator: Implemented events with function type as one of its indexed parameters. ### 0.7.2 (2020-09-28) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index bb4156b93..0e2c39524 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -867,11 +867,26 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) else { solAssert(paramTypes[arg - 1]->isValueType(), ""); - utils().convertType( - *arguments[arg - 1]->annotation().type, - *paramTypes[arg - 1], - true - ); + if (auto functionType = dynamic_cast(paramTypes[arg - 1])) + { + auto argumentType = + dynamic_cast(arguments[arg-1]->annotation().type); + solAssert( + argumentType && + functionType->kind() == FunctionType::Kind::External && + argumentType->kind() == FunctionType::Kind::External && + !argumentType->bound(), + "" + ); + + utils().combineExternalFunctionType(true); + } + else + utils().convertType( + *arguments[arg - 1]->annotation().type, + *paramTypes[arg - 1], + true + ); } } if (!event.isAnonymous()) diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 22c939d8f..2757e197e 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -929,6 +929,20 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) "(" << IRVariable(arg).commaSeparatedList() << ")"; + else if (auto functionType = dynamic_cast(paramTypes[i])) + { + solAssert( + IRVariable(arg).type() == *functionType && + functionType->kind() == FunctionType::Kind::External && + !functionType->bound(), + "" + ); + define(indexedArgs.emplace_back(m_context.newYulVariable(), *TypeProvider::fixedBytes(32))) << + m_utils.combineExternalFunctionIdFunction() << + "(" << + IRVariable(arg).commaSeparatedList() << + ")\n"; + } else indexedArgs.emplace_back(convert(arg, *paramTypes[i])); } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 5dc022137..efabb2bb5 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -2453,6 +2453,38 @@ BOOST_AUTO_TEST_CASE(event_indexed_string) BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("E(string,uint256[4])"))); } +BOOST_AUTO_TEST_CASE(event_indexed_function) +{ + char const* sourceCode = R"( + contract C { + event Test(function() external indexed); + function f() public { + emit Test(this.f); + } + } + )"; + + ALSO_VIA_YUL( + DISABLE_EWASM_TESTRUN() + + compileAndRun(sourceCode); + callContractFunction("f()"); + BOOST_REQUIRE_EQUAL(numLogs(), 1); + BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); + BOOST_CHECK(logData(0) == bytes()); + BOOST_REQUIRE_EQUAL(numLogTopics(0), 2); + + bytes functionHash = util::keccak256("f()").asBytes(); + bytes address = m_contractAddress.asBytes(); + bytes selector = bytes(functionHash.cbegin(), functionHash.cbegin() + 4); + bytes padding = bytes(8, 0); + bytes functionABI = address + selector + padding; + + BOOST_CHECK_EQUAL(logTopic(0, 1).hex(), util::toHex(functionABI)); + BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("Test(function)"))); + ) +} + BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) { char const* sourceCode = R"( diff --git a/test/libsolidity/syntaxTests/events/event_function_type_indexed.sol b/test/libsolidity/syntaxTests/events/event_function_type_indexed.sol new file mode 100644 index 000000000..cc0a573a9 --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_function_type_indexed.sol @@ -0,0 +1,6 @@ +contract C { + event Test(function() external indexed); + function f() public { + emit Test(this.f); + } +} diff --git a/test/libsolidity/syntaxTests/events/event_library_function.sol b/test/libsolidity/syntaxTests/events/event_library_function.sol new file mode 100644 index 000000000..4eba5202f --- /dev/null +++ b/test/libsolidity/syntaxTests/events/event_library_function.sol @@ -0,0 +1,35 @@ +library L { + function f() public { + int x = 1; + } +} + +contract C { + event Test(function() external indexed); + + function g() public { + Test(L.f); + } +} + +contract D { + event Test(function() external); + + function f() public { + Test(L.f); + } +} + +contract E { + event Test(function() external indexed); + + using L for D; + + function k() public { + Test(D.f); + } +} +// ---- +// TypeError 9553: (140-143): Invalid type for argument in function call. Invalid implicit conversion from function () to function () external requested. +// TypeError 9553: (230-233): Invalid type for argument in function call. Invalid implicit conversion from function () to function () external requested. +// TypeError 9553: (345-348): Invalid type for argument in function call. Invalid implicit conversion from function D.f() to function () external requested.