Skip to content

Commit

Permalink
[TT-1824] decode all events in all contracts (#1287)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tofel authored Oct 31, 2024
1 parent 2a8e6cd commit 7437e46
Show file tree
Hide file tree
Showing 31 changed files with 1,257 additions and 43 deletions.
1 change: 1 addition & 0 deletions seth/.changeset/v1.50.8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fix a bug, which resulted in not decoding events emitted from contracts other than the the transaction entrypoint, even if we had their ABIs
11 changes: 9 additions & 2 deletions seth/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@
build:
solc --abi --overwrite -o contracts/abi contracts/NetworkDebugContract.sol
solc --bin --overwrite -o contracts/bin contracts/NetworkDebugContract.sol
abigen --bin=contracts/bin/NetworkDebugContract.bin --abi=contracts/abi/NetworkDebugContract.abi --pkg=network_debug_contract --out=contracts/bind/debug/NetworkDebugContract.go
abigen --bin=contracts/bin/NetworkDebugContract.bin --abi=contracts/abi/NetworkDebugContract.abi --pkg=network_debug_contract --out=contracts/bind/NetworkDebugContract/NetworkDebugContract.go
solc --abi --overwrite -o contracts/abi contracts/NetworkDebugSubContract.sol
solc --bin --overwrite -o contracts/bin contracts/NetworkDebugSubContract.sol
abigen --bin=contracts/bin/NetworkDebugSubContract.bin --abi=contracts/abi/NetworkDebugSubContract.abi --pkg=network_debug_sub_contract --out=contracts/bind/sub/NetworkDebugSubContract.go
abigen --bin=contracts/bin/NetworkDebugSubContract.bin --abi=contracts/abi/NetworkDebugSubContract.abi --pkg=network_debug_sub_contract --out=contracts/bind/NetworkDebugSubContract/NetworkDebugSubContract.go

solc --abi --overwrite -o contracts/abi contracts/TestContractOne.sol
solc --bin --overwrite -o contracts/bin contracts/TestContractOne.sol
abigen --bin=contracts/bin/TestContractOne.bin --abi=contracts/abi/TestContractOne.abi --pkg=unique_event_one --out=contracts/bind/TestContractOne/TestContractOne.go
solc --abi --overwrite -o contracts/abi contracts/TestContractTwo.sol
solc --bin --overwrite -o contracts/bin contracts/TestContractTwo.sol
abigen --bin=contracts/bin/TestContractTwo.bin --abi=contracts/abi/TestContractTwo.abi --pkg=unique_event_two --out=contracts/bind/TestContractTwo/TestContractTwo.go

.PHONY: AnvilSync
AnvilSync:
Expand Down
38 changes: 21 additions & 17 deletions seth/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1222,25 +1222,29 @@ func (t TransactionLog) GetData() []byte {
return t.Data
}

func (m *Client) decodeContractLogs(l zerolog.Logger, logs []types.Log, a abi.ABI) ([]DecodedTransactionLog, error) {
l.Trace().Msg("Decoding events")
func (m *Client) decodeContractLogs(l zerolog.Logger, logs []types.Log, allABIs []*abi.ABI) ([]DecodedTransactionLog, error) {
l.Trace().Msg("Decoding ALL events")
var eventsParsed []DecodedTransactionLog
for _, lo := range logs {
for _, evSpec := range a.Events {
if evSpec.ID.Hex() == lo.Topics[0].Hex() {
d := TransactionLog{lo.Topics, lo.Data}
l.Trace().Str("Name", evSpec.RawName).Str("Signature", evSpec.Sig).Msg("Unpacking event")
eventsMap, topicsMap, err := decodeEventFromLog(l, a, evSpec, d)
if err != nil {
return nil, errors.Wrap(err, ErrDecodeLog)
}
parsedEvent := decodedLogFromMaps(&DecodedTransactionLog{}, eventsMap, topicsMap)
if decodedTransactionLog, ok := parsedEvent.(*DecodedTransactionLog); ok {
decodedTransactionLog.Signature = evSpec.Sig
m.mergeLogMeta(decodedTransactionLog, lo)
eventsParsed = append(eventsParsed, *decodedTransactionLog)
l.Trace().Interface("Log", parsedEvent).Msg("Transaction log")
} else {
ABI_LOOP:
for _, a := range allABIs {
for _, evSpec := range a.Events {
if evSpec.ID.Hex() == lo.Topics[0].Hex() {
d := TransactionLog{lo.Topics, lo.Data}
l.Trace().Str("Name", evSpec.RawName).Str("Signature", evSpec.Sig).Msg("Unpacking event")
eventsMap, topicsMap, err := decodeEventFromLog(l, *a, evSpec, d)
if err != nil {
return nil, errors.Wrap(err, ErrDecodeLog)
}
parsedEvent := decodedLogFromMaps(&DecodedTransactionLog{}, eventsMap, topicsMap)
decodedTransactionLog, ok := parsedEvent.(*DecodedTransactionLog)
if ok {
decodedTransactionLog.Signature = evSpec.Sig
m.mergeLogMeta(decodedTransactionLog, lo)
eventsParsed = append(eventsParsed, *decodedTransactionLog)
l.Trace().Interface("Log", parsedEvent).Msg("Transaction log")
break ABI_LOOP
}
l.Trace().
Str("Actual type", fmt.Sprintf("%T", decodedTransactionLog)).
Msg("Failed to cast decoded event to DecodedCommonLog")
Expand Down
4 changes: 2 additions & 2 deletions seth/client_main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-testing-framework/seth"
network_debug_contract "github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/debug"
network_debug_contract "github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/NetworkDebugContract"
network_sub_contract "github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/NetworkDebugSubContract"
link_token "github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/link"
network_sub_contract "github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/sub"
)

/*
Expand Down
77 changes: 76 additions & 1 deletion seth/client_trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import (
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-testing-framework/seth"
network_debug_contract "github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/debug"
network_debug_contract "github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/NetworkDebugContract"
"github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/TestContractOne"
"github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/TestContractTwo"
link_token "github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/link"
"github.com/smartcontractkit/chainlink-testing-framework/seth/contracts/bind/link_token_interface"
"github.com/smartcontractkit/chainlink-testing-framework/seth/test_utils"
Expand Down Expand Up @@ -1786,6 +1788,79 @@ func TestTraceVariousCallTypesAndNestingLevels(t *testing.T) {
require.Equal(t, 4, c.Tracer.GetDecodedCalls(decodedTx.Hash)[8].NestingLevel, "expected nesting level to be 4")
}

func TestNestedEvents(t *testing.T) {
c := newClientWithContractMapFromEnv(t)
SkipAnvil(t, c)

tx, txErr := TestEnv.DebugContract.TraceNestedEvents(c.NewTXOpts())
require.NoError(t, txErr, "transaction should have succeeded")
decoded, decodeErr := c.Decode(tx, txErr)
require.NoError(t, decodeErr, "transaction should have succeeded")

expectedLogs := []seth.DecodedCommonLog{
{
Signature: "UniqueSubDebugEvent()",
Address: TestEnv.DebugSubContractAddress,
EventData: map[string]interface{}{},
Topics: []string{"0xe0b03c5e88196d907268b0babc690e041bdc7fcc1abf4bbf1e363e28c17e6b9b"},
},
{
Signature: "UniqueDebugEvent()",
Address: TestEnv.DebugContractAddress,
EventData: map[string]interface{}{},
Topics: []string{"0xa0f7c7c1fff15178b5db3e56860767f0889c56b591bd2d9ba3121b491347d74c"},
},
}

require.Equal(t, 2, len(decoded.Events), "expected 2 events")
var actualEvents []seth.DecodedCommonLog
for _, event := range decoded.Events {
actualEvents = append(actualEvents, event.DecodedCommonLog)
}

require.EqualValues(t, expectedLogs, actualEvents, "decoded events do not match")
}

func TestSameEventTwoABIs(t *testing.T) {
c := newClientWithContractMapFromEnv(t)
SkipAnvil(t, c)

contractAbi, err := TestContractOne.UniqueEventOneMetaData.GetAbi()
require.NoError(t, err, "failed to get contract ABI")
oneData, err := c.DeployContract(c.NewTXOpts(), "TestContractOne", *contractAbi, common.FromHex(TestContractOne.UniqueEventOneMetaData.Bin))
require.NoError(t, err, "failed to deploy contract")

contractAbi, err = TestContractTwo.UniqueEventTwoMetaData.GetAbi()
require.NoError(t, err, "failed to get contract ABI")
_, err = c.DeployContract(c.NewTXOpts(), "TestContractTwo", *contractAbi, common.FromHex(TestContractTwo.UniqueEventTwoMetaData.Bin))
require.NoError(t, err, "failed to deploy contract")

oneInstance, err := TestContractOne.NewUniqueEventOne(oneData.Address, c.Client)
require.NoError(t, err, "failed to create contract instance")
decoded, txErr := c.Decode(oneInstance.ExecuteFirstOperation(c.NewTXOpts(), big.NewInt(1), big.NewInt(2)))
require.NoError(t, txErr, "transaction should have succeeded")

expectedLogs := []seth.DecodedCommonLog{
{
Signature: "NonUniqueEvent(int256,int256)",
Address: oneData.Address,
EventData: map[string]interface{}{
"a": big.NewInt(1),
"b": big.NewInt(2),
},
Topics: []string{"0x192aedde7837c0cbfb2275e082ba2391de36cf5a893681e9dac2cced6947614e", "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000002"},
},
}

require.Equal(t, 1, len(decoded.Events), "expected 1 event")
var actualEvents []seth.DecodedCommonLog
for _, event := range decoded.Events {
actualEvents = append(actualEvents, event.DecodedCommonLog)
}

require.EqualValues(t, expectedLogs, actualEvents, "decoded events do not match")
}

func removeGasDataFromDecodedCalls(decodedCall map[string][]*seth.DecodedCall) {
for _, decodedCalls := range decodedCall {
for _, call := range decodedCalls {
Expand Down
13 changes: 13 additions & 0 deletions seth/contract_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ func (c *ContractStore) GetABI(name string) (*abi.ABI, bool) {
return &abi, ok
}

func (c *ContractStore) GetAllABIs() []*abi.ABI {
c.mu.Lock()
defer c.mu.Unlock()

var allABIs []*abi.ABI
for _, a := range c.ABIs {
alias := a
allABIs = append(allABIs, &alias)
}

return allABIs
}

func (c *ContractStore) AddABI(name string, abi abi.ABI) {
if !strings.HasSuffix(name, ".abi") {
name = name + ".abi"
Expand Down
8 changes: 4 additions & 4 deletions seth/contract_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,23 @@ func TestSmokeContractABIStore(t *testing.T) {
{
name: "can load the ABI only from ABI files",
abiPath: "./contracts/abi",
expectedABICount: 5,
expectedABICount: 8,
},
{
name: "can load the ABI from ABI files and from gethwrappers",
abiPath: "./contracts/abi",
gethWrappersPaths: []string{"./contracts/bind"},
expectedABICount: 10,
expectedABICount: 11,
},
{
name: "can load the ABI only from gethwrappers",
gethWrappersPaths: []string{"./contracts/bind"},
expectedABICount: 5,
expectedABICount: 7,
},
{
name: "can load the ABI from 2 gethwrappers folders",
gethWrappersPaths: []string{"./contracts/bind", "./contracts/bind2"},
expectedABICount: 6,
expectedABICount: 8,
},
{
name: "can't open the ABI path",
Expand Down
6 changes: 6 additions & 0 deletions seth/contracts/AbstractContractWithEvent.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

abstract contract AbstractContractWithEvent {
event NonUniqueEvent(int256 indexed a, int256 indexed b);
}
6 changes: 6 additions & 0 deletions seth/contracts/NetworkDebugContract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ contract NetworkDebugContract {
event ThreeIndexEvent(uint256 indexed roundId, address indexed startedBy, uint256 indexed startedAt);
event ThreeIndexAndOneNonIndexedEvent(uint256 indexed roundId, address indexed startedBy, uint256 indexed startedAt, string dataId);
event CallbackEvent(int256 indexed a);
event UniqueDebugEvent();

/* Struct events */

Expand Down Expand Up @@ -113,6 +114,11 @@ contract NetworkDebugContract {
return x + y;
}

function traceNestedEvents() public {
subContract.traceUniqueEvent();
emit UniqueDebugEvent();
}

/* Events */

function emitNoIndexEventString() public {
Expand Down
5 changes: 5 additions & 0 deletions seth/contracts/NetworkDebugSubContract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ contract NetworkDebugSubContract {
event OneIndexEvent(uint indexed a);
event TwoIndexEvent(uint256 indexed roundId, address indexed startedBy);
event ThreeIndexEvent(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
event UniqueSubDebugEvent();

/* Struct events */

Expand Down Expand Up @@ -50,6 +51,10 @@ contract NetworkDebugSubContract {
return x + 3;
}

function traceUniqueEvent() public {
emit UniqueSubDebugEvent();
}

function alwaysRevertsCustomError(uint256 x, uint256 y) public {
revert CustomErr({
available: x,
Expand Down
11 changes: 11 additions & 0 deletions seth/contracts/TestContractOne.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "./AbstractContractWithEvent.sol";

contract unique_event_two is AbstractContractWithEvent {
function executeFirstOperation(int256 x, int256 y) public returns (int256) {
emit NonUniqueEvent(x, y);
return x + y;
}
}
11 changes: 11 additions & 0 deletions seth/contracts/TestContractTwo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "./AbstractContractWithEvent.sol";

contract TestContractTwo is AbstractContractWithEvent {
function executeSecondOperation(int256 x, int256 y) public returns (int256) {
emit NonUniqueEvent(x, y);
return x + y;
}
}
1 change: 1 addition & 0 deletions seth/contracts/abi/AbstractContractWithEvent.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"int256","name":"a","type":"int256"},{"indexed":true,"internalType":"int256","name":"b","type":"int256"}],"name":"NonUniqueEvent","type":"event"}]
Loading

0 comments on commit 7437e46

Please sign in to comment.