From db62baddefb077a512b8ba5cf22acf446b2b9cb6 Mon Sep 17 00:00:00 2001 From: Mohammed Sohail Date: Mon, 7 Oct 2024 10:36:58 +0300 Subject: [PATCH] feat: add contract creation handler --- cmd/service/router.go | 2 + internal/handler/contract_creation.go | 27 +++++++ internal/processor/processor.go | 103 ++++++++++++++++++++------ pkg/router/router.go | 36 +++++++-- 4 files changed, 139 insertions(+), 29 deletions(-) create mode 100644 internal/handler/contract_creation.go diff --git a/cmd/service/router.go b/cmd/service/router.go index 80a64d5..b0d7599 100644 --- a/cmd/service/router.go +++ b/cmd/service/router.go @@ -11,6 +11,8 @@ func bootstrapEventRouter(cacheProvider cache.Cache, pubCB router.Callback) *rou handlerContainer := handler.New(cacheProvider) router := router.New(pubCB) + router.RegisterContractCreationHandler(handler.HandleContractCreation()) + router.RegisterLogRoute(w3.H("0x26162814817e23ec5035d6a2edc6c422da2da2119e27cfca6be65cc2dc55ca4c"), handler.HandleFaucetGiveLog()) router.RegisterLogRoute(w3.H("0xa226db3f664042183ee0281230bba26cbf7b5057e50aee7f25a175ff45ce4d7f"), handler.HandleIndexAddLog(handlerContainer)) router.RegisterLogRoute(w3.H("0x24a12366c02e13fe4a9e03d86a8952e85bb74a456c16e4a18b6d8295700b74bb"), handler.HandleIndexRemoveLog(handlerContainer)) diff --git a/internal/handler/contract_creation.go b/internal/handler/contract_creation.go new file mode 100644 index 0000000..c45207b --- /dev/null +++ b/internal/handler/contract_creation.go @@ -0,0 +1,27 @@ +package handler + +import ( + "context" + + "github.com/grassrootseconomics/eth-tracker/pkg/event" + "github.com/grassrootseconomics/eth-tracker/pkg/router" +) + +const contractCreationEventName = "CONTRACT_CREATION" + +func HandleContractCreation() router.ContractCreationHandlerFunc { + return func(ctx context.Context, ccp router.ContractCreationPayload, c router.Callback) error { + contractCreationEvent := event.Event{ + Block: ccp.Block, + ContractAddress: ccp.ContractAddress, + Success: ccp.Success, + Timestamp: ccp.Timestamp, + TxHash: ccp.TxHash, + Payload: map[string]any{ + "from": ccp.From, + }, + } + + return c(ctx, contractCreationEvent) + } +} diff --git a/internal/processor/processor.go b/internal/processor/processor.go index 14376c8..5a16e38 100644 --- a/internal/processor/processor.go +++ b/internal/processor/processor.go @@ -54,7 +54,7 @@ func (p *Processor) ProcessBlock(ctx context.Context, blockNumber uint64) error } for _, receipt := range receipts { - if receipt.Status > 0 { + if receipt.Status == 1 { for _, log := range receipt.Logs { exists, err := p.cache.Exists(ctx, log.Address.Hex()) if err != nil { @@ -72,35 +72,96 @@ func (p *Processor) ProcessBlock(ctx context.Context, blockNumber uint64) error } } } - } else { - tx, err := p.chain.GetTransaction(ctx, receipt.TxHash) - if err != nil && !errors.Is(err, context.Canceled) { - return fmt.Errorf("get transaction error: tx %s: %v", receipt.TxHash.Hex(), err) - } - if tx.To() != nil { - exists, err := p.cache.Exists(ctx, tx.To().Hex()) + if receipt.ContractAddress != (common.Address{}) { + tx, err := p.chain.GetTransaction(ctx, receipt.TxHash) + if err != nil && !errors.Is(err, context.Canceled) { + return fmt.Errorf("get transaction error: tx %s: %v", receipt.TxHash.Hex(), err) + } + + from, err := types.Sender(types.LatestSignerForChainID(tx.ChainId()), tx) + if err != nil { + return fmt.Errorf("transaction decode error: tx %s: %v", receipt.TxHash.Hex(), err) + } + + exists, err := p.cache.Exists(ctx, from.Hex()) if err != nil { return err } - if exists { + + if exists && tx.To() != nil { + if err := p.router.ProcessContractCreation( + ctx, + router.ContractCreationPayload{ + From: from.Hex(), + Block: blockNumber, + ContractAddress: tx.To().Hex(), + Timestamp: block.Time(), + TxHash: receipt.TxHash.Hex(), + Success: true, + }, + ); err != nil && !errors.Is(err, context.Canceled) { + return fmt.Errorf("route success contract creation error: tx %s: %v", receipt.TxHash.Hex(), err) + } + } + } + + if receipt.Status == 0 { + tx, err := p.chain.GetTransaction(ctx, receipt.TxHash) + if err != nil && !errors.Is(err, context.Canceled) { + return fmt.Errorf("get transaction error: tx %s: %v", receipt.TxHash.Hex(), err) + } + + if tx.To() == nil { from, err := types.Sender(types.LatestSignerForChainID(tx.ChainId()), tx) if err != nil { return fmt.Errorf("transaction decode error: tx %s: %v", receipt.TxHash.Hex(), err) } - if err := p.router.ProcessInputData( - ctx, - router.InputDataPayload{ - From: from.Hex(), - InputData: common.Bytes2Hex(tx.Data()), - Block: blockNumber, - ContractAddress: tx.To().Hex(), - Timestamp: block.Time(), - TxHash: receipt.TxHash.Hex(), - }, - ); err != nil && !errors.Is(err, context.Canceled) { - return fmt.Errorf("route revert transaction error: tx %s: %v", receipt.TxHash.Hex(), err) + exists, err := p.cache.Exists(ctx, from.Hex()) + if err != nil { + return err + } + + if exists { + if err := p.router.ProcessContractCreation( + ctx, + router.ContractCreationPayload{ + From: from.Hex(), + Block: blockNumber, + ContractAddress: tx.To().Hex(), + Timestamp: block.Time(), + TxHash: receipt.TxHash.Hex(), + Success: false, + }, + ); err != nil && !errors.Is(err, context.Canceled) { + return fmt.Errorf("route reverted contract creation error: tx %s: %v", receipt.TxHash.Hex(), err) + } + } + } else { + exists, err := p.cache.Exists(ctx, tx.To().Hex()) + if err != nil { + return err + } + if exists { + from, err := types.Sender(types.LatestSignerForChainID(tx.ChainId()), tx) + if err != nil { + return fmt.Errorf("transaction decode error: tx %s: %v", receipt.TxHash.Hex(), err) + } + + if err := p.router.ProcessInputData( + ctx, + router.InputDataPayload{ + From: from.Hex(), + InputData: common.Bytes2Hex(tx.Data()), + Block: blockNumber, + ContractAddress: tx.To().Hex(), + Timestamp: block.Time(), + TxHash: receipt.TxHash.Hex(), + }, + ); err != nil && !errors.Is(err, context.Canceled) { + return fmt.Errorf("route revert transaction error: tx %s: %v", receipt.TxHash.Hex(), err) + } } } } diff --git a/pkg/router/router.go b/pkg/router/router.go index 6f5e940..61696bc 100644 --- a/pkg/router/router.go +++ b/pkg/router/router.go @@ -25,8 +25,18 @@ type ( TxHash string } - LogHandlerFunc func(context.Context, LogPayload, Callback) error - InputDataHandlerFunc func(context.Context, InputDataPayload, Callback) error + ContractCreationPayload struct { + From string + ContractAddress string + Block uint64 + Timestamp uint64 + TxHash string + Success bool + } + + LogHandlerFunc func(context.Context, LogPayload, Callback) error + InputDataHandlerFunc func(context.Context, InputDataPayload, Callback) error + ContractCreationHandlerFunc func(context.Context, ContractCreationPayload, Callback) error LogRouteEntry struct { Signature common.Hash @@ -39,17 +49,19 @@ type ( } Router struct { - callbackFn Callback - logHandlers map[common.Hash]LogRouteEntry - inputDataHandlers map[string]InputDataEntry + callbackFn Callback + logHandlers map[common.Hash]LogRouteEntry + inputDataHandlers map[string]InputDataEntry + contractCreationHandler ContractCreationHandlerFunc } ) func New(callbackFn Callback) *Router { return &Router{ - callbackFn: callbackFn, - logHandlers: make(map[common.Hash]LogRouteEntry), - inputDataHandlers: make(map[string]InputDataEntry), + callbackFn: callbackFn, + logHandlers: make(map[common.Hash]LogRouteEntry), + inputDataHandlers: make(map[string]InputDataEntry), + contractCreationHandler: nil, } } @@ -67,6 +79,10 @@ func (r *Router) RegisterInputDataRoute(signature string, handlerFunc InputDataH } } +func (r *Router) RegisterContractCreationHandler(handlerFunc ContractCreationHandlerFunc) { + r.contractCreationHandler = handlerFunc +} + func (r *Router) ProcessLog(ctx context.Context, payload LogPayload) error { handler, ok := r.logHandlers[payload.Log.Topics[0]] if ok { @@ -88,3 +104,7 @@ func (r *Router) ProcessInputData(ctx context.Context, payload InputDataPayload) return nil } + +func (r *Router) ProcessContractCreation(ctx context.Context, payload ContractCreationPayload) error { + return r.contractCreationHandler(ctx, payload, r.callbackFn) +}