diff --git a/libsolidity/AST.h b/libsolidity/AST.h index f5f6a3f38..335b9a880 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -553,17 +553,24 @@ private: class EventDefinition: public Declaration, public VariableScope, public Documented { public: - EventDefinition(SourceLocation const& _location, - ASTPointer const& _name, - ASTPointer const& _documentation, - ASTPointer const& _parameters): - Declaration(_location, _name), Documented(_documentation), m_parameters(_parameters) {} + EventDefinition( + SourceLocation const& _location, + ASTPointer const& _name, + ASTPointer const& _documentation, + ASTPointer const& _parameters, + bool _anonymous = false + ): + Declaration(_location, _name), + Documented(_documentation), + m_parameters(_parameters), + m_anonymous(_anonymous){} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; std::vector> const& getParameters() const { return m_parameters->getParameters(); } ParameterList const& getParameterList() const { return *m_parameters; } + bool isAnonymous() const { return m_anonymous; } virtual TypePointer getType(ContractDefinition const* = nullptr) const override { @@ -574,6 +581,7 @@ public: private: ASTPointer m_parameters; + bool m_anonymous = false; }; /** diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index a0a688bbd..61b17f663 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -542,8 +542,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) appendTypeConversion(*arguments[arg - 1]->getType(), *function.getParameterTypes()[arg - 1], true); } - m_context << u256(h256::Arith(dev::sha3(function.getCanonicalSignature(event.getName())))); - ++numIndexed; + if (!event.isAnonymous()) + { + m_context << u256(h256::Arith(dev::sha3(function.getCanonicalSignature(event.getName())))); + ++numIndexed; + } solAssert(numIndexed <= 4, "Too many indexed arguments."); // Copy all non-indexed arguments to memory (data) m_context << u256(0); diff --git a/libsolidity/InterfaceHandler.cpp b/libsolidity/InterfaceHandler.cpp index 99a7db96e..406d1e24a 100644 --- a/libsolidity/InterfaceHandler.cpp +++ b/libsolidity/InterfaceHandler.cpp @@ -70,6 +70,7 @@ std::unique_ptr InterfaceHandler::getABIInterface(ContractDefinitio Json::Value event; event["type"] = "event"; event["name"] = it->getName(); + event["anonymous"] = it->isAnonymous(); Json::Value params(Json::arrayValue); for (auto const& p: it->getParameters()) { diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 459a34bd0..393d2734e 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -394,9 +394,15 @@ ASTPointer Parser::parseEventDefinition() parameters = parseParameterList(true, true); else parameters = createEmptyParameterList(); + bool anonymous = false; + if (m_scanner->getCurrentToken() == Token::Anonymous) + { + anonymous = true; + m_scanner->next(); + } nodeFactory.markEndPosition(); expectToken(Token::Semicolon); - return nodeFactory.createNode(name, docstring, parameters); + return nodeFactory.createNode(name, docstring, parameters, anonymous); } ASTPointer Parser::parseModifierInvocation() diff --git a/libsolidity/Token.h b/libsolidity/Token.h index 2d8a49fcd..b2951e939 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -145,6 +145,7 @@ namespace solidity K(Break, "break", 0) \ K(Case, "case", 0) \ K(Const, "constant", 0) \ + K(Anonymous, "anonymous", 0) \ K(Continue, "continue", 0) \ K(Contract, "contract", 0) \ K(Default, "default", 0) \ diff --git a/test/SolidityABIJSON.cpp b/test/SolidityABIJSON.cpp index 195270138..f7f968ea8 100644 --- a/test/SolidityABIJSON.cpp +++ b/test/SolidityABIJSON.cpp @@ -309,6 +309,7 @@ BOOST_AUTO_TEST_CASE(events) { "name": "e1", "type": "event", + "anonymous": false, "inputs": [ { "indexed": false, @@ -325,6 +326,7 @@ BOOST_AUTO_TEST_CASE(events) { "name": "e2", "type": "event", + "anonymous": false, "inputs": [] } @@ -333,6 +335,23 @@ BOOST_AUTO_TEST_CASE(events) checkInterface(sourceCode, interface); } +BOOST_AUTO_TEST_CASE(events_anonymous) +{ + char const* sourceCode = "contract test {\n" + " event e() anonymous; \n" + "}\n"; + char const* interface = R"([ + { + "name": "e", + "type": "event", + "anonymous": true, + "inputs": [] + } + + ])"; + + checkInterface(sourceCode, interface); +} BOOST_AUTO_TEST_CASE(inherited) { @@ -380,6 +399,7 @@ BOOST_AUTO_TEST_CASE(inherited) { "name": "derivedEvent", "type": "event", + "anonymous": false, "inputs": [{ "indexed": true, @@ -390,6 +410,7 @@ BOOST_AUTO_TEST_CASE(inherited) { "name": "baseEvent", "type": "event", + "anonymous": false, "inputs": [{ "indexed": true, diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index e4b55514d..ce7a472bc 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -2202,6 +2202,43 @@ BOOST_AUTO_TEST_CASE(event_no_arguments) BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::sha3(string("Deposit()"))); } +BOOST_AUTO_TEST_CASE(event_anonymous) +{ + char const* sourceCode = R"( + contract ClientReceipt { + event Deposit() anonymous; + function deposit() { + Deposit(); + } + } + )"; + compileAndRun(sourceCode); + callContractFunction("deposit()"); + BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 0); +} + +BOOST_AUTO_TEST_CASE(event_anonymous_with_topics) +{ + char const* sourceCode = R"( + contract ClientReceipt { + event Deposit(address indexed _from, bytes32 indexed _id, uint _value) anonymous; + function deposit(bytes32 _id, bool _manually) { + Deposit(msg.sender, _id, msg.value); + } + } + )"; + compileAndRun(sourceCode); + u256 value(18); + u256 id(0x1234); + callContractFunctionWithValue("deposit(bytes32,bool)", value, id); + BOOST_REQUIRE_EQUAL(m_logs.size(), 1); + BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); + BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(value))); + BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2); + BOOST_CHECK_EQUAL(m_logs[0].topics[0], h256(m_sender)); + BOOST_CHECK_EQUAL(m_logs[0].topics[1], h256(id)); +} + BOOST_AUTO_TEST_CASE(event_lots_of_data) { char const* sourceCode = R"(