[Ethereum] Transaction receipt contains all log entries, but only the last two are decoded by web3

eventstransactionsweb3js

I have a flow which yields 4 events.

When I obtain the transaction hash via web3.js, I can see that all 4 events are included in the receipt logs, but only the last 2 events are in the decoded logs (which means I have to decode the first 2 events myself):

{
    "receipt": {
        ...
        "logs": [
            {
                "logIndex": 0,
                ...
            },
            {
                "logIndex": 1,
                ...
            },
            {
                "logIndex": 2,
                ...
            },
            {
                "logIndex": 3,
                ...
            }
        ],
        ...
    },
    "logs": [
        {
            "logIndex": 2,
            ...
        },
        {
            "logIndex": 3,
            ...
        }
    ]
}

What is the reason for this?

Best Answer

OK, I understand the reason:

All the events generated during the execution of the function called by web3 are included in the receipt logs, but only the events generated in the scope of the contract in which the function is implemented are included in the decoded logs.

For example, given the following on-chain code:

File IContract1.sol:

pragma solidity ^0.4.18;

interface IContract1 {
    function func(uint256 x) external returns (uint256);
}

File Contract1.sol:

pragma solidity ^0.4.18;
import "./IContract1.sol";

contract Contract1 is IContract1{
    event Event1(uint256 x);
    function func(uint256 x) external returns (uint256) {
        Event1(x);
        return x;
    }
}

File Contract2.sol:

pragma solidity ^0.4.18;
import "./IContract1.sol";

contract Contract2 {
    IContract1 private contract1;
    function Contract2(IContract1 _contract1) public {
        contract1 = _contract1;
    }
    event Event2(uint256 x);
    function func(uint256 x) external returns (uint256) {
        Event2(x);
        return contract1.func(x);
    }
}

If I execute the following off-chain code:

let contract1 = await artifacts.require("Contract1.sol").new();
let contract2 = await artifacts.require("Contract2.sol").new(contract1.address);

let hash = await contract2.func(42);

Then hash.receipt.logs will include both Event1 and Event2.

But hash.logs will include only Event2.

Related Topic