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

     1  package ante
     2  
     3  import (
     4  	"math/big"
     5  
     6  	"github.com/ethereum/go-ethereum/common"
     7  	ethcore "github.com/ethereum/go-ethereum/core"
     8  	ethtypes "github.com/ethereum/go-ethereum/core/types"
     9  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    10  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    11  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    12  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/types"
    13  	evmtypes "github.com/fibonacci-chain/fbc/x/evm/types"
    14  )
    15  
    16  // EthGasConsumeDecorator validates enough intrinsic gas for the transaction and
    17  // gas consumption.
    18  type EthGasConsumeDecorator struct {
    19  	ak        auth.AccountKeeper
    20  	sk        types.SupplyKeeper
    21  	evmKeeper EVMKeeper
    22  }
    23  
    24  // NewEthGasConsumeDecorator creates a new EthGasConsumeDecorator
    25  func NewEthGasConsumeDecorator(ak auth.AccountKeeper, sk types.SupplyKeeper, ek EVMKeeper) EthGasConsumeDecorator {
    26  	return EthGasConsumeDecorator{
    27  		ak:        ak,
    28  		sk:        sk,
    29  		evmKeeper: ek,
    30  	}
    31  }
    32  
    33  // AnteHandle validates that the Ethereum tx message has enough to cover intrinsic gas
    34  // (during CheckTx only) and that the sender has enough balance to pay for the gas cost.
    35  //
    36  // Intrinsic gas for a transaction is the amount of gas
    37  // that the transaction uses before the transaction is executed. The gas is a
    38  // constant value of 21000 plus any cost inccured by additional bytes of data
    39  // supplied with the transaction.
    40  func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
    41  	// simulate means 'eth_call' or 'eth_estimateGas', when it means 'eth_estimateGas' we can not 'VerifySig'.so skip here
    42  	if simulate {
    43  		return next(ctx, tx, simulate)
    44  	}
    45  	pinAnte(ctx.AnteTracer(), "EthGasConsumeDecorator")
    46  
    47  	msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
    48  	if !ok {
    49  		return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
    50  	}
    51  
    52  	address := msgEthTx.AccountAddress()
    53  	if address.Empty() {
    54  		panic("sender address cannot be empty")
    55  	}
    56  
    57  	// fetch sender account from signature
    58  	senderAcc, err := auth.GetSignerAcc(ctx, egcd.ak, address)
    59  	if err != nil {
    60  		return ctx, err
    61  	}
    62  
    63  	if senderAcc == nil {
    64  		return ctx, sdkerrors.Wrapf(
    65  			sdkerrors.ErrUnknownAddress,
    66  			"sender account %s (%s) is nil", common.BytesToAddress(address.Bytes()), address,
    67  		)
    68  	}
    69  
    70  	gasLimit := msgEthTx.GetGas()
    71  	gas, err := ethcore.IntrinsicGas(msgEthTx.Data.Payload, []ethtypes.AccessTuple{}, msgEthTx.To() == nil, true, false)
    72  	if err != nil {
    73  		return ctx, sdkerrors.Wrap(err, "failed to compute intrinsic gas cost")
    74  	}
    75  
    76  	// intrinsic gas verification during CheckTx
    77  	if ctx.IsCheckTx() && gasLimit < gas {
    78  		return ctx, sdkerrors.Wrapf(sdkerrors.ErrOutOfGas, "intrinsic gas too low: %d < %d", gasLimit, gas)
    79  	}
    80  
    81  	// Charge sender for gas up to limit
    82  	if gasLimit != 0 {
    83  		// Cost calculates the fees paid to validators based on gas limit and price
    84  		cost := new(big.Int).Mul(msgEthTx.Data.Price, new(big.Int).SetUint64(gasLimit))
    85  
    86  		evmDenom := sdk.DefaultBondDenom
    87  
    88  		feeAmt := sdk.NewCoins(
    89  			sdk.NewCoin(evmDenom, sdk.NewDecFromBigIntWithPrec(cost, sdk.Precision)), // int2dec
    90  		)
    91  
    92  		err = auth.DeductFees(egcd.sk, ctx, senderAcc, feeAmt)
    93  		if err != nil {
    94  			return ctx, err
    95  		}
    96  	}
    97  
    98  	// Set gas meter after ante handler to ignore gaskv costs
    99  	auth.SetGasMeter(simulate, &ctx, gasLimit)
   100  	return next(ctx, tx, simulate)
   101  }