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 }