Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion src/l1block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const L1_SCALAR_SLOT: U256 = U256::from_limbs([3u64, 0, 0, 0]);
const L1_BLOB_BASE_FEE_SLOT: U256 = U256::from_limbs([5u64, 0, 0, 0]);

/// The L1 commit scalar storage slot.
///
/// Post-FEYNMAN this represents the exec_scalar.
const L1_COMMIT_SCALAR_SLOT: U256 = U256::from_limbs([6u64, 0, 0, 0]);

/// The L1 blob scalar storage slot.
Expand Down Expand Up @@ -138,12 +140,69 @@ impl L1BlockInfo {
self.calldata_gas.unwrap().saturating_add(blob_gas).wrapping_div(TX_L1_FEE_PRECISION)
}

fn calculate_tx_l1_cost_feynman(&self, input: &[u8], spec_id: ScrollSpecId) -> U256 {
// rollup_fee(tx) = compression_factor(tx) * size(tx) * (component_exec + component_blob)
//
// - compression_factor(tx): compression_factor = 1 / compression_ratio, where
// compression_ratio is the estimated compressibility of the signed tx data. The tx is
// eventually a part of a L2 batch that should likely result in a better compression ratio,
// however a conservative estimate is the size of zstd-encoding of the signed tx.
//
// - size(tx): denotes the size of the signed tx.
//
// - component_exec: The component that accounts towards commiting this tx as part of a L2
// batch as well as gas costs for the eventual on-chain proof verification.
// => (compression_scalar + commit_scalar + verification_scalar) * l1_base_fee
// => (exec_scalar) * l1_base_fee
//
// - component_blob: The component that accounts the costs associated with data
// availability, i.e. the costs of posting this tx's data in the EIP-4844 blob.
// => (compression_scalar + blob_scalar) * l1_blob_base_fee
// => (new_blob_scalar) * l1_blob_base_fee
//
// Note that the same slots for L1_COMMIT_SCALAR_SLOT and L1_BLOB_SCALAR_SLOT are
// re-used/updated for the new values post-FEYNMAN.
let component_exec = {
let exec_scalar = self
.l1_commit_scalar
.unwrap_or_else(|| panic!("missing exec scalar in spec_id={:?}", spec_id));
exec_scalar.saturating_mul(self.l1_base_fee)
};
let component_blob = {
let blob_scalar = self
.l1_blob_scalar
.unwrap_or_else(|| panic!("missing l1 blob scalar in spec_id={:?}", spec_id));
let blob_base_fee = self
.l1_blob_base_fee
.unwrap_or_else(|| panic!("missing l1 blob base fee in spec_id={:?}", spec_id));
blob_scalar.saturating_mul(blob_base_fee)
};

// Assume compression_factor = 1 until we have specification for estimating compression
// ratio based on previous finalised batches.
//
// We use the `TX_L1_FEE_PRECISION` to allow fractions. We then divide the overall product
// by the precision value as well.
let compression_factor = |_input: &[u8]| -> U256 { TX_L1_FEE_PRECISION };

// size(tx) is just the length of the RLP-encoded signed tx data.
let tx_size = |input: &[u8]| -> U256 { U256::from(input.len()) };

compression_factor(input)
.saturating_mul(tx_size(input))
.saturating_mul(component_exec.saturating_add(component_blob))
.wrapping_div(TX_L1_FEE_PRECISION)
.wrapping_div(TX_L1_FEE_PRECISION)
}

/// Calculate the gas cost of a transaction based on L1 block data posted on L2.
pub fn calculate_tx_l1_cost(&self, input: &[u8], spec_id: ScrollSpecId) -> U256 {
let l1_cost = if !spec_id.is_enabled_in(ScrollSpecId::CURIE) {
self.calculate_tx_l1_cost_shanghai(input, spec_id)
} else {
} else if !spec_id.is_enabled_in(ScrollSpecId::FEYNMAN) {
self.calculate_tx_l1_cost_curie(input, spec_id)
} else {
self.calculate_tx_l1_cost_feynman(input, spec_id)
};
l1_cost.min(U64_MAX)
}
Expand Down
Loading