diff --git a/chains/evm/calls/evmclient/evm-client.go b/chains/evm/calls/evmclient/evm-client.go index a9588b2d..525952f0 100644 --- a/chains/evm/calls/evmclient/evm-client.go +++ b/chains/evm/calls/evmclient/evm-client.go @@ -58,6 +58,15 @@ type DepositLogs struct { HandlerResponse []byte } +type DepositLogsEnriched struct { + // Deposit Logs + DepositLogs + // DepositTxHash + DepositTxHash common.Hash + // Deposit Block + DepositBlock uint64 +} + type CommonTransaction interface { // Hash returns the transaction hash. Hash() common.Hash @@ -162,12 +171,12 @@ func (c *EVMClient) GetTransactionByHash(h common.Hash) (tx *types.Transaction, return c.Client.TransactionByHash(context.Background(), h) } -func (c *EVMClient) FetchDepositLogs(ctx context.Context, contractAddress common.Address, startBlock *big.Int, endBlock *big.Int) ([]*DepositLogs, error) { +func (c *EVMClient) FetchDepositLogs(ctx context.Context, contractAddress common.Address, startBlock *big.Int, endBlock *big.Int) ([]*DepositLogsEnriched, error) { logs, err := c.FilterLogs(ctx, buildQuery(contractAddress, string(util.Deposit), startBlock, endBlock)) if err != nil { return nil, err } - depositLogs := make([]*DepositLogs, 0) + depositLogs := make([]*DepositLogsEnriched, 0) abi, err := abi.JSON(strings.NewReader(consts.BridgeABI)) if err != nil { @@ -176,13 +185,18 @@ func (c *EVMClient) FetchDepositLogs(ctx context.Context, contractAddress common for _, l := range logs { dl, err := c.UnpackDepositEventLog(abi, l.Data) + dlEnriched := DepositLogsEnriched{ + *dl, + l.TxHash, + l.BlockNumber, + } if err != nil { log.Error().Msgf("failed unpacking deposit event log: %v", err) continue } log.Debug().Msgf("Found deposit log in block: %d, TxHash: %s, contractAddress: %s, sender: %s", l.BlockNumber, l.TxHash, l.Address, dl.SenderAddress) - depositLogs = append(depositLogs, dl) + depositLogs = append(depositLogs, &dlEnriched) } return depositLogs, nil diff --git a/chains/evm/listener/event-handler.go b/chains/evm/listener/event-handler.go index 6bde0a43..71ef2583 100644 --- a/chains/evm/listener/event-handler.go +++ b/chains/evm/listener/event-handler.go @@ -12,7 +12,7 @@ import ( ) type EventHandlers map[common.Address]EventHandlerFunc -type EventHandlerFunc func(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*message.Message, error) +type EventHandlerFunc func(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte, depositTxHash common.Hash, depositBlock uint64) (*message.Message, error) type ETHEventHandler struct { bridgeContract bridge.BridgeContract @@ -27,7 +27,7 @@ func NewETHEventHandler(bridgeContract bridge.BridgeContract) *ETHEventHandler { } } -func (e *ETHEventHandler) HandleEvent(sourceID, destID uint8, depositNonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*message.Message, error) { +func (e *ETHEventHandler) HandleEvent(sourceID, destID uint8, depositNonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte, depositTxHash common.Hash, depositBlock uint64) (*message.Message, error) { handlerAddr, err := e.bridgeContract.GetHandlerAddressForResourceID(resourceID) if err != nil { return nil, err @@ -38,7 +38,7 @@ func (e *ETHEventHandler) HandleEvent(sourceID, destID uint8, depositNonce uint6 return nil, err } - return eventHandler(sourceID, destID, depositNonce, resourceID, calldata, handlerResponse) + return eventHandler(sourceID, destID, depositNonce, resourceID, calldata, handlerResponse, depositTxHash, depositBlock) } // matchAddressWithHandlerFunc matches a handler address with an associated handler function @@ -67,7 +67,7 @@ func (e *ETHEventHandler) RegisterEventHandler(handlerAddress string, handler Ev // Erc20EventHandler converts data pulled from event logs into message // handlerResponse can be an empty slice -func Erc20EventHandler(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*message.Message, error) { +func Erc20EventHandler(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte, depositTxHash common.Hash, depositBlock uint64) (*message.Message, error) { if len(calldata) < 84 { err := errors.New("invalid calldata length: less than 84 bytes") return nil, err @@ -91,11 +91,13 @@ func Erc20EventHandler(sourceID, destId uint8, nonce uint64, resourceID types.Re recipientAddress := calldata[64:] return &message.Message{ - Source: sourceID, - Destination: destId, - DepositNonce: nonce, - ResourceId: resourceID, - Type: message.FungibleTransfer, + DepositTxHash: depositTxHash, + DepositBlock: depositBlock, + Source: sourceID, + Destination: destId, + DepositNonce: nonce, + ResourceId: resourceID, + Type: message.FungibleTransfer, Payload: []interface{}{ amount, recipientAddress, @@ -104,7 +106,7 @@ func Erc20EventHandler(sourceID, destId uint8, nonce uint64, resourceID types.Re } // GenericEventHandler converts data pulled from generic deposit event logs into message -func GenericEventHandler(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*message.Message, error) { +func GenericEventHandler(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte, depositTxHash common.Hash, depositBlock uint64) (*message.Message, error) { if len(calldata) < 32 { err := errors.New("invalid calldata length: less than 32 bytes") return nil, err @@ -114,11 +116,13 @@ func GenericEventHandler(sourceID, destId uint8, nonce uint64, resourceID types. metadata := calldata[32:] return &message.Message{ - Source: sourceID, - Destination: destId, - DepositNonce: nonce, - ResourceId: resourceID, - Type: message.GenericTransfer, + DepositTxHash: depositTxHash, + DepositBlock: depositBlock, + Source: sourceID, + Destination: destId, + DepositNonce: nonce, + ResourceId: resourceID, + Type: message.GenericTransfer, Payload: []interface{}{ metadata, }, @@ -126,7 +130,7 @@ func GenericEventHandler(sourceID, destId uint8, nonce uint64, resourceID types. } // Erc721EventHandler converts data pulled from ERC721 deposit event logs into message -func Erc721EventHandler(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*message.Message, error) { +func Erc721EventHandler(sourceID, destId uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte, depositTxHash common.Hash, depositBlock uint64) (*message.Message, error) { if len(calldata) < 64 { err := errors.New("invalid calldata length: less than 84 bytes") return nil, err @@ -154,11 +158,13 @@ func Erc721EventHandler(sourceID, destId uint8, nonce uint64, resourceID types.R } return &message.Message{ - Source: sourceID, - Destination: destId, - DepositNonce: nonce, - ResourceId: resourceID, - Type: message.NonFungibleTransfer, + DepositTxHash: depositTxHash, + DepositBlock: depositBlock, + Source: sourceID, + Destination: destId, + DepositNonce: nonce, + ResourceId: resourceID, + Type: message.NonFungibleTransfer, Payload: []interface{}{ tokenId, recipientAddress, diff --git a/chains/evm/listener/listener.go b/chains/evm/listener/listener.go index 2a9546e9..ec3ee424 100644 --- a/chains/evm/listener/listener.go +++ b/chains/evm/listener/listener.go @@ -19,11 +19,11 @@ import ( ) type EventHandler interface { - HandleEvent(sourceID, destID uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*message.Message, error) + HandleEvent(sourceID, destID uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte, depositTxHash common.Hash, depositBlock uint64) (*message.Message, error) } type ChainClient interface { LatestBlock() (*big.Int, error) - FetchDepositLogs(ctx context.Context, address common.Address, startBlock *big.Int, endBlock *big.Int) ([]*evmclient.DepositLogs, error) + FetchDepositLogs(ctx context.Context, address common.Address, startBlock *big.Int, endBlock *big.Int) ([]*evmclient.DepositLogsEnriched, error) CallContract(ctx context.Context, callArgs map[string]interface{}, blockNumber *big.Int) ([]byte, error) } @@ -80,7 +80,7 @@ func (l *EVMListener) ListenToEvents( } for _, eventLog := range logs { log.Debug().Msgf("Deposit log found from sender: %s in block: %s with destinationDomainId: %v, resourceID: %X, depositNonce: %v", eventLog.SenderAddress, startBlock.String(), eventLog.DestinationDomainID, eventLog.ResourceID[:], eventLog.DepositNonce) - m, err := l.eventHandler.HandleEvent(domainID, eventLog.DestinationDomainID, eventLog.DepositNonce, eventLog.ResourceID, eventLog.Data, eventLog.HandlerResponse) + m, err := l.eventHandler.HandleEvent(domainID, eventLog.DestinationDomainID, eventLog.DepositNonce, eventLog.ResourceID, eventLog.Data, eventLog.HandlerResponse, eventLog.DepositTxHash, eventLog.DepositBlock) if err != nil { log.Error().Str("block", startBlock.String()).Uint8("domainID", domainID).Msgf("%v", err) } else { diff --git a/chains/evm/listener/mock/listener.go b/chains/evm/listener/mock/listener.go index 9904a358..aa21c59b 100644 --- a/chains/evm/listener/mock/listener.go +++ b/chains/evm/listener/mock/listener.go @@ -55,10 +55,10 @@ func (mr *MockChainClientMockRecorder) CallContract(ctx, callArgs, blockNumber i } // FetchDepositLogs mocks base method. -func (m *MockChainClient) FetchDepositLogs(ctx context.Context, address common.Address, startBlock, endBlock *big.Int) ([]*evmclient.DepositLogs, error) { +func (m *MockChainClient) FetchDepositLogs(ctx context.Context, address common.Address, startBlock, endBlock *big.Int) ([]*evmclient.DepositLogsEnriched, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "FetchDepositLogs", ctx, address, startBlock, endBlock) - ret0, _ := ret[0].([]*evmclient.DepositLogs) + ret0, _ := ret[0].([]*evmclient.DepositLogsEnriched) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -108,7 +108,7 @@ func (m *MockEventHandler) EXPECT() *MockEventHandlerMockRecorder { } // HandleEvent mocks base method. -func (m *MockEventHandler) HandleEvent(sourceID, destID uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte) (*message.Message, error) { +func (m *MockEventHandler) HandleEvent(sourceID, destID uint8, nonce uint64, resourceID types.ResourceID, calldata, handlerResponse []byte, depositTxHash common.Hash, depositBlock uint64) (*message.Message, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "HandleEvent", sourceID, destID, nonce, resourceID, calldata, handlerResponse) ret0, _ := ret[0].(*message.Message) diff --git a/chains/evm/voter/message-handler.go b/chains/evm/voter/message-handler.go index c2006c7d..48990920 100644 --- a/chains/evm/voter/message-handler.go +++ b/chains/evm/voter/message-handler.go @@ -69,15 +69,15 @@ func (mh *EVMMessageHandler) RegisterMessageHandler(address string, handler Mess mh.handlers[common.HexToAddress(address)] = handler } -func ERC20MessageHandler(m *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { - if len(m.Payload) != 2 { +func ERC20MessageHandler(msg *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { + if len(msg.Payload) != 2 { return nil, errors.New("malformed payload. Len of payload should be 2") } - amount, ok := m.Payload[0].([]byte) + amount, ok := msg.Payload[0].([]byte) if !ok { return nil, errors.New("wrong payloads amount format") } - recipient, ok := m.Payload[1].([]byte) + recipient, ok := msg.Payload[1].([]byte) if !ok { return nil, errors.New("wrong payloads recipient format") } @@ -86,7 +86,7 @@ func ERC20MessageHandler(m *message.Message, handlerAddr, bridgeAddress common.A recipientLen := big.NewInt(int64(len(recipient))).Bytes() data = append(data, common.LeftPadBytes(recipientLen, 32)...) // length of recipient (uint256) data = append(data, recipient...) // recipient ([]byte) - return proposal.NewProposal(m.Source, m.DepositNonce, m.ResourceId, data, handlerAddr, bridgeAddress), nil + return proposal.NewProposal(msg.Source, msg.DepositNonce, msg.ResourceId, data, handlerAddr, bridgeAddress, msg.DepositTxHash, msg.DepositBlock), nil } func ERC721MessageHandler(msg *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { @@ -113,7 +113,7 @@ func ERC721MessageHandler(msg *message.Message, handlerAddr, bridgeAddress commo metadataLen := big.NewInt(int64(len(metadata))).Bytes() data.Write(common.LeftPadBytes(metadataLen, 32)) data.Write(metadata) - return proposal.NewProposal(msg.Source, msg.DepositNonce, msg.ResourceId, data.Bytes(), handlerAddr, bridgeAddress), nil + return proposal.NewProposal(msg.Source, msg.DepositNonce, msg.ResourceId, data.Bytes(), handlerAddr, bridgeAddress, msg.DepositTxHash, msg.DepositBlock), nil } func GenericMessageHandler(msg *message.Message, handlerAddr, bridgeAddress common.Address) (*proposal.Proposal, error) { @@ -128,5 +128,5 @@ func GenericMessageHandler(msg *message.Message, handlerAddr, bridgeAddress comm metadataLen := big.NewInt(int64(len(metadata))).Bytes() data.Write(common.LeftPadBytes(metadataLen, 32)) // length of metadata (uint256) data.Write(metadata) - return proposal.NewProposal(msg.Source, msg.DepositNonce, msg.ResourceId, data.Bytes(), handlerAddr, bridgeAddress), nil + return proposal.NewProposal(msg.Source, msg.DepositNonce, msg.ResourceId, data.Bytes(), handlerAddr, bridgeAddress, msg.DepositTxHash, msg.DepositBlock), nil } diff --git a/chains/evm/voter/proposal/proposal.go b/chains/evm/voter/proposal/proposal.go index fb43c308..dae9e80e 100644 --- a/chains/evm/voter/proposal/proposal.go +++ b/chains/evm/voter/proposal/proposal.go @@ -6,8 +6,10 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) -func NewProposal(source uint8, depositNonce uint64, resourceId types.ResourceID, data []byte, handlerAddress, bridgeAddress common.Address) *Proposal { +func NewProposal(source uint8, depositNonce uint64, resourceId types.ResourceID, data []byte, handlerAddress, bridgeAddress common.Address, depositTxHash common.Hash, depositBlock uint64) *Proposal { return &Proposal{ + DepositTxHash: depositTxHash, + DepositBlock: depositBlock, Source: source, DepositNonce: depositNonce, ResourceId: resourceId, @@ -18,8 +20,10 @@ func NewProposal(source uint8, depositNonce uint64, resourceId types.ResourceID, } type Proposal struct { - Source uint8 // Source domainID where message was initiated - DepositNonce uint64 // Nonce for the deposit + DepositTxHash common.Hash // transaction hash of the deposit transaction + DepositBlock uint64 // Block the Deposit transaction were made + Source uint8 // Source domainID where message was initiated + DepositNonce uint64 // Nonce for the deposit ResourceId types.ResourceID Payload []interface{} // data associated with event sequence Data []byte diff --git a/relayer/message/message.go b/relayer/message/message.go index dd2c426d..77dbb997 100644 --- a/relayer/message/message.go +++ b/relayer/message/message.go @@ -6,6 +6,7 @@ package message import ( "errors" "fmt" + "github.com/ethereum/go-ethereum/common" "math/big" "github.com/ChainSafe/chainbridge-core/types" @@ -39,12 +40,14 @@ var ( ) type Message struct { - Source uint8 // Source where message was initiated - Destination uint8 // Destination chain of message - DepositNonce uint64 // Nonce for the deposit - ResourceId types.ResourceID - Payload []interface{} // data associated with event sequence - Type TransferType + DepositTxHash common.Hash // transaction hash of the deposit transaction + DepositBlock uint64 // Block the Deposit transaction were made + Source uint8 // Source where message was initiated + Destination uint8 // Destination chain of message + DepositNonce uint64 // Nonce for the deposit + ResourceId types.ResourceID + Payload []interface{} // data associated with event sequence + Type TransferType } func (m *Message) String() string {