forked from cerc-io/laconicd-deprecated
e1560849dd
* Set priority for eth transactions Set the tx priority to the lowest priority in the messages. fix unit tests code cleanup and spec update spec fix go lint add priority integration test add python linter job add access list tx type fix gas limit remove ledger tag, so no need to replace hid dependency fix earlier check ibc-go v5.0.0-beta1 * fix pruned node integration test * Update x/feemarket/spec/09_antehandlers.md Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
127 lines
3.8 KiB
Go
127 lines
3.8 KiB
Go
package keeper
|
|
|
|
import (
|
|
"math"
|
|
"math/big"
|
|
|
|
sdkmath "cosmossdk.io/math"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
|
|
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
|
|
|
"github.com/ethereum/go-ethereum/core"
|
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
|
)
|
|
|
|
// DefaultPriorityReduction is the default amount of price values required for 1 unit of priority.
|
|
// Because priority is `int64` while price is `big.Int`, it's necessary to scale down the range to keep it more pratical.
|
|
// The default value is the same as the `sdk.DefaultPowerReduction`.
|
|
var DefaultPriorityReduction = sdk.DefaultPowerReduction
|
|
|
|
// DeductTxCostsFromUserBalance it calculates the tx costs and deducts the fees
|
|
// returns (effectiveFee, priority, error)
|
|
func (k Keeper) DeductTxCostsFromUserBalance(
|
|
ctx sdk.Context,
|
|
msgEthTx evmtypes.MsgEthereumTx,
|
|
txData evmtypes.TxData,
|
|
denom string,
|
|
homestead, istanbul, london bool,
|
|
) (fees sdk.Coins, priority int64, err error) {
|
|
isContractCreation := txData.GetTo() == nil
|
|
|
|
// fetch sender account from signature
|
|
signerAcc, err := authante.GetSignerAcc(ctx, k.accountKeeper, msgEthTx.GetFrom())
|
|
if err != nil {
|
|
return nil, 0, sdkerrors.Wrapf(err, "account not found for sender %s", msgEthTx.From)
|
|
}
|
|
|
|
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 {
|
|
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 {
|
|
return nil, 0, sdkerrors.Wrapf(
|
|
sdkerrors.ErrOutOfGas,
|
|
"gas limit too low: %d (gas limit) < %d (intrinsic gas)", gasLimit, intrinsicGas,
|
|
)
|
|
}
|
|
|
|
var feeAmt *big.Int
|
|
|
|
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)
|
|
}
|
|
|
|
feeAmt = txData.EffectiveFee(baseFee)
|
|
if feeAmt.Sign() == 0 {
|
|
// zero fee, no need to deduct
|
|
return sdk.Coins{}, 0, nil
|
|
}
|
|
|
|
fees = sdk.Coins{sdk.NewCoin(denom, sdkmath.NewIntFromBigInt(feeAmt))}
|
|
|
|
// deduct the full gas cost from the user balance
|
|
if err := authante.DeductFees(k.bankKeeper, ctx, signerAcc, fees); err != nil {
|
|
return nil, 0, sdkerrors.Wrapf(
|
|
err,
|
|
"failed to deduct full gas cost %s from the user %s balance",
|
|
fees, msgEthTx.From,
|
|
)
|
|
}
|
|
|
|
// 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, DefaultPriorityReduction.BigInt())
|
|
if !priorityBig.IsInt64() {
|
|
priority = math.MaxInt64
|
|
} else {
|
|
priority = priorityBig.Int64()
|
|
}
|
|
|
|
return fees, priority, nil
|
|
}
|
|
|
|
// 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(
|
|
balance sdkmath.Int,
|
|
txData evmtypes.TxData,
|
|
) error {
|
|
cost := txData.Cost()
|
|
|
|
if cost.Sign() < 0 {
|
|
return sdkerrors.Wrapf(
|
|
sdkerrors.ErrInvalidCoins,
|
|
"tx cost (%s) is negative and invalid", cost,
|
|
)
|
|
}
|
|
|
|
if balance.IsNegative() || balance.BigInt().Cmp(cost) < 0 {
|
|
return sdkerrors.Wrapf(
|
|
sdkerrors.ErrInsufficientFunds,
|
|
"sender balance < tx cost (%s < %s)", balance, txData.Cost(),
|
|
)
|
|
}
|
|
return nil
|
|
}
|