laconicd-deprecated/x/evm/keeper/utils.go

125 lines
3.5 KiB
Go
Raw Normal View History

package keeper
import (
2022-10-10 10:38:33 +00:00
"math"
"math/big"
2022-10-10 10:38:33 +00:00
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
2022-10-10 10:38:33 +00:00
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
evmtypes "github.com/cerc-io/laconicd/x/evm/types"
"github.com/ethereum/go-ethereum/core"
ethtypes "github.com/ethereum/go-ethereum/core/types"
)
// DeductTxCostsFromUserBalance it calculates the tx costs and deducts the fees
2022-10-10 10:38:33 +00:00
// returns (effectiveFee, priority, error)
func (k Keeper) DeductTxCostsFromUserBalance(
ctx sdk.Context,
msgEthTx evmtypes.MsgEthereumTx,
txData evmtypes.TxData,
denom string,
homestead, istanbul, london bool,
2022-10-10 10:38:33 +00:00
) (fees sdk.Coins, priority int64, err error) {
isContractCreation := txData.GetTo() == nil
// fetch sender account from signature
2022-10-10 10:38:33 +00:00
signerAcc, err := authante.GetSignerAcc(ctx, k.accountKeeper, msgEthTx.GetFrom())
2022-04-26 10:39:18 +00:00
if err != nil {
2022-10-10 10:38:33 +00:00
return nil, 0, sdkerrors.Wrapf(err, "account not found for sender %s", msgEthTx.From)
2022-04-26 10:39:18 +00:00
}
gasLimit := txData.GetGas()
var accessList ethtypes.AccessList
if txData.GetAccessList() != nil {
accessList = txData.GetAccessList()
}
intrinsicGas, err := core.IntrinsicGas(txData.GetData(), accessList, isContractCreation, homestead, istanbul)
if err != nil {
2022-10-10 10:38:33 +00:00
return nil, 0, sdkerrors.Wrapf(
err,
"failed to retrieve intrinsic gas, contract creation = %t; homestead = %t, istanbul = %t",
isContractCreation, homestead, istanbul,
)
}
// intrinsic gas verification during CheckTx
if ctx.IsCheckTx() && gasLimit < intrinsicGas {
2022-10-10 10:38:33 +00:00
return nil, 0, sdkerrors.Wrapf(
sdkerrors.ErrOutOfGas,
"gas limit too low: %d (gas limit) < %d (intrinsic gas)", gasLimit, intrinsicGas,
)
}
var feeAmt *big.Int
2022-10-10 10:38:33 +00:00
baseFee := k.getBaseFee(ctx, london)
if baseFee != nil && txData.GetGasFeeCap().Cmp(baseFee) < 0 {
return nil, 0, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee,
"the tx gasfeecap is lower than the tx baseFee: %s (gasfeecap), %s (basefee) ",
txData.GetGasFeeCap(),
baseFee)
}
2022-10-10 10:38:33 +00:00
feeAmt = txData.EffectiveFee(baseFee)
if feeAmt.Sign() == 0 {
// zero fee, no need to deduct
2022-10-10 10:38:33 +00:00
return sdk.Coins{}, 0, nil
}
2022-10-10 10:38:33 +00:00
fees = sdk.Coins{sdk.NewCoin(denom, sdkmath.NewIntFromBigInt(feeAmt))}
2022-04-26 10:39:18 +00:00
// deduct the full gas cost from the user balance
2022-10-10 10:38:33 +00:00
if err := authante.DeductFees(k.bankKeeper, ctx, signerAcc, fees); err != nil {
return nil, 0, sdkerrors.Wrapf(
2022-04-26 10:39:18 +00:00
err,
"failed to deduct full gas cost %s from the user %s balance",
fees, msgEthTx.From,
)
}
2022-10-10 10:38:33 +00:00
// calculate priority based on effective gas price
tipPrice := txData.EffectiveGasPrice(baseFee)
// if london hardfork is not enabled, tipPrice is the gasPrice
if baseFee != nil {
tipPrice = new(big.Int).Sub(tipPrice, baseFee)
}
priorityBig := new(big.Int).Quo(tipPrice, evmtypes.DefaultPriorityReduction.BigInt())
if !priorityBig.IsInt64() {
priority = math.MaxInt64
} else {
priority = priorityBig.Int64()
}
return fees, priority, nil
}
2021-09-21 10:29:59 +00:00
// CheckSenderBalance validates that the tx cost value is positive and that the
// sender has enough funds to pay for the fees and value of the transaction.
func CheckSenderBalance(
2022-10-10 10:38:33 +00:00
balance sdkmath.Int,
txData evmtypes.TxData,
) error {
cost := txData.Cost()
2021-09-21 10:29:59 +00:00
if cost.Sign() < 0 {
return sdkerrors.Wrapf(
sdkerrors.ErrInvalidCoins,
"tx cost (%s) is negative and invalid", cost,
)
2021-09-21 10:29:59 +00:00
}
if balance.IsNegative() || balance.BigInt().Cmp(cost) < 0 {
return sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds,
"sender balance < tx cost (%s < %s)", balance, txData.Cost(),
)
}
return nil
}