From b14d22d11e9fb63225fa4222f2ac342f1c3ee39f Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 19 Feb 2019 17:35:24 +0100 Subject: [PATCH 1/2] Tests for events with structs in libraries. --- test/libsolidity/ABIEncoderTests.cpp | 1 + test/libsolidity/SolidityEndToEndTest.cpp | 29 +++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index b6e6cedd4..f56b8ad1f 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -444,6 +444,7 @@ BOOST_AUTO_TEST_CASE(structs) ); BOOST_CHECK(callContractFunction("f()") == encoded); REQUIRE_LOG_DATA(encoded); + BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("e(uint16,(uint16,uint16,(uint64[2])[],uint16))"))); ) } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 6c1e31f7f..c540ef320 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -14097,6 +14097,35 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_arrayOfStrings) BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(arrayEncoding))); } +BOOST_AUTO_TEST_CASE(event_signature_in_library) +{ + // This tests a bug that was present where the "internal signature" + // for structs was also used for events. + char const* sourceCode = R"( + pragma experimental ABIEncoderV2; + library L { + struct S { + uint8 a; + int16 b; + } + event E(S indexed, S); + function f() internal { + S memory s; + emit E(s, s); + } + } + contract C { + constructor() public { + L.f(); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2); + BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16),(uint8,int16))"))); +} + + BOOST_AUTO_TEST_CASE(abi_encode_with_selector) { char const* sourceCode = R"( From fb07462d82343da25fe13b7a923338c9d46132d5 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 19 Feb 2019 17:35:38 +0100 Subject: [PATCH 2/2] Fix: Do use actual ABI signatures for events also in libraries instead of internal signature. --- Changelog.md | 1 + libsolidity/ast/Types.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index b1f48f630..6867f8596 100644 --- a/Changelog.md +++ b/Changelog.md @@ -12,6 +12,7 @@ Bugfixes: * ABIEncoderV2: Fix internal error related to bare delegatecall. * ABIEncoderV2: Fix internal error related to ecrecover. * ABIEncoderV2: Fix internal error related to mappings as library parameters. + * ABIEncoderV2: Fix invalid signature for events containing structs emitted in libraries. * Inline Assembly: Proper error message for missing variables. * SMTChecker: Fixed crash when used with fixed-sized arrays. * Yul: Properly detect name clashes with functions before their declaration. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 96808645f..dc2b2a850 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3062,7 +3062,8 @@ string FunctionType::externalSignature() const solAssert(false, "Invalid function type for requesting external signature."); } - bool const inLibrary = dynamic_cast(*m_declaration->scope()).isLibrary(); + // "inLibrary" is only relevant if this is not an event. + bool const inLibrary = kind() != Kind::Event && dynamic_cast(*m_declaration->scope()).isLibrary(); FunctionTypePointer external = interfaceFunctionType(); solAssert(!!external, "External function type requested."); auto parameterTypes = external->parameterTypes();