Skip to main content

Overview

ParameterTypeDefaultRecommendedUnits
Number0 (400)400gas per byte
The default value of 0 is the same as setting the scalar to 400. In order to effectively disable this feature, set the scalar to a very low value such as 1. See the specs for more detail.
The Data Availability (DA) Footprint Block Limit was introduced in the Jovian hardfork to limit the total amount of transaction data that can fit into a block based on a scaled estimate of the compressed size (or “data availability footprint”) of that data. When an OP Stack chain receives more calldata-heavy transactions than can fit into the L1s available blob space, the Batcher can throttle the chains throughput. However, continuous batcher throttling may cause the base fee to drop to the minimum base fee, causing unnecessary losses for the chain operator and negative user experiences such as priority fee auctions. And without throttling, the batcher runs the risk of becoming overwhelmed with chain data to batch to the blob space. Limiting the amount of (estimated compressed) calldata taken up by transactions in a block using their total DA Footprint can reduce the need for batcher throttling and its related issues.

DA Footprint Calculation

For all non-deposit transactions processed by an OP Stack chain, a DA Footprint value is recorded alongside the transaction’s gas usage. The DA Footprint can be configured via the daFootprintGasScalar variable in the SystemConfig contract on the L1 chain. The DA Footprint is automatically calculated for every transaction first by calculating a daUsageEstimate for that transaction:
daUsageEstimate = max(
          minTransactionSize,
          (intercept + fastlzCoef * tx.fastlzSize) // 1e6
      )
where the minTransactionSize, intercept, fastlzCoef, and tx.fastlzSize are as specified in the Fjord specs. Then the daUsageEstimate is then multiplied by the daFootprintGasScalar to get the daFootprint for that individual transaction.
      daFootprint += daUsageEstimate * daFootprintGasScalar
The daFootprint for all the transactions in a block are then added together to calculate that block’s total daFootprint. With the block’s total daFootprint calculated:
  • The block’s total daFootprint must stay below its gasLimit.
  • The blobGasUsed property of each block header is set to that block’s daFootprint.
  • The base fee update calculation then uses gasMetered := max(gasUsed, blobGasUsed) as a replacement for the gasUsed variable.
From Jovian, transaction receipts also record the transaction’s DA Footprint in the receipt’s blobGasUsed field, as well as the block’s daFootprintGasScalar in a new field with the same name.

The DA Footprint Gas Scalar

  • If no limit is set, or the value 0 is set for the daFootprintGasScalar in the SystemConfig, the default value of 400 is used
  • In order to effectively disable this feature, set the scalar to a very low value such as 1.
  • Setting the daFootprintGasScalar too high may exclude too many transactions from your blocks.
  • Setting the daFootprintGasScalar too low may prove ineffective at preventing batcher throttling or protecting against continuous DA heavy transactions.
  • When a chain’s gas limit is changed, the DA footprint scales proportionally by design. However, if you want to retain the same absolute DA footprint limit, then you must also scale the daFootprintGasScalar accordingly.
The DA footprint gas scalar scales the estimated DA usage in bytes to the gas dimension, and this scaled estimate of the DA usage is what we call the DA footprint. This allows us to limit the estimated DA usage using the block’s gasLimit: the effective limit of estimated DA usage per block is gasLimit / daFootprintGasScalar bytes. So increasing this scalar makes DA usage more gas-heavy, so decreases the limit, and vice versa. This is closely related to how the calldata (floor) cost of 40 gas per non-zero byte limits the total amount of calldata in a block. A DA footprint gas scalar of 400 effectively limits incompressible calldata by a factor of 10 compared to its limit without a DA footprint block limit. As such, the feature can be seen as an extension of the existing calldata limit. But instead of repricing the calldata (floor) gas cost, the limit is accounted in parallel to EVM execution gas, and is based on the more relevant FastLZ-based DA usage estimate instead of simply counting zero and non-zero bytes.

Default Value 400

The default scalar of 400 was chosen so that it protects chains in worst-case DA spam scenarios, but has negligible to no impact during normal operation. Careful analyses have been done to estimate the impact on current OP Stack chains and pick the right default. Only high-throughput chains would occasionally even see a small impact from the resulting DA footprint limit (as slightly faster rising base fees). The DA footprint limit is mostly invisible. On mid to low-throughput chains, the feature is expected to have no impact under normal usage conditions. It acts more like an insurance to protect against worst-case incompressible DA spam.

How to Update the daFootprintGasScalar

The steps below explain how to update the daFootprintGasScalar parameter on-chain using the SystemConfig contract.
1

Find your SystemConfig contract address

The SystemConfig contract stores configurable protocol parameters such as gas limits and fee settings.
You can find its proxy address in the state.json generated by op-deployer.
2

Call the setDAFootprintGasScalar() method

The SystemConfig owner is the only address that can make these changes.
To update the daFootprintGasScalar, call the following method on the SystemConfig contract:setDAFootprintGasScalar(uint16 daFootprintGasScalar) external onlyOwner;Example (using cast) to double the scalar, so lower the effective DA usage limit by half:
Cast
cast send -r <L1_RPC_URL> <SYSTEM_CONFIG_PROXY_ADDRESS> "daFootprintGasScalar(uint16)" 800 
3

Verify the new value

After the transaction confirms, verify the current value by calling the following getter method on the SystemConfig contract:function daFootprintGasScalar() external view returns (uint16);Example (using cast):
cast
cast call -r <L1_RPC_URL> <SYSTEM_CONFIG_PROXY_ADDRESS> "daFootprintGasScalar()"
And on your L2 chain you can query the scalar at the L1Block predeploy to confirm the new scalar has been propagated to the chain:
cast
cast call -r <L2_RPC_URL> 0x4200000000000000000000000000000000000015 "daFootprintGasScalar()"


References