Skip to content

Commit

Permalink
feat: deposit event handler (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpetrun5 authored Nov 3, 2023
1 parent 435cf46 commit 669d420
Show file tree
Hide file tree
Showing 10 changed files with 792 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/mocks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
with:
go-version: "^1.17"

- run: go install github.com/golang/mock/mockgen@v1.6.0
- run: go install go.uber.org/mock/mockgen@v0.3.0

- run: make genmocks

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ test:
./scripts/tests.sh

genmocks:
echo ''
mockgen -source=./chains/evm/listener/events/handlers/deposit.go -destination=./mock/handlers.go -package mock


PLATFORMS := linux/amd64 darwin/amd64 darwin/arm64 linux/arm
Expand Down
213 changes: 213 additions & 0 deletions chains/evm/abi/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
// The Licensed Work is (c) 2023 Sygma
// SPDX-License-Identifier: LGPL-3.0-only

package abi

const RouterABI = `[
{
"inputs": [
{
"internalType": "uint8",
"name": "domainID",
"type": "uint8"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "DepositToCurrentDomain",
"type": "error"
},
{
"inputs": [],
"name": "NonceDecrementsNotAllowed",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint8",
"name": "destinationDomainID",
"type": "uint8"
},
{
"indexed": false,
"internalType": "uint8",
"name": "securityModel",
"type": "uint8"
},
{
"indexed": false,
"internalType": "bytes32",
"name": "resourceID",
"type": "bytes32"
},
{
"indexed": false,
"internalType": "uint64",
"name": "depositNonce",
"type": "uint64"
},
{
"indexed": true,
"internalType": "address",
"name": "user",
"type": "address"
},
{
"indexed": false,
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "Deposit",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"name": "_depositCounts",
"outputs": [
{
"internalType": "uint64",
"name": "",
"type": "uint64"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "_domainID",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint8",
"name": "destinationDomainID",
"type": "uint8"
},
{
"internalType": "uint8",
"name": "securityModel",
"type": "uint8"
},
{
"internalType": "bytes32",
"name": "resourceID",
"type": "bytes32"
},
{
"internalType": "bytes",
"name": "depositData",
"type": "bytes"
},
{
"internalType": "bytes",
"name": "feeData",
"type": "bytes"
}
],
"name": "deposit",
"outputs": [
{
"internalType": "uint64",
"name": "depositNonce",
"type": "uint64"
}
],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "transferHashes",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]`
36 changes: 36 additions & 0 deletions chains/evm/listener/events/events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// The Licensed Work is (c) 2023 Sygma
// SPDX-License-Identifier: LGPL-3.0-only

package events

import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)

type EventSig string

func (es EventSig) GetTopic() common.Hash {
return crypto.Keccak256Hash([]byte(es))
}

const (
DepositSig EventSig = "Deposit(uint8,uint8,bytes32,uint64,address,bytes)"
)

// Deposit struct holds event data raised by Deposit event on-chain
type Deposit struct {
// ID of chain deposit will be bridged to
DestinationDomainID uint8
// SecurityModel is used to distringuish between block header oracles
// on the destination network that verify this deposit
SecurityModel uint8
// ResourceID used to find address of handler to be used for deposit
ResourceID [32]byte
// Nonce of deposit
DepositNonce uint64
// Address of sender (msg.sender: user)
SenderAddress common.Address
// Additional data to be passed to specified handler
Data []byte
}
122 changes: 122 additions & 0 deletions chains/evm/listener/events/handlers/deposit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// The Licensed Work is (c) 2023 Sygma
// SPDX-License-Identifier: LGPL-3.0-only

package handlers

import (
"context"
"fmt"
"math/big"
"strings"

ethereumABI "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/rs/zerolog/log"
"github.com/sygmaprotocol/spectre-node/chains/evm/abi"
"github.com/sygmaprotocol/spectre-node/chains/evm/listener/events"
evmMessage "github.com/sygmaprotocol/spectre-node/chains/evm/message"
"github.com/sygmaprotocol/sygma-core/relayer/message"
)

type EventFetcher interface {
FetchEventLogs(ctx context.Context, contractAddress common.Address, event string, startBlock *big.Int, endBlock *big.Int) ([]types.Log, error)
}

type StepProver interface {
StepProof(blocknumber *big.Int) (interface{}, error)
}

type DepositEventHandler struct {
msgChan chan []*message.Message

eventFetcher EventFetcher
stepProver StepProver

domainID uint8
routerABI ethereumABI.ABI
routerAddress common.Address
}

func NewDepositEventHandler(
msgChan chan []*message.Message,
eventFetcher EventFetcher,
stepProver StepProver,
routerAddress common.Address,
domainID uint8,
) *DepositEventHandler {
routerABI, _ := ethereumABI.JSON(strings.NewReader(abi.RouterABI))
return &DepositEventHandler{
eventFetcher: eventFetcher,
stepProver: stepProver,
routerAddress: routerAddress,
routerABI: routerABI,
msgChan: msgChan,
domainID: domainID,
}
}

// HandleEvents fetches deposit events and if deposits exists, submits a step message
// to be executed on the destination network
func (h *DepositEventHandler) HandleEvents(startBlock *big.Int, endBlock *big.Int) error {
deposits, err := h.fetchDeposits(startBlock, endBlock)
if err != nil {
return fmt.Errorf("unable to fetch deposit events because of: %+v", err)
}
domainDeposits := make(map[uint8][]*events.Deposit)
for _, d := range deposits {
domainDeposits[d.DestinationDomainID] = append(domainDeposits[d.DestinationDomainID], d)
}
if len(domainDeposits) == 0 {
return nil
}

proof, err := h.stepProver.StepProof(endBlock)
if err != nil {
return err
}
for _, deposits := range domainDeposits {
h.msgChan <- []*message.Message{
evmMessage.NewEvmStepMessage(
h.domainID,
deposits[0].DestinationDomainID,
proof,
),
}
}
return nil
}

func (h *DepositEventHandler) fetchDeposits(startBlock *big.Int, endBlock *big.Int) ([]*events.Deposit, error) {
logs, err := h.eventFetcher.FetchEventLogs(context.Background(), h.routerAddress, string(events.DepositSig), startBlock, endBlock)
if err != nil {
return nil, err
}

deposits := make([]*events.Deposit, 0)
for _, dl := range logs {
d, err := h.unpackDeposit(dl.Data)
if err != nil {
log.Error().Msgf("Failed unpacking deposit event log: %v", err)
continue
}
d.SenderAddress = common.BytesToAddress(dl.Topics[1].Bytes())

log.Debug().Msgf("Found deposit log in block: %d, TxHash: %s, contractAddress: %s, sender: %s", dl.BlockNumber, dl.TxHash, dl.Address, d.SenderAddress)
deposits = append(deposits, d)
}

return deposits, nil
}

func (h *DepositEventHandler) unpackDeposit(data []byte) (*events.Deposit, error) {
fmt.Println(data)

var d events.Deposit
err := h.routerABI.UnpackIntoInterface(&d, "Deposit", data)
if err != nil {
return &events.Deposit{}, err
}

return &d, nil
}
Loading

0 comments on commit 669d420

Please sign in to comment.