Users need to pay a fee to submit transactions on a Cosmos EVM-based blockchain. As fees are handled differently on Ethereum and Cosmos, it is important to understand how a Cosmos EVM blockchain implements an Ethereum-type fee calculation, that is compatible with the Cosmos SDK.
GasLimit
corresponding to an upper bound on execution gas, defined as GasWanted
Fees
or GasPrice
, which will be used to specify or calculate the transaction feesGasLimit
is found to be insufficient during execution, the transaction will fail and roll back any changes made, without refunding the fees provided.
Validators for Cosmos SDK-based chains can specify their min-gas-prices
that they will enforce when selecting transactions to include in blocks. Thus, transactions with insufficient fees will encounter delays or fail outright.
At the beginning of each block, fees from the previous block are allocated to validators and delegators, after which they can be withdrawn and spent.
GasPrice
and GasLimit
within a transaction—much like a Cosmos SDK transaction. A block proposer would receive the entire gas fee from each transaction in the block, and they would select transactions to include accordingly.
With proposal EIP-1559 and the London Hard fork, gas calculation changed. The GasPrice
from above has now been split into two separate components: a BaseFee
and PriorityFee
. The BaseFee
is calculated automatically based on the block size and is burned once the block is mined. The PriorityFee
goes to the proposer and represents a tip, or an incentive for a proposer to include the transaction in a block.
max_fee_per_gas
corresponding to the total GasPrice
and a max_priority_fee_per_gas
corresponding to a maximum PriorityFee
, in addition to specifying the gas_limit
as before. All surplus gas that was not required for execution is refunded to the user.
More on Ethereum Fees:
fee_collector
module, then paid out to validators and delegators. A few key distinctions are as follows:
min-gas-prices
configuration, and instead applies EIP-1559 fee logic—the gas price simply must be greater than both the global min-gas-price
and the block’s BaseFee
, and the surplus is considered a priority tip. This allows validators to compute Ethereum fees without applying Cosmos SDK fee logic.
Unlike on Ethereum, the BaseFee
on a Cosmos EVM chain is not burned, and instead is distributed to validators and delegators by default, although this can be adjusted. Furthermore, the BaseFee
is lower-bounded by the global min-gas-price
(currently, the global min-gas-price
parameter is set to zero, although it can be updated via Governance).
EndBlock
hook
TransientGasWanted
from the transactions on this block. This will be used for the next block’s BaseFee
.BeginBlock
for the subsequent block
BaseFee
(code snippet) to be applied for this block using the total GasWanted
from the previous block.AnteHandler
corresponding to the transaction type. This process:
BaseFee
calculatedfee_collector
moduleTransientGasWanted
in the current block, to be used to calculate the next block’s BaseFee
EndBlock
for this block and store the block’s GasWanted
Gas
GasMeter
and the BlockGasMeter
:
GasMeter
: keeps track of the gas consumed during executions that lead to state transitions. It is reset on every transaction execution.BlockGasMeter
: keeps track of the gas consumed in a block and enforces that the gas does not go over a predefined limit. This limit is defined in the CometBFT consensus parameters and can be changed via governance parameter change proposals.uint256
values, Cosmos SDK numericals are represented using Big.Int types, which are dynamically sized).
More information regarding gas as part of the Cosmos SDK can be found here.
GasConfig
that charges gas for each CRUD operation by setting a flat and per-byte cost for accessing the database.
+++ https://github.com/cosmos/cosmos-sdk/blob/3fd376bd5659f076a4dc79b644573299fd1ec1bf/store/types/gas.go#L187-L196
In order to match the gas consumed by the EVM, the gas consumption logic from the SDK is ignored, and instead the gas consumed is calculated by subtracting the state transition leftover gas plus refund from the gas limit defined on the message.
To ignore the SDK gas consumption, we reset the transaction GasMeter
count to 0 and manually set it to the gasUsed
value computed by the EVM module at the end of the execution.
+++ https://github.com/cosmos/evm/blob/098da6d0cc0e0c4cefbddf632df1057383973e4a/x/evm/keeper/state_transition.go
AnteHandler
AnteHandler
performs basic checks prior to transaction execution. These checks are usually signature verification, transaction field validation, transaction fees, etc.
Regarding gas consumption and fees, the AnteHandler
checks that the user has enough balance to cover for the tx cost (amount plus fees) as well as checking that the gas limit defined in the message is greater or equal than the computed intrinsic gas for the message.
AnteHandler
step) and the remaining gas is refunded back to the user if any gas is left over after the execution. Additionally the EVM can also define gas to be refunded back to the user but those will be capped to a fraction of the used gas depending on the fork/version being used.
AnteHandler
as the min-gas-prices
is checked against the local node/validator. In other words, the minimum fees accepted are determined by the validators of the network, and each validator can specify a different minimum value for their fees. This potentially allows end users to submit 0 fee transactions if there is at least one single validator that is willing to include transactions with 0
gas price in their blocks proposed.
For this same reason, in the Cosmos EVM it is possible to send transactions with 0
fees for transaction types other than the ones defined by the evm
module. EVM module transactions cannot have 0
fees as gas is required inherently by the EVM. This check is done by the EVM transactions stateless validation (i.e ValidateBasic
) function as well as on the custom AnteHandler
defined by Cosmos EVM.
eth_estimateGas
to help users set up a correct gas limit in their transactions.
For that reason, a specific query API EstimateGas
is implemented in the Cosmos EVM. It will apply the transaction against the current block/state and perform a binary search in order to find the optimal gas value to return to the user (the same transaction will be applied over and over until we find the minimum gas needed before it fails). The reason we need to use a binary search is that the gas required for the transaction might be higher than the value returned by the EVM after applying the transaction, so we need to try until we find the optimal value.
A cache context will be used during the whole execution to avoid changes be persisted in the state.
+++ https://github.com/cosmos/evm/blob/098da6d0cc0e0c4cefbddf632df1057383973e4a/x/evm/keeper/grpc_query.go
For Cosmos Tx’s, developers can use Cosmos SDK’s transaction simulation to create an accurate estimate.
Tips
as a solution to this issue; a user can cover fees using a different token—in this case, tokens from Chain A.
To cover transaction fees using a tip, this user can sign a transaction with a tip and no fees, then send the transaction to a fee relayer. The fee relayer will then cover the fee in the native currency, and receive the tip in payment, behaving as an intermediary exchange.
--fees
: fees to pay along with transaction. Defaults to the required fees.--gas
: the gas limit to set per-transaction; the default value is 200000.--gas-prices
: gas prices to determine the transaction fee.--fees=auto
: estimates fees and gas automatically (same behavior as --gas=auto
). Throws an error if using any other fees-related flag (e.i, --gas-prices
, --fees
)--gas=auto
: same behavior as --fees=auto
. Throws an error if using any other fees-related flag (e.i, --gas-prices
, --fees
)--gas={int}
: uses the specified gas amount and the required fees for the transaction--fees={int}{denom}
: uses the specified fees for the tx. Uses gas default value (200000) for the tx.--fees={int}{denom} --gas={int}
: uses specified gas and fees. Calculates gas-prices with the provided params--gas-prices={int}{denom}
: uses the provided gas price and the default gas amount (200000)--gas-prices={int}{denom} --gas={int}
: uses the gas specified on for the tx and calculates the fee with the corresponding parameters.auto
flag option that calculates automatically the gas and fees required to execute a transaction. In this way, new users or developers can perform transactions without the hustle of defining specific gas and fees values.
Using the auto
flag sometimes may fail on estimating the right gas and fees based on network traffic. To overcome this, you can use a higher value for the --gas-adjustment
flag. By default, this is set to 1.2
. When the estimated values are insufficient, retry with a higher gas adjustment, for example, --gas-adjustment 1.3
.
It is not possible to use the --gas-prices
and --fees
flags combined. If so, the user will get an error stating that cannot provide both fees and gas prices.
Keep in mind that the above combinations may fail if the provided fees or gas amount is insufficient. If that is the case, the CLI will return an error message with the specific reason. For example: