Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(relayer): add is_profitable and fee related columns #17619

Merged
merged 6 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 42 additions & 23 deletions packages/relayer/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"math/big"
"net/http"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/morkid/paginate"
Expand Down Expand Up @@ -51,29 +52,36 @@ func (e EventType) String() string {
// into the Data field to be unmarshalled into a concrete struct
// dependant on the name of the event
type Event struct {
ID int `json:"id"`
Name string `json:"name"`
Data datatypes.JSON `json:"data"`
Status EventStatus `json:"status"`
EventType EventType `json:"eventType"`
ChainID int64 `json:"chainID"`
DestChainID int64 `json:"destChainID"`
SyncedChainID uint64 `json:"syncedChainID"`
EmittedBlockID uint64 `json:"emittedBlockID"`
BlockID uint64 `json:"blockID"`
SyncedInBlockID uint64 `json:"syncedInBlockID"`
SyncData string `json:"syncData"`
Kind string `json:"kind"`
CanonicalTokenAddress string `json:"canonicalTokenAddress"`
CanonicalTokenSymbol string `json:"canonicalTokenSymbol"`
CanonicalTokenName string `json:"canonicalTokenName"`
CanonicalTokenDecimals uint8 `json:"canonicalTokenDecimals"`
Amount string `json:"amount"`
MsgHash string `json:"msgHash"`
MessageOwner string `json:"messageOwner"`
Event string `json:"event"`
ClaimedBy string `json:"claimedBy" gorm:"-"`
ProcessedTxHash string `json:"processedTxHash" gorm:"-"`
ID int `json:"id"`
Name string `json:"name"`
Data datatypes.JSON `json:"data"`
Status EventStatus `json:"status"`
EventType EventType `json:"eventType"`
ChainID int64 `json:"chainID"`
DestChainID int64 `json:"destChainID"`
SyncedChainID uint64 `json:"syncedChainID"`
EmittedBlockID uint64 `json:"emittedBlockID"`
BlockID uint64 `json:"blockID"`
SyncedInBlockID uint64 `json:"syncedInBlockID"`
SyncData string `json:"syncData"`
Kind string `json:"kind"`
CanonicalTokenAddress string `json:"canonicalTokenAddress"`
CanonicalTokenSymbol string `json:"canonicalTokenSymbol"`
CanonicalTokenName string `json:"canonicalTokenName"`
CanonicalTokenDecimals uint8 `json:"canonicalTokenDecimals"`
Amount string `json:"amount"`
MsgHash string `json:"msgHash"`
MessageOwner string `json:"messageOwner"`
Event string `json:"event"`
ClaimedBy string `json:"claimedBy" gorm:"-"`
ProcessedTxHash string `json:"processedTxHash" gorm:"-"`
Fee *uint64 `json:"fee"`
DestChainBaseFee *uint64 `json:"destChainBaseFee"`
GasTipCap *uint64 `json:"gasTipCap"`
GasLimit *uint64 `json:"gasLimit"`
IsProfitable *bool `json:"isProfitable"`
EstimatedOnchainFee *uint64 `json:"estimatedOnchainFee"`
IsProfitableEvaluatedAt *time.Time `json:"isProfitableEvaluatedAt"`
}

// SaveEventOpts
Expand All @@ -100,6 +108,16 @@ type SaveEventOpts struct {
SyncedInBlockID uint64
}

type UpdateFeesAndProfitabilityOpts struct {
Fee uint64
DestChainBaseFee uint64
GasTipCap uint64
GasLimit uint64
IsProfitable bool
EstimatedOnchainFee uint64
IsProfitableEvaluatedAt time.Time
}

type FindAllByAddressOpts struct {
Address common.Address
EventType *EventType
Expand All @@ -112,6 +130,7 @@ type FindAllByAddressOpts struct {
type EventRepository interface {
Save(ctx context.Context, opts SaveEventOpts) (*Event, error)
UpdateStatus(ctx context.Context, id int, status EventStatus) error
UpdateFeesAndProfitability(ctx context.Context, id int, opts UpdateFeesAndProfitabilityOpts) error
FindAllByAddress(
ctx context.Context,
req *http.Request,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- +goose Up
-- +goose StatementBegin
ALTER TABLE `events`
ADD COLUMN `fee` BIGINT UNSIGNED NULL,
ADD COLUMN `dest_chain_base_fee` BIGINT UNSIGNED NULL,
ADD COLUMN `gas_tip_cap` BIGINT UNSIGNED NULL,
ADD COLUMN `gas_limit` BIGINT UNSIGNED NULL,
ADD COLUMN `is_profitable` BOOLEAN NULL,
ADD COLUMN `estimated_onchain_fee` BIGINT UNSIGNED NULL,
ADD COLUMN `is_profitable_evaluated_at` TIMESTAMP NULL;

-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
ALTER TABLE `events`
DROP COLUMN `fee`,
DROP COLUMN `dest_chain_base_fee`,
DROP COLUMN `gas_tip_cap`,
DROP COLUMN `gas_limit`,
DROP COLUMN `is_profitable`,
DROP COLUMN `estimated_onchain_fee`,
DROP COLUMN `is_profitable_evaluated_at`;
-- +goose StatementEnd
39 changes: 39 additions & 0 deletions packages/relayer/pkg/mock/event_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"math/rand"
"net/http"
"time"

"github.com/morkid/paginate"
"github.com/taikoxyz/taiko-mono/packages/relayer"
Expand Down Expand Up @@ -62,6 +63,44 @@ func (r *EventRepository) UpdateStatus(ctx context.Context, id int, status relay
return nil
}

func (r *EventRepository) UpdateFeesAndProfitability(
ctx context.Context,
id int, opts relayer.UpdateFeesAndProfitabilityOpts,
) error {
var event *relayer.Event

var index int

// Find the event by ID
for i, e := range r.events {
if e.ID == id {
event = e
index = i

break
}
}

if event == nil {
return nil // Or return an appropriate error if the event is not found
}

// Update the event fields
event.Fee = &opts.Fee
event.DestChainBaseFee = &opts.DestChainBaseFee
event.GasTipCap = &opts.GasTipCap
event.GasLimit = &opts.GasLimit
event.IsProfitable = &opts.IsProfitable
event.EstimatedOnchainFee = &opts.EstimatedOnchainFee
currentTime := time.Now().UTC()
event.IsProfitableEvaluatedAt = &currentTime

// Save the updated event back to the slice
r.events[index] = event

return nil
}

func (r *EventRepository) FindAllByAddress(
ctx context.Context,
req *http.Request,
Expand Down
27 changes: 27 additions & 0 deletions packages/relayer/pkg/repo/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package repo
import (
"context"
"strings"
"time"

"net/http"

Expand Down Expand Up @@ -58,6 +59,32 @@ func (r *EventRepository) Save(ctx context.Context, opts relayer.SaveEventOpts)
return e, nil
}

func (r *EventRepository) UpdateFeesAndProfitability(
ctx context.Context,
id int,
opts relayer.UpdateFeesAndProfitabilityOpts,
) error {
e := &relayer.Event{}
if err := r.db.GormDB().Where("id = ?", id).First(e).Error; err != nil {
return errors.Wrap(err, "r.db.First")
}

e.Fee = &opts.Fee
e.DestChainBaseFee = &opts.DestChainBaseFee
e.GasTipCap = &opts.GasTipCap
e.GasLimit = &opts.GasLimit
e.IsProfitable = &opts.IsProfitable
e.EstimatedOnchainFee = &opts.EstimatedOnchainFee
currentTime := time.Now().UTC()
e.IsProfitableEvaluatedAt = &currentTime

if err := r.db.GormDB().Save(e).Error; err != nil {
return errors.Wrap(err, "r.db.Save")
}

return nil
}

func (r *EventRepository) UpdateStatus(ctx context.Context, id int, status relayer.EventStatus) error {
e := &relayer.Event{}
if err := r.db.GormDB().Where("id = ?", id).First(e).Error; err != nil {
Expand Down
16 changes: 15 additions & 1 deletion packages/relayer/processor/is_profitable.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package processor

import (
"context"

"log/slog"

"github.com/pkg/errors"
Expand All @@ -18,6 +17,7 @@ var (
// profitable. Otherwise, we compare it to the estimated cost.
func (p *Processor) isProfitable(
ctx context.Context,
id int,
fee uint64,
gasLimit uint64,
destChainBaseFee uint64,
Expand All @@ -44,11 +44,25 @@ func (p *Processor) isProfitable(
slog.Info("isProfitable",
"processingFee", fee,
"destChainBaseFee", destChainBaseFee,
"gasTipCap", gasTipCap,
"gasLimit", gasLimit,
"shouldProcess", shouldProcess,
"estimatedOnchainFee", estimatedOnchainFee,
)

opts := relayer.UpdateFeesAndProfitabilityOpts{
Fee: fee,
DestChainBaseFee: destChainBaseFee,
GasTipCap: gasTipCap,
GasLimit: gasLimit,
IsProfitable: shouldProcess,
EstimatedOnchainFee: estimatedOnchainFee,
}

if err := p.eventRepo.UpdateFeesAndProfitability(ctx, id, opts); err != nil {
slog.Error("failed to update event", "error", err)
}

if !shouldProcess {
relayer.UnprofitableMessagesDetected.Inc()

Expand Down
5 changes: 5 additions & 0 deletions packages/relayer/processor/is_profitable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ func Test_isProfitable(t *testing.T) {
p := newTestProcessor(true)

tests := []struct {
id int
name string
fee uint64
gasLimit uint64
Expand All @@ -20,6 +21,7 @@ func Test_isProfitable(t *testing.T) {
wantErr error
}{
{
0,
"zeroProcessingFee",
0,
1,
Expand All @@ -29,6 +31,7 @@ func Test_isProfitable(t *testing.T) {
errImpossible,
},
{
1,
"profitable",
600000000600001,
600000,
Expand All @@ -38,6 +41,7 @@ func Test_isProfitable(t *testing.T) {
nil,
},
{
2,
"unprofitable",
590000000600000,
600000,
Expand All @@ -52,6 +56,7 @@ func Test_isProfitable(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
profitable, err := p.isProfitable(
context.Background(),
tt.id,
tt.fee,
tt.gasLimit,
tt.baseFee,
Expand Down
4 changes: 3 additions & 1 deletion packages/relayer/processor/process_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func (p *Processor) processMessage(
return false, msgBody.TimesRetried, err
}

_, err = p.sendProcessMessageCall(ctx, msgBody.Event, encodedSignalProof)
_, err = p.sendProcessMessageCall(ctx, msgBody.ID, msgBody.Event, encodedSignalProof)
if err != nil {
return false, msgBody.TimesRetried, err
}
Expand Down Expand Up @@ -390,6 +390,7 @@ func (p *Processor) generateEncodedSignalProof(ctx context.Context,
// after estimating gas, and checking profitability.
func (p *Processor) sendProcessMessageCall(
ctx context.Context,
id int,
event *bridge.BridgeMessageSent,
proof []byte,
) (*types.Receipt, error) {
Expand Down Expand Up @@ -433,6 +434,7 @@ func (p *Processor) sendProcessMessageCall(
if bool(p.profitableOnly) {
profitable, err := p.isProfitable(
ctx,
id,
event.Message.Fee,
gasLimit,
baseFee.Uint64(),
Expand Down
1 change: 1 addition & 0 deletions packages/relayer/processor/process_message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func Test_sendProcessMessageCall(t *testing.T) {

_, err := p.sendProcessMessageCall(
context.Background(),
1,
&bridge.BridgeMessageSent{
Message: bridge.IBridgeMessage{
Id: 1,
Expand Down
Loading