Gas and fees
Users need to pay fees to submit transactions on the Daodst network. Since fees are handled differently in Ethereum and Cosmos, it is important to understand how the Daodst blockchain implements Ethereum-type fee calculations that are compatible with the Cosmos SDK.
Thus, this overview explains the basics of gas calculations, how fees are provided for transactions, and how Ethereum-style fee calculations use the fee market (EIP1559) to prioritize transactions.
Also note that fees paid for interacting with smart contracts on Daodst can earn revenue for smart contract deployers. For information on this, go to develop.
Prerequisites to read
Base
Why is there a transaction fee?
If anyone could submit transactions to the network for free, the network could be overwhelmed by a small number of participants sending fraudulent transactions to clog the network and make it non-functional.
The solution to this problem is a concept called gas
, which is the resource consumed throughout the execution of a transaction.
In practice, each step of code execution consumes a small amount of gas, effectively charging validator resource usage and preventing malicious actors from disrupting the network at will.
What is Gas?
In general, gas is a unit of measure for the computational intensity of a particular transaction — in other words, how much work is required to evaluate and execute it.
Complex multi-step transactions, such as a Cosmos transaction that delegates to a dozen validators, require more gas than simple single-step transactions (such as a Cosmos transaction that sends tokens to another address).
When referring to a transaction, gas
refers to the total amount of gas required for the transaction.
For example, a transaction may require 300,000 units of gas to execute.
Think of gas as electricity (kWh) in a house or factory, or as fuel for a car.
The idea is that it costs some money to get somewhere.
More Gas introduction:
How to calculate Gas
In general, there is no way to know exactly how much gas a transaction will cost without simply running it.
Using the Cosmos SDK, this can be done with Simulating a Tx.
Otherwise, there are ways to estimate the gas a transaction will require based on details of the transaction fields and data.
For example, in the case of the EVM, each bytecode operation has a corresponding amount of gas.
More about Gas calculation:
The relationship between Gas and handling fee?
Gas refers to the computational work required to perform it, while the fee refers to the amount of tokens you actually spend to execute the transaction.
They are derived using the following formulas:
Total Fees = Gas * Gas Price (the price per unit of gas)
If gas
is in kWh, then "gas price" will be the rate determined by your energy supplier in USD/kWh, and fees
will be your bill.
Like electricity, gas prices can fluctuate on a given day, depending on network traffic.
More about Gas and Fees:
How does Cosmos handle transaction fees?
Gas fees in Cosmos are relatively simple. As a user, you specify two fields:
- Corresponding to
GasLimit
of the execution gas limit, defined asGasWanted
- One of
Fees
orGasPrice
, which will be used to specify or calculate the transaction fee
The node will fully consume the provided fee and then start executing the transaction.
If the GasLimit
is found to be insufficient during execution, the transaction will fail and any changes will be rolled back, the provided fee will not be refunded.
Validators of Cosmos SDK-based chains can specify a "minimum gas price" that they will enforce when selecting transactions to include in a block.
As a result, transactions with insufficient fees will experience delays or fail outright.
At the beginning of each block, the previous block's fees are distributed to validators and delegators, after which they can be withdrawn and spent.
How to handle fees on Ethereum?
Ethereum fees include multiple implementations introduced over time.
Initially, the user will specify the GasPrice
and GasLimit
in the transaction - much like a Cosmos SDK transaction.
Block proposers will receive the full gas fee from each transaction in the block, and they will choose which transactions to include accordingly.
With the proposal EIP-1559 and the London hard fork, the gas calculation has changed.
The above GasPrice
is now split into two separate parts: BaseFee
and PriorityFee
.
BaseFee
is automatically calculated based on the block size and will be destroyed once the block is mined.
PriorityFee
is given to the proposer and represents a tip, or incentive for the proposer to include the transaction in a block.
Gas Price = Base Fee + Priority Fee
In a transaction, in addition to specifying a gas_limit
as before, the user can specify a max_fee_per_gas
corresponding to the total GasPrice
and a max_priority_fee_per_gas
corresponding to the maximum PriorityFee
.
All excess gas not required for execution is returned to the user.
More about Ethereum fees:
Implementation
How to deal with Gas and fees on Daodst?
Fundamentally, Daodst is a Cosmos SDK chain that enables EVM compatibility as part of a Cosmos SDK module. Due to this architecture, all EVM transactions are ultimately encoded as Cosmos SDK transactions and update the state managed by the Cosmos SDK. Since all transactions are represented as Cosmos SDK transactions, transaction fees can be at different execution layers.
In fact, processing fees include standard Cosmos SDK logic, some Ethereum logic, and customDaodst logic. In most cases, fees are collected by the fee_collector
module and then paid to validators and delegators. Some key differences are as follows:
1.Fee Market Module
To support EIP-1559 gas and fee calculations on Daodst's EVM layer, Daodst tracks the gas supplied for each block and uses it to calculate the base fee for future EVM transactions, enabling EIP-specified EVM dynamic fees and transaction prioritization Level -1559.
For EVM transactions, each node bypasses its local min-gas-prices
configuration and instead applies EIP-1559 fee logic - the gas price must simply be greater than the global min-gas-price
and the block's BaseFee
, the remainder is considered the priority tip.
This allows validators to calculate Ethereum fees without applying the Cosmos SDK fee logic.
Unlike Ethereum, the BaseFee
on Daodst will not be destroyed, but distributed to validators and delegators
Additionally, BaseFee
is 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).
2. EVM Gas refund
Daodst refunds a small portion (at least 50% by default) of unspent gas for EVM transactions to approximate the current behavior on Ethereum.
3. Income module
Daodst develops the revenue module as a way to reward developers for creating useful dApps - any contract that registers with the Daodst revenue module rewards the contract developer with a small portion of transaction fees (currently 95% ). Validators and delegators earn the remainder.
Detailed schedule
-
The node executes the previous block and runs the
EndBlock
hook * As part of this hook, the FeeMarket (EIP-1559) module tracks the totalTransientGasWanted
from transactions on that block. This will be used for theBaseFee
of the next block. -
Nodes receive transactions for subsequent blocks and gossip about these transactions to their peers *These can be sorted and prioritized by included fee price (EVM transactions using the EIP-1559 fee priority mechanism will be included in the next block
-
The node runs the
BeginBlock
* FeeMarket module for the subsequent block to calculate theBaseFee
to apply to this block using the totalGasWanted
from the previous block. -
Distribution module distributes The previous block's fee rewards to validators and delegators
-
For each valid transaction to be included in this block, the node does the following:
** They run an AnteHandler
corresponding to the transaction type **.
This process:
- Perform basic transaction validation
- Verify that the provided fee is greater than the global and local minimum validator values and greater than the computed
BaseFee
- (For Ethereum transactions) Preempting EVM transaction consumption gas
- Deduct the user's transaction fee and transfer it to the
fee_collector
module - Increase the
TransientGasWanted
in the current block to calculate theBaseFee
of the next block
Then, for standard Cosmos transactions, nodes
- Execute transactions and update status
- Transaction consumes gas
For Ethereum transactions, nodes:
- Execute transactions and update status
- Calculates the gas used and compares it to the supplied gas, then refunds the remainder of the specified portion
-
If the transaction interacts with a registered smart contract, a small portion of the fee used as revenue is sent to the contract developer as part of the revenue module
-
The node runs
EndBlock
for this block and stores theGasWanted
of the block
Detailed practice
Cosmos Gas
In the Cosmos SDK, gas is mainly tracked in GasMeter
and BlockGasMeter
:
GasMeter
: Tracks gas consumed during executions that lead to state transitions. It is reset every time a transaction is executed.BlockGasMeter
: Tracks gas consumed in a block and enforces gas not exceeding a predefined limit. This limit is defined in the Tendermint consensus parameters and can be changed through governance parameter change proposals.
Since gas is priced in bytes, the same interaction with larger parameter values will cost more gas than smaller parameter values (unlike Ethereum's uint256
values, Cosmos SDK values use Big.Int types, which are dynamically resized).
More information on gas as part of the Cosmos SDK can be found here.
Match EVM Gas consumption
Daodst is an EVM compatible chain that supports Ethereum Web3 tools. For this reason, gas consumption must be comparable to other EVMs, most importantly Ethereum.
The main difference between EVM and Cosmos state transitions is that the EVM uses a gas table for each opcode, Instead, Cosmos uses GasConfig
to charge gas for each CRUD operation by setting a fixed per-byte cost for accessing the database.
To match the gas consumed by the EVM, the gas consumption logic in the SDK is ignored, instead the gas consumed is calculated by subtracting the state transition remaining gas plus the refund from the gas limit defined on the message.
To ignore the SDK's gas consumption, we reset the transaction GasMeter
count to 0 and manually set it to the gasUsed
value calculated by the EVM module at the end of execution.
AnteHandler
The Cosmos SDK AnteHandler
performs basic checks before transaction execution.
These checks are typically signature verification, transaction field verification, transaction fees, etc.
Regarding gas consumption and fees, AnteHandler
checks that the user has enough balance to cover the tx cost (amount plus the fee), and checks that the gas limit defined in the message is greater than or equal to the computed intrinsic gas message.
Gas Return
In EVM, gas can be specified before execution. The full amount of gas specified is consumed at the start of execution (during the AnteHandler
step), if any gas remains after execution, the remaining gas will be refunded to the user.
Additionally, the EVM can also define gas to be returned to the user, but these will be limited to a fraction of the gas used, depending on the fork/version used.
Zero Fee Transactions
In Cosmos, AnteHandler
does not enforce minimum gas prices, because min-gas-prices
are checked against local nodes/validators.
In other words, the minimum fee accepted is determined by the validators of the network, and each validator can specify a different minimum value for their fee.
This may allow end users to submit 0-fee transactions if at least one validator is willing to include a 0
gas price transaction in their proposed block.
For the same reason, in Daodst it is possible to send transactions with a 0
fee for transaction types other than those defined by the evm
module.
EVM module transactions cannot have a "0" fee because the EVM itself requires gas.
This check is done by the EVM transaction stateless validation (i.e. ValidateBasic
) function as well as a custom AnteHandler
defined by Daodst.
Gas Estimate
Ethereum provides a JSON-RPC endpoint eth_estimateGas
to help users set the correct gas limit in their transactions.
Therefore, a specific query API EstimateGas
is implemented in Daodst. It will apply the transaction against the current block/state and perform a binary search to find the best gas value to return to the user (the same transaction will be applied over and over until we find the minimum gas required before failing).
The reason we need to use binary search is that the gas required by the transaction may 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 cached context will be used throughout execution to avoid persisting changes in state.
For Cosmos Tx, developers can use Cosmos SDK's transaction simulation to create accurate estimates.
Use Daodst CLI to process Gas and transaction fees
Users should consider the available options when broadcasting transactions using the Daodst CLI client. There are three flags to consider when sending a transaction to the network:
--fees
: Fees to pay with the transaction; eg: 10dst. Defaults to required fee.--gas
: Gas limit to set per transaction; default is 200000.--gas-prices
: gas prices to determine transaction fees (e.g. 10dst).
However, not all of these need to be defined in every transaction. The correct combination is:
--fees=auto
: Automatically estimate fees and gas (same behavior as --gas=auto ). An error is thrown if any other fee-related flags are used (e.g.--gas-prices
,--fees
)--gas=auto
: Same behavior as--fees=auto
. An error is thrown if any other fee-related flags are used (e.g.--gas-prices
,--fees
)--gas={int}
: use the specified amount of gas and the transaction fee--fees={int}{denom}
: use the specified fee for tx. Use the gas default (200000) for tx.--fees={int}{denom} --gas={int}
: Use the specified gas and fee. Computes the gas-price using the provided parameters--gas-prices={int}{denom}
: Use provided gas prices and default gas amount (200000)--gas-prices={int}{denom} --gas={int}
: Use the gas specified for tx and calculate the price with the corresponding parameters.
Readers should note that the first two options provide a more user-friendly experience for new users, while the latter are intended for more advanced users who want more control over these parameters.
The team introduced the 'auto' flag option, which automatically calculates the gas and fees required to execute a transaction. In this way, new users or developers can execute transactions without defining specific gas and fee values.
Using the auto
flag may sometimes not estimate the correct gas and fees based on network traffic.
To overcome this, you can use a higher value for the --gas-adjustment
flag.
By default it is set to 1.2
.
When the estimate is insufficient, retry a higher gas adjustment, such as --gas-adjustment 1.3
.
The --gas-prices
and --fees
flags cannot be combined.
If so, the user will receive an error message stating that fees and gas prices cannot be provided at the same time.
Keep in mind that the above combo may fail if the fee or gas amount offered is insufficient. If this is the case, the CLI will return an error message with the specific reason. For example:
raw_log: 'out of gas in location: submit proposal; gasWanted: 200000, gasUsed: 263940.
Please retry with a gas (--gas flag) amount higher than gasUsed: out of gas'