Transaction Fees on Scroll

Overview

Scroll fees are notably lower than on its supporting layer. For users and developers, transaction fees on Scroll appear to work similarly to those on Ethereum mainnet, and existing tools, wallets, and code will likely work as if they were. However, the transaction fee shown in the wallet isn’t the whole picture unless the software is specifically aware of Scroll’s fee calculations.

Due to the design of L2 rollups, transaction costs depend on the L1’s costs. To leverage Ethereum’s security, Scroll must account for the cost of the transaction data and proofs that must be stored and verified on the L1.

Compared to Ethereum mainnet, Scroll introduces some new dimensions to transaction fee calculation to do this. The final cost of a transaction is constructed from several parts:

  • L2 fee
    • Calculated in the same manner as on the L1, equaling gas_price * gas_used
  • L1 fee
    • This additional fee covers sending data to L1 for data availability. Transactions initiated on the L1 do not pay this fee.
    • It is calculated based on the size of the transaction’s calldata
    • ETH is automatically deducted from the user’s balance on Scroll for the fee

At a high level, the L2 fee is the cost of executing your transaction on the L2 sequencer, and the L1 fee is the cost of committing that transaction onto L1.

In short, totalTxFee = l2Fee + l1Fee, all denominated in ETH, the native gas token for the Scroll network.

L2 Fee

Transactions on Scroll, like on Ethereum, must pay the cost of executing their computations and storing the data they produce.

Calculating the Execution Fee

The L2 execution fee is straightforward:

l2TransactionExecutionFee = l2TransactionGasUsed * l2TransactionGasPrice

The total fee depends on what the transaction does (l2TransactionGasUsed) as well as the current market conditions (l2TransactionGasPrice). Users set the gas price, and the “gas used” is assessed by calling the estimateGas endpoint on a Scroll node.

In other words, the execution fee is calculated precisely like pre-EIP1559 Ethereum.

L1 Fee

Every transaction’s calldata must be committed to Ethereum, which incurs an additional transaction fee, referred to as the “L1 Fee”. Without doing this, Scroll couldn’t be reconstructed from only L1 data.

Transactions aren’t committed 1-by-1 — they are collected in batches of blocks (and blocks of transactions). The cost of an individual transaction is computed based on the zeros and non-zero bytes in its payload.

Estimating the L1 Data Fee

Scroll has a pre-deployed L1GasPriceOracle, accessible on both Scroll and Scroll Sepolia at (0x5300000000000000000000000000000000000002). It provides a getL1Fee method to estimate the L1 data fee for a given transaction’s raw data.

function getL1Fee(bytes memory _data) external view override returns (uint256);

Calculating the L1 Data Fee with Gas Oracle

As mentioned, the L1GasPriceOracle is used to estimate the L1 gas fee given raw transaction data. This is a push oracle, updated by a relayer run by Scroll.

The data fee is based on multiple factors:

  • The bytes which are zeros and nonzeros of an RLP-encoded transaction with Signature
  • l1BaseFee - Current base fee on the L1
  • overhead - Additional gas overhead of a data commitment transaction
  • scalingFactor - A scaling factor used to account for price spikes
  • PRECISION - A constant used to scale the final fee

The following steps are taken to calculate the L1 data fee:

  1. Read three fields l1BaseFee, overhead, scalar from the L1GasPriceOracle contract. The slots for these fields in the contract are:

    FieldSlot
    l1BaseFee1
    overhead2
    scalar3
  2. Count the number of zero bytes and non-zero bytes from the transaction.

  3. Calculate the L1 data fee, given TX_DATA_ZERO_GAS = 4 and TX_DATA_NON_ZERO_GAS = 161 and PRECISION = 1e9:

    l1Gas = zeros * TX_DATA_ZERO_GAS + (nonzeros + 4) * TX_DATA_NON_ZERO_GAS
    l1GasFee = ((l1Gas + overhead) * l1BaseFee * scalar) / PRECISION
    

    We reserve an additional 4 bytes in the non-zero bytes to store the number of bytes in the RLP-encoded transaction.

L1GasPriceOracle API

overhead

function overhead() external view returns (uint256);

Returns the current L1 fee overhead

scalar

function scalar() external view returns (uint256);

Returns the current l1 fee scalar

l1BaseFee

function l1BaseFee() external view returns (uint256);

Returns the latest known l1 base fee

getL1Fee

function getL1Fee(bytes memory data) external view returns (uint256);

Computes the L1 portion of the fee based on the size of the RLP encoded input transaction, the current L1 base fee, and the various dynamic parameters.

Returns: L1 fee that should be paid for the transaction

ParameterDescription
dataSigned fully RLP-encoded transaction to get the L1 fee for.

getL1GasUsed

function getL1GasUsed(bytes memory data) external view returns (uint256);

Computes the amount of L1 gas used for a transaction. Adds the overhead which represents the per-transaction gas overhead of posting the transaction and state roots to L1. Adds 74 bytes of padding to account for the fact that the input does not have a signature.

Returns: Amount of L1 gas used to publish the transaction.

ParameterDescription
dataSigned fully RLP-encoded transaction to get the L1 fee for.

L1 Originated Transactions

When messaging from L1 to L2, the user pays all transaction fees on L1. The user pays L1 gas fees, but because of this, doesn’t need to pay Scroll an L1 Data Fee. They will need to account for L2 Execution Fees in their L1 transaction though, and will need to know how much L2 gas to pay.

Contracts on L1 can use an L2 Gas Price Oracle deployed to the L1 to get the gas fee for a given transaction. The oracle also exposes the current l2BaseFee and estimated cross-domain message fee for a given gas limit.

On mainnet, the L2GasPriceOracle is deployed at 0x987e300fDfb06093859358522a79098848C33852.

On Sepolia, an upgraded L1MessageQueueWithGasPriceOracle should be used, deployed to 0xF0B2293F5D834eAe920c6974D50957A1732de763.

If your system supports off-chain mechanisms, you can also call eth_estimateGas and eth_gasPrice on any Scroll RPC node to get an estimate of the gas required for a given transaction.

Future Roadmap

Currently, the computation required for proof generation and gas for proof verification on L1 is subsidized by Scroll and various proving partners. It is partially covered by setting a floor to L2 Gas Price.

As the prover network becomes decentralized, incentives for proof generation will need to be incorporated into the protocol for the system to be sustainable and scalable.

We expect the final gas cost will explicitly include the cost of this proof generation. With further protocol optimization, this cost for the user should be minimal, as each proof covers many transactions.

Footnotes

  1. See EIP-2028 for more info.

What's Next

Stay up-to-date on the latest Scroll Developer news
Roadmap updates, virtual and live events, ecosystem opportunities and more
Thank you for subscribing!

Resources

Follow Us