github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/app/ante/AccountVerificationDecorator.go (about)

     1  package ante
     2  
     3  import (
     4  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     5  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
     6  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
     7  	evmtypes "github.com/fibonacci-chain/fbc/x/evm/types"
     8  )
     9  
    10  // AccountVerificationDecorator validates an account balance checks
    11  type AccountVerificationDecorator struct {
    12  	ak        auth.AccountKeeper
    13  	evmKeeper EVMKeeper
    14  }
    15  
    16  // NewAccountVerificationDecorator creates a new AccountVerificationDecorator
    17  func NewAccountVerificationDecorator(ak auth.AccountKeeper, ek EVMKeeper) AccountVerificationDecorator {
    18  	return AccountVerificationDecorator{
    19  		ak:        ak,
    20  		evmKeeper: ek,
    21  	}
    22  }
    23  
    24  // AnteHandle validates the signature and returns sender address
    25  func (avd AccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
    26  	if !ctx.IsCheckTx() || simulate {
    27  		return next(ctx, tx, simulate)
    28  	}
    29  
    30  	msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
    31  	if !ok {
    32  		return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
    33  	}
    34  
    35  	address := msgEthTx.AccountAddress()
    36  	if address.Empty() {
    37  		panic("sender address cannot be empty")
    38  	}
    39  
    40  	acc := avd.ak.GetAccount(ctx, address)
    41  	if acc == nil {
    42  		acc = avd.ak.NewAccountWithAddress(ctx, address)
    43  		avd.ak.SetAccount(ctx, acc)
    44  	}
    45  
    46  	// on InitChain make sure account number == 0
    47  	if ctx.BlockHeight() == 0 && acc.GetAccountNumber() != 0 {
    48  		return ctx, sdkerrors.Wrapf(
    49  			sdkerrors.ErrInvalidSequence,
    50  			"invalid account number for height zero (got %d)", acc.GetAccountNumber(),
    51  		)
    52  	}
    53  
    54  	evmDenom := sdk.DefaultBondDenom
    55  
    56  	// validate sender has enough funds to pay for gas cost
    57  	balance := acc.GetCoins().AmountOf(evmDenom)
    58  	if balance.BigInt().Cmp(msgEthTx.Cost()) < 0 {
    59  		return ctx, sdkerrors.Wrapf(
    60  			sdkerrors.ErrInsufficientFunds,
    61  			"sender balance < tx gas cost (%s%s < %s%s)", balance.String(), evmDenom, sdk.NewDecFromBigIntWithPrec(msgEthTx.Cost(), sdk.Precision).String(), evmDenom,
    62  		)
    63  	}
    64  
    65  	return next(ctx, tx, simulate)
    66  }