From f023c913b99527ab9502b426aecc48d7668ed11e Mon Sep 17 00:00:00 2001 From: tcar Date: Thu, 5 Oct 2023 13:09:56 +0200 Subject: [PATCH 1/5] refactor deposit handlers; Signed-off-by: tcar --- Makefile | 1 + chains/evm/deposithandlers/deposit-handler.go | 66 ++++++ chains/evm/deposithandlers/erc20.go | 62 ++++++ chains/evm/deposithandlers/erc20_test.go | 156 ++++++++++++++ chains/evm/deposithandlers/erc721.go | 67 ++++++ chains/evm/deposithandlers/erc721_test.go | 197 ++++++++++++++++++ chains/evm/deposithandlers/generic.go | 35 ++++ chains/evm/deposithandlers/generic_test.go | 151 ++++++++++++++ chains/evm/eventhandlers/event-handler.go | 90 ++++++++ .../evm/eventhandlers/event-handler_test.go | 184 ++++++++++++++++ .../evm/eventhandlers/mock/eventhandlers.go | 91 ++++++++ go.mod | 1 + go.sum | 2 + 13 files changed, 1103 insertions(+) create mode 100644 chains/evm/deposithandlers/deposit-handler.go create mode 100644 chains/evm/deposithandlers/erc20.go create mode 100644 chains/evm/deposithandlers/erc20_test.go create mode 100644 chains/evm/deposithandlers/erc721.go create mode 100644 chains/evm/deposithandlers/erc721_test.go create mode 100644 chains/evm/deposithandlers/generic.go create mode 100644 chains/evm/deposithandlers/generic_test.go create mode 100644 chains/evm/eventhandlers/event-handler.go create mode 100644 chains/evm/eventhandlers/event-handler_test.go create mode 100644 chains/evm/eventhandlers/mock/eventhandlers.go diff --git a/Makefile b/Makefile index 126841ab..b7d060b7 100644 --- a/Makefile +++ b/Makefile @@ -39,3 +39,4 @@ genmocks: mockgen -source=chains/evm/transactor/transact.go -destination=./mock/transact.go -package mock mockgen -source=chains/evm/transactor/signAndSend/signAndSend.go -destination=./mock/signAndSend.go -package mock mockgen -source=./store/store.go -destination=./mock/store.go -package mock + mockgen -destination=chains/evm/eventhandlers/mock/eventhandlers.go -source=./chains/evm/eventhandlers/event-handler.go -package mock diff --git a/chains/evm/deposithandlers/deposit-handler.go b/chains/evm/deposithandlers/deposit-handler.go new file mode 100644 index 00000000..8e760032 --- /dev/null +++ b/chains/evm/deposithandlers/deposit-handler.go @@ -0,0 +1,66 @@ +package deposithandlers + +import ( + "errors" + + "github.com/ChainSafe/sygma-core/chains/evm/eventhandlers" + + "github.com/ChainSafe/sygma-core/types" + "github.com/rs/zerolog/log" + + "github.com/ethereum/go-ethereum/common" +) + +type arbitraryFunction func(Config interface{}) error +type DepositHandlers map[common.Address]eventhandlers.DepositHandler +type DepositHandlerFunc func(sourceID, destID uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*types.Message, error) +type HandlerMatcher interface { + GetHandlerAddressForResourceID(resourceID types.ResourceID) (common.Address, error) +} + +type ETHDepositHandler struct { + handlerMatcher HandlerMatcher + depositHandlers DepositHandlers +} + +// NewETHDepositHandler creates an instance of ETHDepositHandler that contains +// handler functions for processing deposit events +func NewETHDepositHandler(handlerMatcher HandlerMatcher) *ETHDepositHandler { + return ÐDepositHandler{ + handlerMatcher: handlerMatcher, + depositHandlers: make(map[common.Address]eventhandlers.DepositHandler), + } +} + +func (e *ETHDepositHandler) HandleDeposit(sourceID, destID uint8, depositNonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*types.Message, error) { + handlerAddr, err := e.handlerMatcher.GetHandlerAddressForResourceID(resourceID) + if err != nil { + return nil, err + } + + depositHandler, err := e.matchAddressWithHandlerFunc(handlerAddr) + if err != nil { + return nil, err + } + + return depositHandler(sourceID, destID, depositNonce, resourceID, calldata, handlerResponse) +} + +// matchAddressWithHandlerFunc matches a handler address with an associated handler function +func (e *ETHDepositHandler) matchAddressWithHandlerFunc(handlerAddress common.Address) (DepositHandlerFunc, error) { + hf, ok := e.depositHandlers[handlerAddress] + if !ok { + return nil, errors.New("no corresponding deposit handler for this address exists") + } + return hf.HandleDeposit, nil +} + +// RegisterDepositHandler registers an event handler by associating a handler function to a specified address +func (e *ETHDepositHandler) RegisterDepositHandler(handlerAddress string, handler eventhandlers.DepositHandler) { + if handlerAddress == "" { + return + } + + log.Debug().Msgf("Registered deposit handler for address %s", handlerAddress) + e.depositHandlers[common.HexToAddress(handlerAddress)] = handler +} diff --git a/chains/evm/deposithandlers/erc20.go b/chains/evm/deposithandlers/erc20.go new file mode 100644 index 00000000..be04cb55 --- /dev/null +++ b/chains/evm/deposithandlers/erc20.go @@ -0,0 +1,62 @@ +package deposithandlers + +import ( + "errors" + "math/big" + + "github.com/ChainSafe/sygma-core/types" +) + +type Erc20DepositHandler struct { + ArbitraryFunction arbitraryFunction + Config interface{} +} + +// Erc20DepositHandler converts data pulled from event logs into message +// handlerResponse can be an empty slice +func (dh *Erc20DepositHandler) HandleDeposit(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*types.Message, error) { + if len(calldata) < 84 { + err := errors.New("invalid calldata length: less than 84 bytes") + return nil, err + } + + err := dh.ArbitraryFunction(dh.Config) + if err != nil { + return nil, err + } + + // @dev + // amount: first 32 bytes of calldata + amount := calldata[:32] + + // lenRecipientAddress: second 32 bytes of calldata [32:64] + // does not need to be derived because it is being calculated + // within ERC20MessageHandler + // https://github.com/ChainSafe/chainbridge-core/blob/main/chains/evm/voter/message-handler.go#L108 + + // 32-64 is recipient address length + recipientAddressLength := big.NewInt(0).SetBytes(calldata[32:64]) + + // 64 - (64 + recipient address length) is recipient address + recipientAddress := calldata[64:(64 + recipientAddressLength.Int64())] + + // if there is priority data, parse it and use it + payload := []interface{}{ + amount, + recipientAddress, + } + + // arbitrary metadata that will be most likely be used by the relayer + var metadata types.Metadata + if 64+recipientAddressLength.Int64() < int64(len(calldata)) { + priorityLength := big.NewInt(0).SetBytes(calldata[(64 + recipientAddressLength.Int64()):((64 + recipientAddressLength.Int64()) + 1)]) + + // (64 + recipient address length + 1) - ((64 + recipient address length + 1) + priority length) is priority data + priority := calldata[(64 + recipientAddressLength.Int64() + 1):((64 + recipientAddressLength.Int64()) + 1 + priorityLength.Int64())] + + // Assign the priority data to the Metadata struct + metadata.Data = make(map[string]interface{}) + metadata.Data["Priority"] = priority[0] + } + return types.NewMessage(sourceID, destId, nonce, resourceID, types.FungibleTransfer, payload, metadata), nil +} diff --git a/chains/evm/deposithandlers/erc20_test.go b/chains/evm/deposithandlers/erc20_test.go new file mode 100644 index 00000000..7ff72ab1 --- /dev/null +++ b/chains/evm/deposithandlers/erc20_test.go @@ -0,0 +1,156 @@ +package deposithandlers_test + +import ( + "errors" + "math/big" + "testing" + + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts/deposit" + "github.com/ChainSafe/sygma-core/chains/evm/deposithandlers" + "github.com/ChainSafe/sygma-core/chains/evm/eventhandlers" + "github.com/ChainSafe/sygma-core/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/stretchr/testify/suite" +) + +var errIncorrectDataLen = errors.New("invalid calldata length: less than 84 bytes") + +type Erc20HandlerTestSuite struct { + suite.Suite +} + +func testFunc(Config interface{}) error { + return nil +} + +type Config struct{} + +func TestRunErc20HandlerTestSuite(t *testing.T) { + suite.Run(t, new(Erc20HandlerTestSuite)) +} + +func (s *Erc20HandlerTestSuite) SetupSuite() {} +func (s *Erc20HandlerTestSuite) TearDownSuite() {} +func (s *Erc20HandlerTestSuite) SetupTest() {} +func (s *Erc20HandlerTestSuite) TearDownTest() {} + +func (s *Erc20HandlerTestSuite) TestErc20HandleEvent() { + // 0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b + recipientByteSlice := []byte{241, 229, 143, 177, 119, 4, 194, 218, 132, 121, 165, 51, 249, 250, 212, 173, 9, 147, 202, 107} + + calldata := deposit.ConstructErc20DepositData(recipientByteSlice, big.NewInt(2)) + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + amountParsed := calldata[:32] + recipientAddressParsed := calldata[64:] + + expected := &types.Message{ + Source: sourceID, + Destination: depositLog.DestinationDomainID, + DepositNonce: depositLog.DepositNonce, + ResourceId: depositLog.ResourceID, + Type: types.FungibleTransfer, + Payload: []interface{}{ + amountParsed, + recipientAddressParsed, + }, + } + conf := &Config{} + erc20DepositHandler := deposithandlers.Erc20DepositHandler{ + ArbitraryFunction: testFunc, + Config: conf, + } + message, err := erc20DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.Nil(err) + s.NotNil(message) + s.Equal(message, expected) +} + +func (s *Erc20HandlerTestSuite) TestErc20HandleEventWithPriority() { + // 0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b + recipientByteSlice := []byte{241, 229, 143, 177, 119, 4, 194, 218, 132, 121, 165, 51, 249, 250, 212, 173, 9, 147, 202, 107} + + calldata := deposit.ConstructErc20DepositDataWithPriority(recipientByteSlice, big.NewInt(2), uint8(1)) + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + amountParsed := calldata[:32] + // 32-64 is recipient address length + recipientAddressLength := big.NewInt(0).SetBytes(calldata[32:64]) + + // 64 - (64 + recipient address length) is recipient address + recipientAddressParsed := calldata[64:(64 + recipientAddressLength.Int64())] + expected := &types.Message{ + Source: sourceID, + Destination: depositLog.DestinationDomainID, + DepositNonce: depositLog.DepositNonce, + ResourceId: depositLog.ResourceID, + Type: types.FungibleTransfer, + Payload: []interface{}{ + amountParsed, + recipientAddressParsed, + }, + Metadata: types.Metadata{ + Data: map[string]interface{}{ + "Priority": uint8(1), + }, + }, + } + + conf := &Config{} + erc20DepositHandler := deposithandlers.Erc20DepositHandler{ + ArbitraryFunction: testFunc, + Config: conf, + } + message, err := erc20DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.Nil(err) + s.NotNil(message) + s.Equal(message, expected) +} + +func (s *Erc20HandlerTestSuite) TestErc20HandleEventIncorrectDataLen() { + metadata := []byte("0xdeadbeef") + + var calldata []byte + calldata = append(calldata, math.PaddedBigBytes(big.NewInt(int64(len(metadata))), 32)...) + calldata = append(calldata, metadata...) + + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + conf := &Config{} + + erc20DepositHandler := deposithandlers.Erc20DepositHandler{ + ArbitraryFunction: testFunc, + Config: conf, + } + message, err := erc20DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.Nil(message) + s.EqualError(err, errIncorrectDataLen.Error()) +} diff --git a/chains/evm/deposithandlers/erc721.go b/chains/evm/deposithandlers/erc721.go new file mode 100644 index 00000000..c355e80c --- /dev/null +++ b/chains/evm/deposithandlers/erc721.go @@ -0,0 +1,67 @@ +package deposithandlers + +import ( + "errors" + "math/big" + + "github.com/ChainSafe/sygma-core/types" +) + +type Erc721DepositHandler struct { + ArbitraryFunction arbitraryFunction + Config interface{} +} + +// Erc721DepositHandler converts data pulled from ERC721 deposit event logs into message +func (dh *Erc721DepositHandler) HandleDeposit(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*types.Message, error) { + if len(calldata) < 64 { + err := errors.New("invalid calldata length: less than 84 bytes") + return nil, err + } + + err := dh.ArbitraryFunction(dh.Config) + if err != nil { + return nil, err + } + + // first 32 bytes are tokenId + tokenId := calldata[:32] + + // 32 - 64 is recipient address length + recipientAddressLength := big.NewInt(0).SetBytes(calldata[32:64]) + + // 64 - (64 + recipient address length) is recipient address + recipientAddress := calldata[64:(64 + recipientAddressLength.Int64())] + + // (64 + recipient address length) - ((64 + recipient address length) + 32) is metadata length + metadataLength := big.NewInt(0).SetBytes( + calldata[(64 + recipientAddressLength.Int64()):((64 + recipientAddressLength.Int64()) + 32)], + ) + // ((64 + recipient address length) + 32) - ((64 + recipient address length) + 32 + metadata length) is metadata + var metadata []byte + var metadataStart int64 + if metadataLength.Cmp(big.NewInt(0)) == 1 { + metadataStart = (64 + recipientAddressLength.Int64()) + 32 + metadata = calldata[metadataStart : metadataStart+metadataLength.Int64()] + } + // arbitrary metadata that will be most likely be used by the relayer + var meta types.Metadata + + payload := []interface{}{ + tokenId, + recipientAddress, + metadata, + } + + if 64+recipientAddressLength.Int64()+32+metadataLength.Int64() < int64(len(calldata)) { + // (metadataStart + metadataLength) - (metadataStart + metadataLength + 1) is priority length + priorityLength := big.NewInt(0).SetBytes(calldata[(64 + recipientAddressLength.Int64() + 32 + metadataLength.Int64()):(64 + recipientAddressLength.Int64() + 32 + metadataLength.Int64() + 1)]) + // (metadataStart + metadataLength + 1) - (metadataStart + metadataLength + 1) + priority length) is priority data + priority := calldata[(64 + recipientAddressLength.Int64() + 32 + metadataLength.Int64() + 1):(64 + recipientAddressLength.Int64() + 32 + metadataLength.Int64() + 1 + priorityLength.Int64())] + + // Assign the priority data to the Metadata struct + meta.Data = make(map[string]interface{}) + meta.Data["Priority"] = priority[0] + } + return types.NewMessage(sourceID, destId, nonce, resourceID, types.NonFungibleTransfer, payload, meta), nil +} diff --git a/chains/evm/deposithandlers/erc721_test.go b/chains/evm/deposithandlers/erc721_test.go new file mode 100644 index 00000000..5ff692f4 --- /dev/null +++ b/chains/evm/deposithandlers/erc721_test.go @@ -0,0 +1,197 @@ +package deposithandlers_test + +import ( + "math/big" + "testing" + + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts/deposit" + "github.com/ChainSafe/sygma-core/chains/evm/deposithandlers" + "github.com/ChainSafe/sygma-core/chains/evm/eventhandlers" + "github.com/ChainSafe/sygma-core/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/stretchr/testify/suite" +) + +type Erc721HandlerTestSuite struct { + suite.Suite +} + +func TestRunErc721HandlerTestSuite(t *testing.T) { + suite.Run(t, new(Erc721HandlerTestSuite)) +} + +func (s *Erc721HandlerTestSuite) SetupSuite() {} +func (s *Erc721HandlerTestSuite) TearDownSuite() {} +func (s *Erc721HandlerTestSuite) SetupTest() {} +func (s *Erc721HandlerTestSuite) TearDownTest() {} + +func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerEmptyMetadata() { + recipient := common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b") + + calldata := deposit.ConstructErc721DepositData(recipient.Bytes(), big.NewInt(2), []byte{}) + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + tokenId := calldata[:32] + recipientAddressParsed := calldata[64:84] + var metadata []byte + + expected := &types.Message{ + Source: sourceID, + Destination: depositLog.DestinationDomainID, + DepositNonce: depositLog.DepositNonce, + ResourceId: depositLog.ResourceID, + Type: types.NonFungibleTransfer, + Payload: []interface{}{ + tokenId, + recipientAddressParsed, + metadata, + }, + } + conf := &Config{} + + erc721DepositHandler := deposithandlers.Erc721DepositHandler{ + ArbitraryFunction: testFunc, + Config: conf, + } + m, err := erc721DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.Nil(err) + s.NotNil(m) + s.Equal(expected, m) +} + +func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerIncorrectDataLen() { + metadata := []byte("0xdeadbeef") + + var calldata []byte + calldata = append(calldata, math.PaddedBigBytes(big.NewInt(int64(len(metadata))), 16)...) + calldata = append(calldata, metadata...) + + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + conf := &Config{} + + erc721DepositHandler := deposithandlers.Erc721DepositHandler{ + ArbitraryFunction: testFunc, + Config: conf, + } + m, err := erc721DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + s.Nil(m) + s.EqualError(err, "invalid calldata length: less than 84 bytes") +} + +func (s *Erc721HandlerTestSuite) TestErc721DepositHandler() { + recipient := common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b") + metadata := []byte("metadata.url") + + calldata := deposit.ConstructErc721DepositData(recipient.Bytes(), big.NewInt(2), metadata) + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + tokenId := calldata[:32] + recipientAddressParsed := calldata[64:84] + parsedMetadata := calldata[116:128] + + expected := &types.Message{ + Source: sourceID, + Destination: depositLog.DestinationDomainID, + DepositNonce: depositLog.DepositNonce, + ResourceId: depositLog.ResourceID, + Type: types.NonFungibleTransfer, + Payload: []interface{}{ + tokenId, + recipientAddressParsed, + parsedMetadata, + }, + } + conf := &Config{} + + erc721DepositHandler := deposithandlers.Erc721DepositHandler{ + ArbitraryFunction: testFunc, + Config: conf, + } + m, err := erc721DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + s.Nil(err) + s.NotNil(m) + s.Equal(expected, m) +} +func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerWithPriority() { + recipient := common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b") + metadata := []byte("metadata.url") + + calldata := deposit.ConstructErc721DepositDataWithPriority(recipient.Bytes(), big.NewInt(2), metadata, uint8(1)) + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + tokenId := calldata[:32] + + // 32 - 64 is recipient address length + recipientAddressLength := big.NewInt(0).SetBytes(calldata[32:64]) + + // 64 - (64 + recipient address length) is recipient address + recipientAddressParsed := calldata[64:(64 + recipientAddressLength.Int64())] + + // (64 + recipient address length) - ((64 + recipient address length) + 32) is metadata length + metadataLength := big.NewInt(0).SetBytes( + calldata[(64 + recipientAddressLength.Int64()):((64 + recipientAddressLength.Int64()) + 32)], + ) + + metadataStart := (64 + recipientAddressLength.Int64()) + 32 + parsedMetadata := calldata[metadataStart : metadataStart+metadataLength.Int64()] + + expected := &types.Message{ + Source: sourceID, + Destination: depositLog.DestinationDomainID, + DepositNonce: depositLog.DepositNonce, + ResourceId: depositLog.ResourceID, + Type: types.NonFungibleTransfer, + Payload: []interface{}{ + tokenId, + recipientAddressParsed, + parsedMetadata, + }, + Metadata: types.Metadata{ + Data: map[string]interface{}{ + "Priority": uint8(1), + }, + }, + } + conf := &Config{} + + erc721DepositHandler := deposithandlers.Erc721DepositHandler{ + ArbitraryFunction: testFunc, + Config: conf, + } + m, err := erc721DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + s.Nil(err) + s.NotNil(m) + s.Equal(expected, m) +} diff --git a/chains/evm/deposithandlers/generic.go b/chains/evm/deposithandlers/generic.go new file mode 100644 index 00000000..b19bbdff --- /dev/null +++ b/chains/evm/deposithandlers/generic.go @@ -0,0 +1,35 @@ +package deposithandlers + +import ( + "errors" + "math/big" + + "github.com/ChainSafe/sygma-core/types" +) + +type GenericDepositHandler struct { + ArbitraryFunction arbitraryFunction + Config interface{} +} + +// GenericDepositHandler converts data pulled from generic deposit event logs into message +func (dh *GenericDepositHandler) HandleDeposit(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*types.Message, error) { + if len(calldata) < 32 { + err := errors.New("invalid calldata length: less than 32 bytes") + return nil, err + } + err := dh.ArbitraryFunction(dh.Config) + if err != nil { + return nil, err + } + // first 32 bytes are metadata length + metadataLen := big.NewInt(0).SetBytes(calldata[:32]) + metadata := calldata[32 : 32+metadataLen.Int64()] + payload := []interface{}{ + metadata, + } + + // generic handler has specific payload length and doesn't support arbitrary metadata + meta := types.Metadata{} + return types.NewMessage(sourceID, destId, nonce, resourceID, types.GenericTransfer, payload, meta), nil +} diff --git a/chains/evm/deposithandlers/generic_test.go b/chains/evm/deposithandlers/generic_test.go new file mode 100644 index 00000000..35ea1ffb --- /dev/null +++ b/chains/evm/deposithandlers/generic_test.go @@ -0,0 +1,151 @@ +package deposithandlers_test + +import ( + "math/big" + "testing" + + "github.com/ChainSafe/chainbridge-core/chains/evm/calls/contracts/deposit" + "github.com/ChainSafe/sygma-core/chains/evm/deposithandlers" + "github.com/ChainSafe/sygma-core/chains/evm/eventhandlers" + "github.com/ChainSafe/sygma-core/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/stretchr/testify/suite" +) + +type GenericHandlerTestSuite struct { + suite.Suite +} + +func TestRunGenericHandlerTestSuite(t *testing.T) { + suite.Run(t, new(GenericHandlerTestSuite)) +} + +func (s *GenericHandlerTestSuite) SetupSuite() {} +func (s *GenericHandlerTestSuite) TearDownSuite() {} +func (s *GenericHandlerTestSuite) SetupTest() {} +func (s *GenericHandlerTestSuite) TearDownTest() {} + +func (s *GenericHandlerTestSuite) TestGenericHandleEventIncorrectDataLen() { + metadata := []byte("0xdeadbeef") + + var calldata []byte + calldata = append(calldata, math.PaddedBigBytes(big.NewInt(int64(len(metadata))), 16)...) + calldata = append(calldata, metadata...) + + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + conf := &Config{} + + genericDepositHandler := deposithandlers.GenericDepositHandler{ + ArbitraryFunction: testFunc, + Config: conf, + } + message, err := genericDepositHandler.HandleDeposit( + sourceID, + depositLog.DestinationDomainID, + depositLog.DepositNonce, + depositLog.ResourceID, + depositLog.Data, + depositLog.HandlerResponse, + ) + + s.Nil(message) + s.EqualError(err, "invalid calldata length: less than 32 bytes") +} + +func (s *GenericHandlerTestSuite) TestGenericHandleEventEmptyMetadata() { + metadata := []byte("") + calldata := deposit.ConstructGenericDepositData(metadata) + + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + expected := &types.Message{ + Source: sourceID, + Destination: depositLog.DestinationDomainID, + DepositNonce: depositLog.DepositNonce, + ResourceId: depositLog.ResourceID, + Type: types.GenericTransfer, + Payload: []interface{}{ + metadata, + }, + } + conf := &Config{} + + genericDepositHandler := deposithandlers.GenericDepositHandler{ + ArbitraryFunction: testFunc, + Config: conf, + } + message, err := genericDepositHandler.HandleDeposit( + sourceID, + depositLog.DestinationDomainID, + depositLog.DepositNonce, + depositLog.ResourceID, + depositLog.Data, + depositLog.HandlerResponse, + ) + + s.Nil(err) + s.NotNil(message) + s.Equal(message, expected) +} + +func (s *GenericHandlerTestSuite) TestGenericHandleEvent() { + metadata := []byte("0xdeadbeef") + calldata := deposit.ConstructGenericDepositData(metadata) + + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + expected := &types.Message{ + Source: sourceID, + Destination: depositLog.DestinationDomainID, + DepositNonce: depositLog.DepositNonce, + ResourceId: depositLog.ResourceID, + Type: types.GenericTransfer, + Payload: []interface{}{ + metadata, + }, + } + + conf := &Config{} + genericDepositHandler := deposithandlers.GenericDepositHandler{ + ArbitraryFunction: testFunc, + Config: conf, + } + message, err := genericDepositHandler.HandleDeposit( + sourceID, + depositLog.DestinationDomainID, + depositLog.DepositNonce, + depositLog.ResourceID, + depositLog.Data, + depositLog.HandlerResponse, + ) + + s.Nil(err) + s.NotNil(message) + s.Equal(message, expected) +} diff --git a/chains/evm/eventhandlers/event-handler.go b/chains/evm/eventhandlers/event-handler.go new file mode 100644 index 00000000..5e3e0dca --- /dev/null +++ b/chains/evm/eventhandlers/event-handler.go @@ -0,0 +1,90 @@ +package eventhandlers + +import ( + "context" + "fmt" + "math/big" + + "github.com/ChainSafe/sygma-core/types" + "github.com/ethereum/go-ethereum/common" + "github.com/rs/zerolog/log" +) + +// Deposit struct holds event data with all necessary parameters and a handler response +// https://github.com/ChainSafe/chainbridge-solidity/blob/develop/contracts/Bridge.sol#L47 +type Deposit struct { + // ID of chain deposit will be bridged to + DestinationDomainID uint8 + // ResourceID used to find address of handler to be used for deposit + ResourceID types.ResourceID + // Nonce of deposit + DepositNonce uint64 + // Address of sender (msg.sender: user) + SenderAddress common.Address + // Additional data to be passed to specified handler + Data []byte + // ERC20Handler: responds with empty data + // ERC721Handler: responds with deposited token metadata acquired by calling a tokenURI method in the token contract + // GenericHandler: responds with the raw bytes returned from the call to the target contract + HandlerResponse []byte +} + +type EventListener interface { + FetchDeposits(ctx context.Context, address common.Address, startBlock *big.Int, endBlock *big.Int) ([]*Deposit, error) +} + +type DepositHandler interface { + HandleDeposit(sourceID, destID uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*types.Message, error) +} + +type DepositEventHandler struct { + eventListener EventListener + depositHandler DepositHandler + + bridgeAddress common.Address + domainID uint8 +} + +func NewDepositEventHandler(eventListener EventListener, depositHandler DepositHandler, bridgeAddress common.Address, domainID uint8) *DepositEventHandler { + return &DepositEventHandler{ + eventListener: eventListener, + depositHandler: depositHandler, + bridgeAddress: bridgeAddress, + domainID: domainID, + } +} + +func (eh *DepositEventHandler) HandleEvent(startBlock *big.Int, endBlock *big.Int, msgChan chan []*types.Message) error { + deposits, err := eh.eventListener.FetchDeposits(context.Background(), eh.bridgeAddress, startBlock, endBlock) + if err != nil { + return fmt.Errorf("unable to fetch deposit events because of: %+v", err) + } + + domainDeposits := make(map[uint8][]*types.Message) + for _, d := range deposits { + func(d *Deposit) { + defer func() { + if r := recover(); r != nil { + log.Error().Err(err).Msgf("panic occured while handling deposit %+v", d) + } + }() + + m, err := eh.depositHandler.HandleDeposit(eh.domainID, d.DestinationDomainID, d.DepositNonce, d.ResourceID, d.Data, d.HandlerResponse) + if err != nil { + log.Error().Err(err).Str("start block", startBlock.String()).Str("end block", endBlock.String()).Uint8("domainID", eh.domainID).Msgf("%v", err) + return + } + + log.Debug().Msgf("Resolved message %+v in block range: %s-%s", m, startBlock.String(), endBlock.String()) + domainDeposits[m.Destination] = append(domainDeposits[m.Destination], m) + }(d) + } + + for _, deposits := range domainDeposits { + go func(d []*types.Message) { + msgChan <- d + }(deposits) + } + + return nil +} diff --git a/chains/evm/eventhandlers/event-handler_test.go b/chains/evm/eventhandlers/event-handler_test.go new file mode 100644 index 00000000..60023c6f --- /dev/null +++ b/chains/evm/eventhandlers/event-handler_test.go @@ -0,0 +1,184 @@ +package eventhandlers_test + +import ( + "fmt" + "math/big" + "testing" + + "github.com/ChainSafe/sygma-core/chains/evm/eventhandlers" + mock_listener "github.com/ChainSafe/sygma-core/chains/evm/eventhandlers/mock" + "github.com/ChainSafe/sygma-core/types" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/suite" + "go.uber.org/mock/gomock" +) + +type DepositHandlerTestSuite struct { + suite.Suite + depositEventHandler *eventhandlers.DepositEventHandler + mockDepositHandler *mock_listener.MockDepositHandler + mockEventListener *mock_listener.MockEventListener + domainID uint8 +} + +func TestRunDepositHandlerTestSuite(t *testing.T) { + suite.Run(t, new(DepositHandlerTestSuite)) +} + +func (s *DepositHandlerTestSuite) SetupTest() { + ctrl := gomock.NewController(s.T()) + s.domainID = 1 + s.mockEventListener = mock_listener.NewMockEventListener(ctrl) + s.mockDepositHandler = mock_listener.NewMockDepositHandler(ctrl) + s.depositEventHandler = eventhandlers.NewDepositEventHandler(s.mockEventListener, s.mockDepositHandler, common.Address{}, s.domainID) +} + +func (s *DepositHandlerTestSuite) Test_FetchDepositFails() { + s.mockEventListener.EXPECT().FetchDeposits(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]*eventhandlers.Deposit{}, fmt.Errorf("error")) + + msgChan := make(chan []*types.Message, 1) + err := s.depositEventHandler.HandleEvent(big.NewInt(0), big.NewInt(5), msgChan) + + s.NotNil(err) + s.Equal(len(msgChan), 0) +} + +func (s *DepositHandlerTestSuite) Test_HandleDepositFails_ExecutionContinue() { + d1 := &eventhandlers.Deposit{ + DepositNonce: 1, + DestinationDomainID: 2, + ResourceID: types.ResourceID{}, + HandlerResponse: []byte{}, + Data: []byte{}, + } + d2 := &eventhandlers.Deposit{ + DepositNonce: 2, + DestinationDomainID: 2, + ResourceID: types.ResourceID{}, + HandlerResponse: []byte{}, + Data: []byte{}, + } + deposits := []*eventhandlers.Deposit{d1, d2} + s.mockEventListener.EXPECT().FetchDeposits(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(deposits, nil) + s.mockDepositHandler.EXPECT().HandleDeposit( + s.domainID, + d1.DestinationDomainID, + d1.DepositNonce, + d1.ResourceID, + d1.Data, + d1.HandlerResponse, + ).Return(&types.Message{}, fmt.Errorf("error")) + s.mockDepositHandler.EXPECT().HandleDeposit( + s.domainID, + d2.DestinationDomainID, + d2.DepositNonce, + d2.ResourceID, + d2.Data, + d2.HandlerResponse, + ).Return( + &types.Message{DepositNonce: 2}, + nil, + ) + + msgChan := make(chan []*types.Message, 2) + err := s.depositEventHandler.HandleEvent(big.NewInt(0), big.NewInt(5), msgChan) + msgs := <-msgChan + + s.Nil(err) + s.Equal(msgs, []*types.Message{{DepositNonce: 2}}) +} + +func (s *DepositHandlerTestSuite) Test_HandleDepositPanis_ExecutionContinues() { + d1 := &eventhandlers.Deposit{ + DepositNonce: 1, + DestinationDomainID: 2, + ResourceID: types.ResourceID{}, + HandlerResponse: []byte{}, + Data: []byte{}, + } + d2 := &eventhandlers.Deposit{ + DepositNonce: 2, + DestinationDomainID: 2, + ResourceID: types.ResourceID{}, + HandlerResponse: []byte{}, + Data: []byte{}, + } + deposits := []*eventhandlers.Deposit{d1, d2} + s.mockEventListener.EXPECT().FetchDeposits(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(deposits, nil) + s.mockDepositHandler.EXPECT().HandleDeposit( + s.domainID, + d1.DestinationDomainID, + d1.DepositNonce, + d1.ResourceID, + d1.Data, + d1.HandlerResponse, + ).Do(func(sourceID, destID, nonce, resourceID, calldata, handlerResponse interface{}) { + panic("error") + }) + s.mockDepositHandler.EXPECT().HandleDeposit( + s.domainID, + d2.DestinationDomainID, + d2.DepositNonce, + d2.ResourceID, + d2.Data, + d2.HandlerResponse, + ).Return( + &types.Message{DepositNonce: 2}, + nil, + ) + + msgChan := make(chan []*types.Message, 2) + err := s.depositEventHandler.HandleEvent(big.NewInt(0), big.NewInt(5), msgChan) + msgs := <-msgChan + + s.Nil(err) + s.Equal(msgs, []*types.Message{{DepositNonce: 2}}) +} + +func (s *DepositHandlerTestSuite) Test_SuccessfulHandleDeposit() { + d1 := &eventhandlers.Deposit{ + DepositNonce: 1, + DestinationDomainID: 2, + ResourceID: types.ResourceID{}, + HandlerResponse: []byte{}, + Data: []byte{}, + } + d2 := &eventhandlers.Deposit{ + DepositNonce: 2, + DestinationDomainID: 2, + ResourceID: types.ResourceID{}, + HandlerResponse: []byte{}, + Data: []byte{}, + } + deposits := []*eventhandlers.Deposit{d1, d2} + s.mockEventListener.EXPECT().FetchDeposits(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(deposits, nil) + s.mockDepositHandler.EXPECT().HandleDeposit( + s.domainID, + d1.DestinationDomainID, + d1.DepositNonce, + d1.ResourceID, + d1.Data, + d1.HandlerResponse, + ).Return( + &types.Message{DepositNonce: 1}, + nil, + ) + s.mockDepositHandler.EXPECT().HandleDeposit( + s.domainID, + d2.DestinationDomainID, + d2.DepositNonce, + d2.ResourceID, + d2.Data, + d2.HandlerResponse, + ).Return( + &types.Message{DepositNonce: 2}, + nil, + ) + + msgChan := make(chan []*types.Message, 2) + err := s.depositEventHandler.HandleEvent(big.NewInt(0), big.NewInt(5), msgChan) + msgs := <-msgChan + + s.Nil(err) + s.Equal(msgs, []*types.Message{{DepositNonce: 1}, {DepositNonce: 2}}) +} diff --git a/chains/evm/eventhandlers/mock/eventhandlers.go b/chains/evm/eventhandlers/mock/eventhandlers.go new file mode 100644 index 00000000..a1355629 --- /dev/null +++ b/chains/evm/eventhandlers/mock/eventhandlers.go @@ -0,0 +1,91 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./chains/evm/eventhandlers/event-handler.go + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + big "math/big" + reflect "reflect" + + eventhandlers "github.com/ChainSafe/sygma-core/chains/evm/eventhandlers" + types "github.com/ChainSafe/sygma-core/types" + common "github.com/ethereum/go-ethereum/common" + gomock "go.uber.org/mock/gomock") + +// MockEventListener is a mock of EventListener interface. +type MockEventListener struct { + ctrl *gomock.Controller + recorder *MockEventListenerMockRecorder +} + +// MockEventListenerMockRecorder is the mock recorder for MockEventListener. +type MockEventListenerMockRecorder struct { + mock *MockEventListener +} + +// NewMockEventListener creates a new mock instance. +func NewMockEventListener(ctrl *gomock.Controller) *MockEventListener { + mock := &MockEventListener{ctrl: ctrl} + mock.recorder = &MockEventListenerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockEventListener) EXPECT() *MockEventListenerMockRecorder { + return m.recorder +} + +// FetchDeposits mocks base method. +func (m *MockEventListener) FetchDeposits(ctx context.Context, address common.Address, startBlock, endBlock *big.Int) ([]*eventhandlers.Deposit, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FetchDeposits", ctx, address, startBlock, endBlock) + ret0, _ := ret[0].([]*eventhandlers.Deposit) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FetchDeposits indicates an expected call of FetchDeposits. +func (mr *MockEventListenerMockRecorder) FetchDeposits(ctx, address, startBlock, endBlock interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchDeposits", reflect.TypeOf((*MockEventListener)(nil).FetchDeposits), ctx, address, startBlock, endBlock) +} + +// MockDepositHandler is a mock of DepositHandler interface. +type MockDepositHandler struct { + ctrl *gomock.Controller + recorder *MockDepositHandlerMockRecorder +} + +// MockDepositHandlerMockRecorder is the mock recorder for MockDepositHandler. +type MockDepositHandlerMockRecorder struct { + mock *MockDepositHandler +} + +// NewMockDepositHandler creates a new mock instance. +func NewMockDepositHandler(ctrl *gomock.Controller) *MockDepositHandler { + mock := &MockDepositHandler{ctrl: ctrl} + mock.recorder = &MockDepositHandlerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockDepositHandler) EXPECT() *MockDepositHandlerMockRecorder { + return m.recorder +} + +// HandleDeposit mocks base method. +func (m *MockDepositHandler) HandleDeposit(sourceID, destID uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*types.Message, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HandleDeposit", sourceID, destID, nonce, resourceID, calldata, handlerResponse) + ret0, _ := ret[0].(*types.Message) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HandleDeposit indicates an expected call of HandleDeposit. +func (mr *MockDepositHandlerMockRecorder) HandleDeposit(sourceID, destID, nonce, resourceID, calldata, handlerResponse interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleDeposit", reflect.TypeOf((*MockDepositHandler)(nil).HandleDeposit), sourceID, destID, nonce, resourceID, calldata, handlerResponse) +} diff --git a/go.mod b/go.mod index bbe681c1..a4e800df 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( ) require ( + github.com/ChainSafe/chainbridge-core v1.4.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect diff --git a/go.sum b/go.sum index 80dd71d9..a5c8cab3 100644 --- a/go.sum +++ b/go.sum @@ -50,6 +50,8 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ChainSafe/chainbridge-core v1.4.1 h1:ks2ViOlduDq4p4z01BS6pnrPYR5IYPP8Fwfo5YP8MxY= +github.com/ChainSafe/chainbridge-core v1.4.1/go.mod h1:4WieCRk3wbrtiRZPTpYjXlOTbZLiRTptWiTEsO+yhnc= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= From 72348150d0ca9589c381f4e10c79f74a68a619f2 Mon Sep 17 00:00:00 2001 From: tcar Date: Thu, 5 Oct 2023 13:17:53 +0200 Subject: [PATCH 2/5] add test for arbitraryFunction error; Signed-off-by: tcar --- chains/evm/deposithandlers/erc20_test.go | 30 ++++++++++++++++++++ chains/evm/deposithandlers/erc721_test.go | 24 ++++++++++++++++ chains/evm/deposithandlers/generic_test.go | 32 ++++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/chains/evm/deposithandlers/erc20_test.go b/chains/evm/deposithandlers/erc20_test.go index 7ff72ab1..bcb529de 100644 --- a/chains/evm/deposithandlers/erc20_test.go +++ b/chains/evm/deposithandlers/erc20_test.go @@ -24,6 +24,10 @@ func testFunc(Config interface{}) error { return nil } +func testErrFunc(Config interface{}) error { + return errors.New("Error") +} + type Config struct{} func TestRunErc20HandlerTestSuite(t *testing.T) { @@ -76,6 +80,32 @@ func (s *Erc20HandlerTestSuite) TestErc20HandleEvent() { s.Equal(message, expected) } +func (s *Erc20HandlerTestSuite) TestErc20HandleEventArbitraryFunctionError() { + // 0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b + recipientByteSlice := []byte{241, 229, 143, 177, 119, 4, 194, 218, 132, 121, 165, 51, 249, 250, 212, 173, 9, 147, 202, 107} + + calldata := deposit.ConstructErc20DepositData(recipientByteSlice, big.NewInt(2)) + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + + conf := &Config{} + erc20DepositHandler := deposithandlers.Erc20DepositHandler{ + ArbitraryFunction: testErrFunc, + Config: conf, + } + _, err := erc20DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.NotNil(err) +} + func (s *Erc20HandlerTestSuite) TestErc20HandleEventWithPriority() { // 0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b recipientByteSlice := []byte{241, 229, 143, 177, 119, 4, 194, 218, 132, 121, 165, 51, 249, 250, 212, 173, 9, 147, 202, 107} diff --git a/chains/evm/deposithandlers/erc721_test.go b/chains/evm/deposithandlers/erc721_test.go index 5ff692f4..9e225686 100644 --- a/chains/evm/deposithandlers/erc721_test.go +++ b/chains/evm/deposithandlers/erc721_test.go @@ -68,6 +68,30 @@ func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerEmptyMetadata() { s.Equal(expected, m) } +func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerArbitraryFunctionError() { + recipient := common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b") + + calldata := deposit.ConstructErc721DepositData(recipient.Bytes(), big.NewInt(2), []byte{}) + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + conf := &Config{} + + erc721DepositHandler := deposithandlers.Erc721DepositHandler{ + ArbitraryFunction: testErrFunc, + Config: conf, + } + _, err := erc721DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) + + s.NotNil(err) +} + func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerIncorrectDataLen() { metadata := []byte("0xdeadbeef") diff --git a/chains/evm/deposithandlers/generic_test.go b/chains/evm/deposithandlers/generic_test.go index 35ea1ffb..2c4be962 100644 --- a/chains/evm/deposithandlers/generic_test.go +++ b/chains/evm/deposithandlers/generic_test.go @@ -149,3 +149,35 @@ func (s *GenericHandlerTestSuite) TestGenericHandleEvent() { s.NotNil(message) s.Equal(message, expected) } + +func (s *GenericHandlerTestSuite) TestGenericHandleEventArbitraryFunctionError() { + metadata := []byte("0xdeadbeef") + calldata := deposit.ConstructGenericDepositData(metadata) + + depositLog := &eventhandlers.Deposit{ + DestinationDomainID: 0, + ResourceID: [32]byte{0}, + DepositNonce: 1, + SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), + Data: calldata, + HandlerResponse: []byte{}, + } + + sourceID := uint8(1) + + conf := &Config{} + genericDepositHandler := deposithandlers.GenericDepositHandler{ + ArbitraryFunction: testErrFunc, + Config: conf, + } + _, err := genericDepositHandler.HandleDeposit( + sourceID, + depositLog.DestinationDomainID, + depositLog.DepositNonce, + depositLog.ResourceID, + depositLog.Data, + depositLog.HandlerResponse, + ) + + s.NotNil(err) +} From c0ee7716be2b00a189264225bac3b8e7bb365c83 Mon Sep 17 00:00:00 2001 From: tcar Date: Thu, 5 Oct 2023 14:40:18 +0200 Subject: [PATCH 3/5] add deposit types; Signed-off-by: tcar --- types/message.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/types/message.go b/types/message.go index e305f4ed..5df24fbe 100644 --- a/types/message.go +++ b/types/message.go @@ -8,6 +8,13 @@ type Metadata struct { Data map[string]interface{} } type TransferType string + +const ( + FungibleTransfer TransferType = "FungibleTransfer" + NonFungibleTransfer TransferType = "NonFungibleTransfer" + GenericTransfer TransferType = "GenericTransfer" +) + type Message struct { Source uint8 // Source where message was initiated Destination uint8 // Destination chain of message From b64481916e315d36a2cc0a906420e711b1edb104 Mon Sep 17 00:00:00 2001 From: tcar Date: Thu, 5 Oct 2023 15:40:18 +0200 Subject: [PATCH 4/5] update mock; Signed-off-by: tcar --- chains/evm/eventhandlers/mock/eventhandlers.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/chains/evm/eventhandlers/mock/eventhandlers.go b/chains/evm/eventhandlers/mock/eventhandlers.go index a1355629..1a17312c 100644 --- a/chains/evm/eventhandlers/mock/eventhandlers.go +++ b/chains/evm/eventhandlers/mock/eventhandlers.go @@ -1,6 +1,8 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./chains/evm/eventhandlers/event-handler.go - +// +// Generated by this command: +// mockgen -destination=chains/evm/eventhandlers/mock/eventhandlers.go -source=./chains/evm/eventhandlers/event-handler.go -package mock // Package mock is a generated GoMock package. package mock @@ -12,7 +14,8 @@ import ( eventhandlers "github.com/ChainSafe/sygma-core/chains/evm/eventhandlers" types "github.com/ChainSafe/sygma-core/types" common "github.com/ethereum/go-ethereum/common" - gomock "go.uber.org/mock/gomock") + gomock "go.uber.org/mock/gomock" +) // MockEventListener is a mock of EventListener interface. type MockEventListener struct { @@ -47,7 +50,7 @@ func (m *MockEventListener) FetchDeposits(ctx context.Context, address common.Ad } // FetchDeposits indicates an expected call of FetchDeposits. -func (mr *MockEventListenerMockRecorder) FetchDeposits(ctx, address, startBlock, endBlock interface{}) *gomock.Call { +func (mr *MockEventListenerMockRecorder) FetchDeposits(ctx, address, startBlock, endBlock any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchDeposits", reflect.TypeOf((*MockEventListener)(nil).FetchDeposits), ctx, address, startBlock, endBlock) } @@ -85,7 +88,7 @@ func (m *MockDepositHandler) HandleDeposit(sourceID, destID uint8, nonce uint64, } // HandleDeposit indicates an expected call of HandleDeposit. -func (mr *MockDepositHandlerMockRecorder) HandleDeposit(sourceID, destID, nonce, resourceID, calldata, handlerResponse interface{}) *gomock.Call { +func (mr *MockDepositHandlerMockRecorder) HandleDeposit(sourceID, destID, nonce, resourceID, calldata, handlerResponse any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleDeposit", reflect.TypeOf((*MockDepositHandler)(nil).HandleDeposit), sourceID, destID, nonce, resourceID, calldata, handlerResponse) } From db4efce150955596ee53c4952e67eea84b6ff8f9 Mon Sep 17 00:00:00 2001 From: tcar Date: Mon, 9 Oct 2023 09:50:27 +0200 Subject: [PATCH 5/5] remove arbitraryFunction and config from handlers; Signed-off-by: tcar --- chains/evm/deposithandlers/deposit-handler.go | 8 ++- chains/evm/deposithandlers/erc20.go | 10 +--- chains/evm/deposithandlers/erc20_test.go | 54 ++----------------- chains/evm/deposithandlers/erc721.go | 10 +--- chains/evm/deposithandlers/erc721_test.go | 48 ++--------------- chains/evm/deposithandlers/generic.go | 10 +--- chains/evm/deposithandlers/generic_test.go | 50 ++--------------- .../evm/eventhandlers/mock/eventhandlers.go | 4 +- 8 files changed, 20 insertions(+), 174 deletions(-) diff --git a/chains/evm/deposithandlers/deposit-handler.go b/chains/evm/deposithandlers/deposit-handler.go index 8e760032..83d43c6e 100644 --- a/chains/evm/deposithandlers/deposit-handler.go +++ b/chains/evm/deposithandlers/deposit-handler.go @@ -11,9 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" ) -type arbitraryFunction func(Config interface{}) error type DepositHandlers map[common.Address]eventhandlers.DepositHandler -type DepositHandlerFunc func(sourceID, destID uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*types.Message, error) type HandlerMatcher interface { GetHandlerAddressForResourceID(resourceID types.ResourceID) (common.Address, error) } @@ -43,16 +41,16 @@ func (e *ETHDepositHandler) HandleDeposit(sourceID, destID uint8, depositNonce u return nil, err } - return depositHandler(sourceID, destID, depositNonce, resourceID, calldata, handlerResponse) + return depositHandler.HandleDeposit(sourceID, destID, depositNonce, resourceID, calldata, handlerResponse) } // matchAddressWithHandlerFunc matches a handler address with an associated handler function -func (e *ETHDepositHandler) matchAddressWithHandlerFunc(handlerAddress common.Address) (DepositHandlerFunc, error) { +func (e *ETHDepositHandler) matchAddressWithHandlerFunc(handlerAddress common.Address) (eventhandlers.DepositHandler, error) { hf, ok := e.depositHandlers[handlerAddress] if !ok { return nil, errors.New("no corresponding deposit handler for this address exists") } - return hf.HandleDeposit, nil + return hf, nil } // RegisterDepositHandler registers an event handler by associating a handler function to a specified address diff --git a/chains/evm/deposithandlers/erc20.go b/chains/evm/deposithandlers/erc20.go index be04cb55..217bcefd 100644 --- a/chains/evm/deposithandlers/erc20.go +++ b/chains/evm/deposithandlers/erc20.go @@ -7,10 +7,7 @@ import ( "github.com/ChainSafe/sygma-core/types" ) -type Erc20DepositHandler struct { - ArbitraryFunction arbitraryFunction - Config interface{} -} +type Erc20DepositHandler struct{} // Erc20DepositHandler converts data pulled from event logs into message // handlerResponse can be an empty slice @@ -20,11 +17,6 @@ func (dh *Erc20DepositHandler) HandleDeposit(sourceID, destId uint8, nonce uint6 return nil, err } - err := dh.ArbitraryFunction(dh.Config) - if err != nil { - return nil, err - } - // @dev // amount: first 32 bytes of calldata amount := calldata[:32] diff --git a/chains/evm/deposithandlers/erc20_test.go b/chains/evm/deposithandlers/erc20_test.go index bcb529de..e9539a8b 100644 --- a/chains/evm/deposithandlers/erc20_test.go +++ b/chains/evm/deposithandlers/erc20_test.go @@ -20,16 +20,6 @@ type Erc20HandlerTestSuite struct { suite.Suite } -func testFunc(Config interface{}) error { - return nil -} - -func testErrFunc(Config interface{}) error { - return errors.New("Error") -} - -type Config struct{} - func TestRunErc20HandlerTestSuite(t *testing.T) { suite.Run(t, new(Erc20HandlerTestSuite)) } @@ -68,11 +58,7 @@ func (s *Erc20HandlerTestSuite) TestErc20HandleEvent() { recipientAddressParsed, }, } - conf := &Config{} - erc20DepositHandler := deposithandlers.Erc20DepositHandler{ - ArbitraryFunction: testFunc, - Config: conf, - } + erc20DepositHandler := deposithandlers.Erc20DepositHandler{} message, err := erc20DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) s.Nil(err) @@ -80,32 +66,6 @@ func (s *Erc20HandlerTestSuite) TestErc20HandleEvent() { s.Equal(message, expected) } -func (s *Erc20HandlerTestSuite) TestErc20HandleEventArbitraryFunctionError() { - // 0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b - recipientByteSlice := []byte{241, 229, 143, 177, 119, 4, 194, 218, 132, 121, 165, 51, 249, 250, 212, 173, 9, 147, 202, 107} - - calldata := deposit.ConstructErc20DepositData(recipientByteSlice, big.NewInt(2)) - depositLog := &eventhandlers.Deposit{ - DestinationDomainID: 0, - ResourceID: [32]byte{0}, - DepositNonce: 1, - SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), - Data: calldata, - HandlerResponse: []byte{}, - } - - sourceID := uint8(1) - - conf := &Config{} - erc20DepositHandler := deposithandlers.Erc20DepositHandler{ - ArbitraryFunction: testErrFunc, - Config: conf, - } - _, err := erc20DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) - - s.NotNil(err) -} - func (s *Erc20HandlerTestSuite) TestErc20HandleEventWithPriority() { // 0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b recipientByteSlice := []byte{241, 229, 143, 177, 119, 4, 194, 218, 132, 121, 165, 51, 249, 250, 212, 173, 9, 147, 202, 107} @@ -144,11 +104,7 @@ func (s *Erc20HandlerTestSuite) TestErc20HandleEventWithPriority() { }, } - conf := &Config{} - erc20DepositHandler := deposithandlers.Erc20DepositHandler{ - ArbitraryFunction: testFunc, - Config: conf, - } + erc20DepositHandler := deposithandlers.Erc20DepositHandler{} message, err := erc20DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) s.Nil(err) @@ -173,12 +129,8 @@ func (s *Erc20HandlerTestSuite) TestErc20HandleEventIncorrectDataLen() { } sourceID := uint8(1) - conf := &Config{} - erc20DepositHandler := deposithandlers.Erc20DepositHandler{ - ArbitraryFunction: testFunc, - Config: conf, - } + erc20DepositHandler := deposithandlers.Erc20DepositHandler{} message, err := erc20DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) s.Nil(message) diff --git a/chains/evm/deposithandlers/erc721.go b/chains/evm/deposithandlers/erc721.go index c355e80c..d40c3bbe 100644 --- a/chains/evm/deposithandlers/erc721.go +++ b/chains/evm/deposithandlers/erc721.go @@ -7,10 +7,7 @@ import ( "github.com/ChainSafe/sygma-core/types" ) -type Erc721DepositHandler struct { - ArbitraryFunction arbitraryFunction - Config interface{} -} +type Erc721DepositHandler struct{} // Erc721DepositHandler converts data pulled from ERC721 deposit event logs into message func (dh *Erc721DepositHandler) HandleDeposit(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*types.Message, error) { @@ -19,11 +16,6 @@ func (dh *Erc721DepositHandler) HandleDeposit(sourceID, destId uint8, nonce uint return nil, err } - err := dh.ArbitraryFunction(dh.Config) - if err != nil { - return nil, err - } - // first 32 bytes are tokenId tokenId := calldata[:32] diff --git a/chains/evm/deposithandlers/erc721_test.go b/chains/evm/deposithandlers/erc721_test.go index 9e225686..b730742b 100644 --- a/chains/evm/deposithandlers/erc721_test.go +++ b/chains/evm/deposithandlers/erc721_test.go @@ -55,12 +55,8 @@ func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerEmptyMetadata() { metadata, }, } - conf := &Config{} - erc721DepositHandler := deposithandlers.Erc721DepositHandler{ - ArbitraryFunction: testFunc, - Config: conf, - } + erc721DepositHandler := deposithandlers.Erc721DepositHandler{} m, err := erc721DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) s.Nil(err) @@ -68,30 +64,6 @@ func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerEmptyMetadata() { s.Equal(expected, m) } -func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerArbitraryFunctionError() { - recipient := common.HexToAddress("0xf1e58fb17704c2da8479a533f9fad4ad0993ca6b") - - calldata := deposit.ConstructErc721DepositData(recipient.Bytes(), big.NewInt(2), []byte{}) - depositLog := &eventhandlers.Deposit{ - DestinationDomainID: 0, - ResourceID: [32]byte{0}, - DepositNonce: 1, - Data: calldata, - HandlerResponse: []byte{}, - } - - sourceID := uint8(1) - conf := &Config{} - - erc721DepositHandler := deposithandlers.Erc721DepositHandler{ - ArbitraryFunction: testErrFunc, - Config: conf, - } - _, err := erc721DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) - - s.NotNil(err) -} - func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerIncorrectDataLen() { metadata := []byte("0xdeadbeef") @@ -109,12 +81,8 @@ func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerIncorrectDataLen() { } sourceID := uint8(1) - conf := &Config{} - erc721DepositHandler := deposithandlers.Erc721DepositHandler{ - ArbitraryFunction: testFunc, - Config: conf, - } + erc721DepositHandler := deposithandlers.Erc721DepositHandler{} m, err := erc721DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) s.Nil(m) s.EqualError(err, "invalid calldata length: less than 84 bytes") @@ -150,12 +118,8 @@ func (s *Erc721HandlerTestSuite) TestErc721DepositHandler() { parsedMetadata, }, } - conf := &Config{} - erc721DepositHandler := deposithandlers.Erc721DepositHandler{ - ArbitraryFunction: testFunc, - Config: conf, - } + erc721DepositHandler := deposithandlers.Erc721DepositHandler{} m, err := erc721DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) s.Nil(err) s.NotNil(m) @@ -208,12 +172,8 @@ func (s *Erc721HandlerTestSuite) TestErc721DepositHandlerWithPriority() { }, }, } - conf := &Config{} - erc721DepositHandler := deposithandlers.Erc721DepositHandler{ - ArbitraryFunction: testFunc, - Config: conf, - } + erc721DepositHandler := deposithandlers.Erc721DepositHandler{} m, err := erc721DepositHandler.HandleDeposit(sourceID, depositLog.DestinationDomainID, depositLog.DepositNonce, depositLog.ResourceID, depositLog.Data, depositLog.HandlerResponse) s.Nil(err) s.NotNil(m) diff --git a/chains/evm/deposithandlers/generic.go b/chains/evm/deposithandlers/generic.go index b19bbdff..2b2fe4ce 100644 --- a/chains/evm/deposithandlers/generic.go +++ b/chains/evm/deposithandlers/generic.go @@ -7,10 +7,7 @@ import ( "github.com/ChainSafe/sygma-core/types" ) -type GenericDepositHandler struct { - ArbitraryFunction arbitraryFunction - Config interface{} -} +type GenericDepositHandler struct{} // GenericDepositHandler converts data pulled from generic deposit event logs into message func (dh *GenericDepositHandler) HandleDeposit(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*types.Message, error) { @@ -18,10 +15,7 @@ func (dh *GenericDepositHandler) HandleDeposit(sourceID, destId uint8, nonce uin err := errors.New("invalid calldata length: less than 32 bytes") return nil, err } - err := dh.ArbitraryFunction(dh.Config) - if err != nil { - return nil, err - } + // first 32 bytes are metadata length metadataLen := big.NewInt(0).SetBytes(calldata[:32]) metadata := calldata[32 : 32+metadataLen.Int64()] diff --git a/chains/evm/deposithandlers/generic_test.go b/chains/evm/deposithandlers/generic_test.go index 2c4be962..6df75b0f 100644 --- a/chains/evm/deposithandlers/generic_test.go +++ b/chains/evm/deposithandlers/generic_test.go @@ -43,12 +43,8 @@ func (s *GenericHandlerTestSuite) TestGenericHandleEventIncorrectDataLen() { } sourceID := uint8(1) - conf := &Config{} - genericDepositHandler := deposithandlers.GenericDepositHandler{ - ArbitraryFunction: testFunc, - Config: conf, - } + genericDepositHandler := deposithandlers.GenericDepositHandler{} message, err := genericDepositHandler.HandleDeposit( sourceID, depositLog.DestinationDomainID, @@ -86,12 +82,8 @@ func (s *GenericHandlerTestSuite) TestGenericHandleEventEmptyMetadata() { metadata, }, } - conf := &Config{} - genericDepositHandler := deposithandlers.GenericDepositHandler{ - ArbitraryFunction: testFunc, - Config: conf, - } + genericDepositHandler := deposithandlers.GenericDepositHandler{} message, err := genericDepositHandler.HandleDeposit( sourceID, depositLog.DestinationDomainID, @@ -131,11 +123,7 @@ func (s *GenericHandlerTestSuite) TestGenericHandleEvent() { }, } - conf := &Config{} - genericDepositHandler := deposithandlers.GenericDepositHandler{ - ArbitraryFunction: testFunc, - Config: conf, - } + genericDepositHandler := deposithandlers.GenericDepositHandler{} message, err := genericDepositHandler.HandleDeposit( sourceID, depositLog.DestinationDomainID, @@ -149,35 +137,3 @@ func (s *GenericHandlerTestSuite) TestGenericHandleEvent() { s.NotNil(message) s.Equal(message, expected) } - -func (s *GenericHandlerTestSuite) TestGenericHandleEventArbitraryFunctionError() { - metadata := []byte("0xdeadbeef") - calldata := deposit.ConstructGenericDepositData(metadata) - - depositLog := &eventhandlers.Deposit{ - DestinationDomainID: 0, - ResourceID: [32]byte{0}, - DepositNonce: 1, - SenderAddress: common.HexToAddress("0x4CEEf6139f00F9F4535Ad19640Ff7A0137708485"), - Data: calldata, - HandlerResponse: []byte{}, - } - - sourceID := uint8(1) - - conf := &Config{} - genericDepositHandler := deposithandlers.GenericDepositHandler{ - ArbitraryFunction: testErrFunc, - Config: conf, - } - _, err := genericDepositHandler.HandleDeposit( - sourceID, - depositLog.DestinationDomainID, - depositLog.DepositNonce, - depositLog.ResourceID, - depositLog.Data, - depositLog.HandlerResponse, - ) - - s.NotNil(err) -} diff --git a/chains/evm/eventhandlers/mock/eventhandlers.go b/chains/evm/eventhandlers/mock/eventhandlers.go index 1a17312c..dabd3faa 100644 --- a/chains/evm/eventhandlers/mock/eventhandlers.go +++ b/chains/evm/eventhandlers/mock/eventhandlers.go @@ -2,7 +2,9 @@ // Source: ./chains/evm/eventhandlers/event-handler.go // // Generated by this command: -// mockgen -destination=chains/evm/eventhandlers/mock/eventhandlers.go -source=./chains/evm/eventhandlers/event-handler.go -package mock +// +// mockgen -destination=chains/evm/eventhandlers/mock/eventhandlers.go -source=./chains/evm/eventhandlers/event-handler.go -package mock +// // Package mock is a generated GoMock package. package mock