---
# System prepended metadata

title: EVM hooks router issue notes

---

EVM hooks router issue notes
===

## Research issue [#1244](https://github.com/evmos/ethermint/issues/1244)


ideas:
register module (evmos) for the hook (defined in ethermint) -> register handler (evmos)

agregar logica -> segun tipo de mensaje/evento/condicion, qué handler se ejecuta -> una func CheckEvent (o algo asi) al Handler y devuelve si se tiene que ejecutar o no --> entonces solo ejecuto los handlers que necesito

este caso es inverso al uso del Router -> en el router, éste se llama desde el modulo que lo registra...
En el caso de el evmHook, muchos modulos se registran en el router del mismo modulo y se llama alli


### Questions

Cual es la funcionalidad deseada??


### Ideas

Dynamically add/remove hooks depending on the tx type, using a middleware


### EVM hooks (PostTxProcessing) logic

#### ERC-20 - mint/burn ERC-20 tokens
* iterates receipt.Logs _question: only way to do it?_
* check for **ERC20EventTransfer**
* check that contract is **registered pair**
* check if tokens are sent to ERC-20 module address
* correspondingly mint or burn coins
* transfer tokens from module to recipient account

_this runs in every tx_
_question: this case will be always a tx to a contract, right?? so we could make the checks (e.g.: if registered) based on the msg data instead of the receipt logs?_

#### Revenue - send fees to withdrawer
* check if tx **to a contract**
* check if contract is **registered** to receive fees
* define withdrawer addr
* calculate the fees for the withdrawer
* send conis from module to the withdrawer

#### Incentives - interaction with incentivezed contract: add gas used
* check if tx **to contract**
* check if contract is **registered** for incentives
* check receiver is EOA
* Add gas used to 
    * incentivized contract
    * participant

#### Claims - claimable amount for user's record evm action is redeemed
* check if sender has claimsRecord
* claim coins for ActionEVM

### Possible implementation

Based on this logic, the router would be something in the terms of:

```
    // claims hook runs for all txs
    hooks := []hooks{claimsHook}
    
    // register hooks before returning
    defer registerEVMHooks(hooks)

    // with current logic this is checked 3 times
    // check msg.To() is an addr
    contract := msg.To()
	if contract == nil {
		return
	}
    
    // check which hook should run    
    id := k.GetERC20Map(ctx, contract)
    // other ERC-20 checks...
    
    if isErc20 {
        hooks = append(hooks, erc20Hook)
    }
    
    revenue, isRevenue := k.GetRevenue(ctx, *contract)
    if isRevenue {
        hooks = append(hooks, revenueHook)
    }
    
    isIncentive := k.IsIncentiveRegistered(ctx, *contract)
    if isIncentive {
        hooks = append(hooks, incentivesHook)
    }
    

```

**Idea**
To avoid checking many times if msg is for contract, we need to consolidate the basic checks in one place (e.g. if tx is to a contract). 

Ideas:
* define a hook type (in Ethermint) for this use case (tx to contract) 
* Another is to dynamically change the registered hooks (in Evmos)

Then do the check one time and run these hooks if fulfill the condition.

__router pattern con__: Using the router pattern will duplicate logic too, cause each handler for each case will have the same check as it is now.

Logic will change in the `hooks.go`

```
// PostTxProcessing delegate the call to underlying hooks
func (mh MultiEvmHooks) PostTxProcessing(ctx sdk.Context, msg core.Message, receipt *ethtypes.Receipt) error {
        if msg.To() == nil {
            return nil
        }
	for i := range mh {
		if err := mh[i].PostTxProcessing(ctx, msg, receipt); err != nil {
			return sdkerrors.Wrapf(err, "EVM hook %T failed", mh[i])
		}
	}
	return nil
}
```

Other option is to add a check in the `state_transition.go` for the new types of hooks, and only run these if it is a tx to contract

Other option is to add a Check fn in the hooks to run before calling the main fn. Example

```
// this check should be added where the hook is called to avoid repetition
if msg.To() != nil {
    PostTxToContractProcessing(ctx, msg, receipt)
}

// PostTxToContractProcessing delegate the call to underlying hooks
func (mh MultiEvmHooks) PostTxToContractProcessing(ctx sdk.Context, msg core.Message, receipt *ethtypes.Receipt) error {             
	for i := range mh {
            if ok := mh[i].Check(ctx, msg); !ok {
                return nil
            }
            if err := mh[i].PostTxToContractProcessing(ctx, msg, receipt); err != nil {
                return sdkerrors.Wrapf(err, "EVM hook %T failed", mh[i])
            }
	}
	return nil
}
```

__Pros of adding the Check__: it is cleaner to understand that the error occurred while processing the tx

__Cons of adding the Check__: does not make much difference with how is implemented now, not sure if it is worth the effort.

