Gas and Fees
Gas is used by Arbitrum to track the cost of execution on a Nitro chain. It works the same as Ethereum gas, in the sense that every EVM instruction costs the same amount of gas that it would on Ethereum.
There are two parties a user pays when submitting a tx:
- the poster, if reimbursable, for the parent chain resources such as the parent chain calldata needed to post the tx
- the network fee account for the child chain resources, which include the computation, storage, and other burdens child chain nodes must bear to service the tx
The parent chain component is the product of the Transaction's estimated contribution to its Batch's size — computed using Brotli on the transaction by itself — and the child chain's view of the parent chain data price, a value which dynamically adjusts over time to ensure the batch-poster is ultimately fairly compensated.
The child chain component consists of the traditional fees Geth would pay to stakers in a vanilla parent chain chain, such as the computation and storage charges applying the State Transition Function entails. ArbOS charges additional fees for executing its child chain-specific precompiles, whose fees are dynamically priced according to the specific resources used while executing the call.
The following sections will detail how to calculate parent and child chain fees. If you do not need precise calculations or a technical understanding, skip to the next section, Parent chain to child chain messaging.
Parent chain gas pricing
ArbOS dynamically prices the parent chain gas, with the price adjusting to ensure that the amount collected in the parent chain gas fees is as close as possible to the costs that must be covered, over time.
Parent chain costs
There are two types of parent chain costs: batch posting costs, and rewards.
Batch posting costs reflect the actual cost a batch poster pays to post batch data on the parent chain. Whenever a batch is posted, the parent chain contract that records the batch will send a special "batch posting report" message to child chain ArbOS, reporting who paid for the batch and what the parent chain basefee was at the time. This message is placed in the chain's Delayed Inbox, so it will be delivered to child chain ArbOS after some delay.
When a batch posting report message arrives to the child chain, ArbOS computes the cost of the referenced batch by multiplying the reported basefee by the batch's data cost. (ArbOS retrieves the batch's data from its inbox state, and computes the parent chain gas that the batch would have used by counting the number of zero bytes and non-zero bytes in the batch.) The resulting cost is recorded by the pricer as funds due to the party who is reported to have submitted the batch.
The second type of parent chain cost is an optional (per chain) per-unit reward for handling transaction calldata. In general the reward might be paid to the Sequencer, or to members of the Data Availability Committee in an AnyTrust chain, or to anyone else who incurs per-calldata-byte costs on behalf of the chain. The reward is a fixed number of wei per data unit, and is paid to a single address.
The parent chain pricer keeps track of the funds due to the reward address, based on the number of data units handled so far. This amount is updated whenever a batch posting report arrives at the child chain.
Parent chain calldata fees
The parent chain calldata fees exist because the Sequencer, or the batch poster which posts the Sequencer's transaction batches on Ethereum, incurs costs in the parent chain gas to post transactions on Ethereum as calldata. Funds collected in the parent chain calldata fees are credited to the batch poster to cover its costs.
Every transaction that comes in through the Sequencer will pay a parent chain calldata fee. Transactions that come in through the delayed inbox do not pay this fee because they don't add to batch posting costs--but these transactions pay gas fees to Ethereum when they are put into the delayed inbox.
The parent chain pricing algorithm assigns a parent chain calldata fee to each Sequencer transaction. First, it computes the transaction's size, which is an estimate of how many bytes the transaction will add to the compressed batch it is in; the formula for this includes an estimate of how compressible the transaction is. Second, it multiplies the computed size estimate by the current price per estimated byte, to determine the transaction's parent chain calldata wei, in wei. Finally, it divides this cost by the current child chain basefee to translate the fee into the child chain gas units. The result is reported as the "poster fee" for the transaction.
The price per estimated byte is set by a dynamic algorithm that compares the total parent chain calldata fees collected to the total fees actually paid by batch posters, and tries to bring the two as close to equality as possible. If the batch posters' costs have been less than fee receipts, the price will increase, and if batch poster costs have exceeded fee receipts, the price will decrease.
Parent chain fee collection
A transaction is charged for the parent chain gas if and only if it arrived as part of a sequencer batch. This means that someone would have paid for the parent chain gas to post the transaction on the parent chain chain.
The estimated cost of posting a transaction on the parent chain is the product of the transaction's estimated size, and the current parent chain Gas Basefee. This estimated cost is divided by the current child chain gas basefee to obtain the amount of child chain gas that corresponds to the parent chain operation (more information about this can be found in this article).
The estimated size is measured in the parent chain gas and is calculated as follows: first, compress the transaction's data using the brotli-zero algorithm, then multiply the size of the result by 16. (16 is because the parent chain charges 16 gas per byte. The parent chain charges less for bytes that are zero, but that doesn't make sense here.) Brotli-zero is used in order to reward users for posting transactions that are compressible. Ideally we would like to reward for posting transactions that contribute to the compressibility (using the brotli compressor) of the entire batch, but that is a difficult notion to define and in any case would be too expensive to compute at the child chain. Brotli-zero is an approximation that is cheap enough to compute.
Parent chain gas fee funds that are collected from transactions are transferred to a special L1PricerFundsPool
account, so that account's balance represents the amount of funds that have been collected and are available to pay for costs.
The parent chain pricer also records the total number of "data units" (the sum of the estimated sizes, after multiplying by 16) that have been received.
Child chain gas pricing
The child chain gas price on a given Arbitrum chain has a set floor, which can be queried via ArbGasInfo's getMinimumGasPrice
method (currently 0.01 gwei on Arbitrum One and 0.01 gwei on Nova).
Estimating child chain gas
Calling an Arbitrum Node's eth_estimateGas
RPC gives a value sufficient to cover the full transaction fee at the given child chain gas price; i.e., the value returned from eth_estimateGas
multiplied by the child chain gas price tells you how much total Ether is required for the transaction to succeed. Note that this means that for a given operation, the value returned by eth_estimateGas
will change over time (as the parent chain calldata price fluctuates.) (See 2-D fees and How to estimate gas in Arbitrum for more.)
Child chain gas fees
Child chain gas fees work very similarly to gas on Ethereum. A transaction uses some amount of gas, and this is multiplied by the current basefee to get the child chain gas fee charged to the transaction.
The child chain basefee is set by a version of the "exponential mechanism" which has been widely discussed in the Ethereum community, and which has been shown equivalent to Ethereum's EIP-1559 gas pricing mechanism.
The algorithm compares gas usage against a parameter called the speed limit which is the target amount of gas per second that the chain can handle sustainably over time. (Currently the Speed Limit on Arbitrum One is 7,000,000 gas per second.) The algorithm tracks a gas backlog. Whenever a transaction consumes gas, that gas is added to the backlog. Whenever the clock ticks one second, the speed limit is subtracted from the backlog; but the backlog can never go below zero.
Intuitively, if the backlog grows, the algorithm should increase the gas price, to slow gas usage, because usage is above the sustainable level. If the backlog shrinks, the price should decrease again because usage has been below the below the sustainable limit so more gas usage can be welcomed.
To make this more precise, the basefee is an exponential function of the backlog, F = exp(-a(B-b)), where a and b are suitably chosen constants: a controls how rapidly the price escalates with backlog, and b allows a small backlog before the basefee escalation begins.
Child chain Tips
The sequencer prioritizes transactions on a first-come first-served basis. Because tips do not make sense in this model, they are ignored. Arbitrum users always just pay the basefee regardless of the tip they choose.
Gas estimating retryables
When a transaction schedules another, the subsequent transaction's execution will be included when estimating gas via the node's RPC. A transaction's gas estimate, then, can only be found if all the transactions succeed at a given gas limit. This is especially important when working with retryables and scheduling redeem attempts.
Because a call to redeem
donates all of the call's gas, doing multiple requires limiting the amount of gas provided to each subcall. Otherwise the first will take all of the gas and force the second to necessarily fail irrespective of the estimation's gas limit.
Gas estimation for Retryable submissions is possible via the NodeInterface and similarly requires the auto-redeem attempt to succeed.
The Speed Limit
The security of Nitro chains depends on the assumption that when one Validator creates an RBlock, other validators will check it, and respond with a correct RBlock and a Challenge if it is wrong. This requires that the other validators have the time and resources to check each RBlock quickly enough to issue a timely challenge. The Arbitrum protocol takes this into account in setting deadlines for RBlocks.
This sets an effective speed limit on execution of a Nitro chain: in the long run the chain cannot make progress faster than a validator can emulate its execution. If RBlocks are published at a rate faster than the speed limit, their deadlines will get farther and farther in the future. Due to the limit, enforced by the Rollup protocol contracts, on how far in the future a deadline can be, this will eventually cause new RBlocks to be slowed down, thereby enforcing the effective speed limit.
Being able to set the speed limit accurately depends on being able to estimate the time required to validate an RBlock, with some accuracy. Any uncertainty in estimating validation time will force us to set the speed limit lower, to be safe. And we do not want to set the speed limit lower, so we try to enable accurate estimation.
Total fee and gas estimation
The total fee charged to a transaction is the child chain basefee, multiplied by the sum of the child chain gas used plus the parent chain calldata charge. As on Ethereum, a transaction will fail if it fails to supply enough gas, or if it specifies a basefee limit that is below the current basefee. Ethereum also allows a "tip" but Nitro ignores this field and never collects any tips.
Allocating funds and paying what is owed
When a batch posting report is processed at the child chain, the pricer allocates some of the collected funds to pay for costs incurred. To allocate funds, the pricer considers three timestamps:
currentTime
is the current time, when the batch posting report message arrives at the child chainupdateTime
is the time at which the reported batch was submitted (which will typically be around 20 minutes before currentTime)lastUpdateTime
is the time at which the previous reported batch was submitted
The pricer computes an allocation fraction F = (updateTime-lastUpdateTime) / (currentTime-lastUpdateTime)
and allocates a fraction F
of funds in the L1PricerFundsPool
to the current report. The intuition is that the pricer knows how many funds have been collected between lastUpdateTime
and currentTime
, and we want to figure out how many of those funds to allocate to the interval between lastUpdateTime
and updateTime
. The given formula is the correct allocation, if we assume that funds arrived at a uniform rate during the interval between lastUpdateTime
and currentTime
. The pricer similarly allocates a portion of the total data units to the current report.
Now the pricer pays out the allocated funds to cover the rewards due and the amounts due to batch posters, reducing the balance due to each party as a result. If the allocated funds aren't sufficient to cover everything that is due, some amount due will remain. If all of the amount due can be covered with the allocated funds, any remaining allocated funds are returned to the L1PricerFundsPool
.
Getting parent chain fee info
The parent chain gas basefee can be queried via ArbGasInfo.getL1BaseFeeEstimate
. To estimate the parent chain fee a transaction will use, the NodeInterface.gasEstimateComponents() or NodeInterface.gasEstimateL1Component() method can be used.
Arbitrum transaction receipts include a gasUsedForL1
field, showing the amount of gas used on the parent chain in units of the child chain gas.
Adjusting the parent chain gas basefee
After allocating funds and paying what is owed, the parent chain Pricer adjusts the parent chain Gas Basefee. The goal of this process is to find a value that will cause the amount collected to equal the amount owed over time.
The algorithm first computes the surplus (funds in the L1PricerFundsPool
, minus total funds due), which might be negative. If the surplus is positive, the parent chain Gas Basefee is reduced, so that the amount collected over a fixed future interval will be reduced by exactly the surplus. If the surplus is negative, the Basefee is increased so that the shortfall will be eliminated over the same fixed future interval.
A second term is added to the parent chain Gas Basefee, based on the derivative of the surplus (surplus at present, minus the surplus after the previous batch posting report was processed). This term, which is multiplied by a smoothing factor to reduce fluctuations, will reduce the Basefee if the surplus is increasing, and increase the Basefee if the surplus is shrinking.