Ethers.js: structs in events with ABIEncoderV2

Created on 30 Jan 2018  ·  9Comments  ·  Source: ethers-io/ethers.js

Issue https://github.com/ethers-io/ethers.js/issues/84 covered passing a struct into a public or external function. This issue covers structs in an event emitted from a contract.

I've created the following project to experiment with structs in functions and events.
https://github.com/naddison36/immutable-events

It has the following simple contract ImmutableEvents.sol

pragma solidity ^0.4.19;
pragma experimental ABIEncoderV2;

contract ImmutableEvents
{
    // Used to generate a unique id for each event that is emmitted
    // starting at 1 rather than 0 so it's clear an evenit id has been set. ie it's not 0 which is what numbers is initialised to
    uint256 public id = 1;

    struct KeyValue {
        string key;
        string value;
    }

    event ImmutableEvent(uint256 id, KeyValue[] keyValues);
    // Is only used for testing
    event SimpleEvent(uint256 id);

    function emitEvent(KeyValue[] keyValues) public returns (bool)
    {
        ImmutableEvent(id++, keyValues);

        // is only used for testing
        SimpleEvent(id);

        return true;
    }
}

The Jest tests in ImmutableEvents.test.ts fails on the following line as it does not return any ImmutableEvent events. That is, it returns an empty array of events when it should return one. https://github.com/naddison36/immutable-events/blob/master/src/js/__tests__/ImmutableEvents.test.ts#L53

The SimpleEvent emitted in the same function call works so we know the emitEvent function call in the test was successful.

The getEvents function is defined in BaseContract.ts

My guess is the encoding of the struct in the topic is different hence Ethers can not find the topic.
Alternatively, there could be a problem in the Solidity compiler with ABIEncoderV2.

@ricmoo @splut have you got structs working in events with ABIEncoderV2?

bug fixed

Most helpful comment

This is now fully functional and tested. Events, passing parameters in and return parameters works with ABI v2 as of [email protected]. For tests, check out tests/test-contract.js.

Thanks! :)

All 9 comments

I tested the above using Parity/v1.9.0-beta-53ec114-20180125/x86_64-macos/rustc1.23.0

When I test using Geth 1.7.3-stable, I get the following error: invalid argument 0: hex number with leading zero digits

I have not tested structs in events yet... I will try out your sample this week and see what the issue may be... I seem to recall at some point thinking “hmmm. This may be an issue for structs and events”... I’m sure once I replicate it, it will be easy to fix. :)

@ricmoo please add this, also just fooling around with Interface.encode/decode params last night. So easy to integrate. Nice module isolation as well, going to make it a real easy switch over. Although I currently dont have names when I encodeParams, so will need to come up with those (maybe just use types for now).. anyway.. continue like a Firefly ;)

Any progress on this @ricmoo ? Let me know if you need any help

Sorry, haven't had a chance to look at it. Maybe tomorrow? I'm almost finished generalizing the Provider Bridge, which allow existing Web3 applications to seamlessly work over Ethers. Very cool things are coming. :)

If you wanted to take a quick look, I suspect only a very small change is required, but I suspect it will take me a few hours to adjust the test case procedural generation to export the test cases for events, since I will probably include solidity-hashing at the same time. Once I have the test cases, it should be quick to add.

This is now fully functional and tested. Events, passing parameters in and return parameters works with ABI v2 as of [email protected]. For tests, check out tests/test-contract.js.

Thanks! :)

Well done, @ricmoo. I've upgraded my project to Ethers.js 3.0.1 and got struts in events working.
Here's the working unit test https://github.com/naddison36/immutable-events/blob/master/src/js/__tests__/ImmutableEvents.test.ts#L47

Note I had to change the way I got the Event object from the contract interface from
const Event = this.contract.interface.events[eventName]();
to
const Event = this.contract.interface.events[eventName];
See the following for the full implemention
https://github.com/naddison36/immutable-events/blob/master/src/js/BaseContract.ts#L232

Ah yes! I should add that to the list of non-backward compatible CKchanges.

It never really made sense to force calling the function, since with events it’s static; that was a reminder from using the same code as the functions, which need to know the passed parameters to compute some of the variables.

Thanks! I’ll add those in the morning. :)

I’ll be posting a quick how-to tomorrow too; I’ll add the link to this ticket once it’s published.

I agree the new Events implementation is better.

Was this page helpful?
0 / 5 - 0 ratings