feat: handle contract creation (#43)

* feat: add contract creation handler

* fix: process contract creations

* fix: redis keys name
This commit is contained in:
Mohamed Sohail 2024-10-07 15:12:58 +03:00 committed by GitHub
parent 4b2ad3daf9
commit 05d142664d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 124 additions and 15 deletions

View File

@ -230,12 +230,12 @@ func bootstrapCache() error {
}
for _, address := range ko.MustStrings("bootstrap.watchlist") {
if err := cache.Add(ctx, address); err != nil {
if err := cache.Add(ctx, ethutils.HexToAddress(address).Hex()); err != nil {
return err
}
}
for _, address := range ko.MustStrings("bootstrap.blacklist") {
if err := cache.Remove(ctx, address); err != nil {
if err := cache.Remove(ctx, ethutils.HexToAddress(address).Hex()); err != nil {
return err
}
}

View File

@ -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))

View File

@ -40,8 +40,8 @@ func (c *redisCache) Remove(ctx context.Context, key string) error {
return c.client.Do(ctx, cmd).Error()
}
func (c *redisCache) Exists(ctx context.Context, key ...string) (bool, error) {
cmd := c.client.B().Exists().Key(key...).Build()
func (c *redisCache) Exists(ctx context.Context, keys ...string) (bool, error) {
cmd := c.client.B().Exists().Key(keys...).Build()
res, err := c.client.Do(ctx, cmd).AsBool()
if err != nil {
return false, err

View File

@ -0,0 +1,28 @@
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,
TxType: contractCreationEventName,
Payload: map[string]any{
"from": ccp.From,
},
}
return c(ctx, contractCreationEvent)
}
}

View File

@ -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,13 +72,72 @@ func (p *Processor) ProcessBlock(ctx context.Context, blockNumber uint64) error
}
}
}
} else {
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 err := p.router.ProcessContractCreation(
ctx,
router.ContractCreationPayload{
From: from.Hex(),
Block: blockNumber,
ContractAddress: receipt.ContractAddress.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 tx.To() != nil {
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: receipt.ContractAddress.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

View File

@ -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)
}