Let's say I've got

contract A {
    event E();

    function a() public {
        emit E();

contract B {
    A private a;

    function b() public {

Now my Dapp is calling the method b:

const contractB = new web3.eth.Contract(BAbi, address)
const receipt = await contractB.methods.B().send({ /* options */ })
const {events, logs} = receipt

events will contain one encoded event. The event will not have an event name and not decoded arguments (in the returnValues field). Thinking of it this makes sense cause the event description wasn't put into the ABI of contract B but into the ABI of A. So the event description wasn't event supplied to a contract.


I've found a straight forward way to solve it by extending the contract B ABI with the events of contract A. A is inside of B, so B can call to A methods and trigger A events. While A's methods are encapsulated, A's events are not. By this line of thinking in makes sense to include A's events in B.

This can be done manually by a copy-paste or with code:

const eventsA = extractEvents(AAbi)
const extendedAbi = [...BAbi, ...eventsA]
const contractB = new web3.eth.Contract(extendedAbi, address)
const receipt = await contractB.methods.B().send({ /* options */ })

or even in a more incautious way:

const extendedAbi = [...BAbi, ...AAbi]

Any thoughs about this pattern? Other solution?

  • That's a very clever hack!
    – Ismael
    May 9 '19 at 19:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.