From 072a01203269870c2004a2bd08ff7e2d7e67f52a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 31 Oct 2025 15:00:36 +0100 Subject: [PATCH 1/9] feat: Galileo rollup fee --- src/handler.rs | 9 +++++++-- src/l1block.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++- src/transaction.rs | 28 +++++++++++++++++++++++++--- 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/handler.rs b/src/handler.rs index 8d3f338..8611d93 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -102,8 +102,12 @@ where }; // Deduct l1 fee from caller. - let tx_l1_cost = - l1_block_info.calculate_tx_l1_cost(rlp_bytes, spec, ctx.tx().compression_ratio()); + let tx_l1_cost = l1_block_info.calculate_tx_l1_cost( + rlp_bytes, + spec, + ctx.tx().compression_ratio(), + ctx.tx().compressed_size(), + ); let caller_account = ctx.journal_mut().load_account(caller)?; if tx_l1_cost.gt(&caller_account.info.balance) { return Err(InvalidTransaction::LackOfFundForMaxFee { @@ -242,6 +246,7 @@ where rlp_bytes, ctx.cfg().spec(), ctx.tx().compression_ratio(), + ctx.tx().compressed_size(), ) } else { U256::from(0) diff --git a/src/l1block.rs b/src/l1block.rs index a6d20c5..847786c 100644 --- a/src/l1block.rs +++ b/src/l1block.rs @@ -248,22 +248,65 @@ impl L1BlockInfo { .wrapping_div(TX_L1_FEE_PRECISION_U256) // account for penalty } + fn calculate_tx_l1_cost_galileo( + &self, + input: &[u8], + spec_id: ScrollSpecId, + compressed_size: U256, + ) -> U256 { + // rollup_fee(tx) = (execScalar * l1BaseFee + blobScalar * l1BlobBaseFee) * + // compressed_size(tx) / PRECISION + // + // Where: + // compressed_size(tx) = min(size(zstd(tx)), size(tx)) + + let tx_size = U256::from(input.len()); + + assert!( + compressed_size <= tx_size, + "transaction compressed size {compressed_size} must be less than or equal to the original size {tx_size}" + ); + + let exec_scalar = self + .l1_commit_scalar + .unwrap_or_else(|| panic!("missing exec scalar in spec_id={spec_id:?}")); + + let compressed_blob_scalar = self + .l1_blob_scalar + .unwrap_or_else(|| panic!("missing l1 blob scalar in spec_id={spec_id:?}")); + + let l1_blob_base_fee = self + .l1_blob_base_fee + .unwrap_or_else(|| panic!("missing l1 blob base fee in spec_id={spec_id:?}")); + + let component_exec = exec_scalar.saturating_mul(self.l1_base_fee); + let component_blob = compressed_blob_scalar.saturating_mul(l1_blob_base_fee); + let fee_per_byte = component_exec.saturating_add(component_blob); + + fee_per_byte.saturating_mul(compressed_size).wrapping_div(TX_L1_FEE_PRECISION_U256) + } + /// 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, compression_ratio: Option, + compressed_size: Option, ) -> U256 { let l1_cost = if !spec_id.is_enabled_in(ScrollSpecId::CURIE) { self.calculate_tx_l1_cost_shanghai(input, spec_id) } else if !spec_id.is_enabled_in(ScrollSpecId::FEYNMAN) { self.calculate_tx_l1_cost_curie(input, spec_id) - } else { + } else if !spec_id.is_enabled_in(ScrollSpecId::GALILEO) { let compression_ratio = compression_ratio.unwrap_or_else(|| { panic!("compression ratio should be set in spec_id={spec_id:?}") }); self.calculate_tx_l1_cost_feynman(input, spec_id, compression_ratio) + } else { + let compressed_size = compressed_size + .unwrap_or_else(|| panic!("compressed size should be set in spec_id={spec_id:?}")); + self.calculate_tx_l1_cost_galileo(input, spec_id, compressed_size) }; l1_cost.min(U64_MAX) } diff --git a/src/transaction.rs b/src/transaction.rs index 07f61d5..c997217 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -26,6 +26,12 @@ pub trait ScrollTxTr: Transaction { /// with posting the transaction on L1. /// Note: compression_ratio(tx) = size(tx) * 1e9 / size(zstd(tx)) fn compression_ratio(&self) -> Option; + + /// The compressed size of the transaction which is used to calculate the cost associated + /// with posting the transaction on L1. + /// Note: compression_ratio(tx) = size(zstd(tx)) + // TODO: Decide if we should use `raw` (rlp-encoded tx) or `tx.Data()` (payload) here. + fn compressed_size(&self) -> Option; } /// A Scroll transaction. Wraps around a base transaction and provides the optional RLPed bytes for @@ -36,17 +42,28 @@ pub struct ScrollTransaction { pub base: T, pub rlp_bytes: Option, pub compression_ratio: Option, + pub compressed_size: Option, } impl ScrollTransaction { - pub fn new(base: T, rlp_bytes: Option, compression_ratio: Option) -> Self { - Self { base, rlp_bytes, compression_ratio } + pub fn new( + base: T, + rlp_bytes: Option, + compression_ratio: Option, + compressed_size: Option, + ) -> Self { + Self { base, rlp_bytes, compression_ratio, compressed_size } } } impl Default for ScrollTransaction { fn default() -> Self { - Self { base: TxEnv::default(), rlp_bytes: None, compression_ratio: None } + Self { + base: TxEnv::default(), + rlp_bytes: None, + compression_ratio: None, + compressed_size: None, + } } } @@ -137,6 +154,10 @@ impl ScrollTxTr for ScrollTransaction { fn compression_ratio(&self) -> Option { self.compression_ratio } + + fn compressed_size(&self) -> Option { + self.compressed_size + } } impl SystemCallTx for ScrollTransaction { @@ -151,6 +172,7 @@ impl SystemCallTx for ScrollTransaction { TX::new_system_tx_with_caller(caller, system_contract_address, data), None, None, + None, ) } } From 666d698999a24e661faf68658e4db768f77c500b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 4 Nov 2025 16:22:11 +0100 Subject: [PATCH 2/9] update --- src/l1block.rs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/l1block.rs b/src/l1block.rs index 847786c..edd5636 100644 --- a/src/l1block.rs +++ b/src/l1block.rs @@ -254,11 +254,13 @@ impl L1BlockInfo { spec_id: ScrollSpecId, compressed_size: U256, ) -> U256 { - // rollup_fee(tx) = (execScalar * l1BaseFee + blobScalar * l1BlobBaseFee) * - // compressed_size(tx) / PRECISION + // Post Galileo rollup fee formula: + // rollup_fee(tx) = fee_per_byte * compressed_size(tx) * (1 + penalty(tx)) / PRECISION // // Where: - // compressed_size(tx) = min(size(zstd(tx)), size(tx)) + // fee_per_byte = (exec_scalar * l1_base_fee + blob_scalar * l1_blob_base_fee) + // compressed_size(tx) = min(len(zstd(rlp(tx))), len(rlp(tx))) + // penalty(tx) = compressed_size(tx) / penalty_factor let tx_size = U256::from(input.len()); @@ -271,7 +273,7 @@ impl L1BlockInfo { .l1_commit_scalar .unwrap_or_else(|| panic!("missing exec scalar in spec_id={spec_id:?}")); - let compressed_blob_scalar = self + let blob_scalar = self .l1_blob_scalar .unwrap_or_else(|| panic!("missing l1 blob scalar in spec_id={spec_id:?}")); @@ -279,11 +281,23 @@ impl L1BlockInfo { .l1_blob_base_fee .unwrap_or_else(|| panic!("missing l1 blob base fee in spec_id={spec_id:?}")); + let penalty_factor = self + .penalty_factor + .unwrap_or_else(|| panic!("missing penalty factor in spec_id={spec_id:?}")); + + // fee_per_byte = (exec_scalar * l1_base_fee) + (blob_scalar * l1_blob_base_fee) let component_exec = exec_scalar.saturating_mul(self.l1_base_fee); - let component_blob = compressed_blob_scalar.saturating_mul(l1_blob_base_fee); + let component_blob = blob_scalar.saturating_mul(l1_blob_base_fee); let fee_per_byte = component_exec.saturating_add(component_blob); - fee_per_byte.saturating_mul(compressed_size).wrapping_div(TX_L1_FEE_PRECISION_U256) + // base_term = fee_per_byte * compressed_size + let base_term = fee_per_byte.saturating_mul(compressed_size); + + // penalty_term = (base_term * compressed_size) / penalty_factor + let penalty_term = base_term.saturating_mul(compressed_size).wrapping_div(penalty_factor); + + // rollup_fee = (base_term + penalty_term) / PRECISION + base_term.saturating_add(penalty_term).wrapping_div(TX_L1_FEE_PRECISION_U256) } /// Calculate the gas cost of a transaction based on L1 block data posted on L2. From 882b0387f66d05c2c19890ff28f19320c89eacbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 4 Nov 2025 16:25:41 +0100 Subject: [PATCH 3/9] update comment --- src/transaction.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/transaction.rs b/src/transaction.rs index c997217..5f88769 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -27,10 +27,9 @@ pub trait ScrollTxTr: Transaction { /// Note: compression_ratio(tx) = size(tx) * 1e9 / size(zstd(tx)) fn compression_ratio(&self) -> Option; - /// The compressed size of the transaction which is used to calculate the cost associated - /// with posting the transaction on L1. - /// Note: compression_ratio(tx) = size(zstd(tx)) - // TODO: Decide if we should use `raw` (rlp-encoded tx) or `tx.Data()` (payload) here. + /// The size of the full rlp-encoded transaction after compression. + /// This is used for calculating the cost associated with posting the transaction on L1. + /// Note: compressed_size(tx) = min(size(zstd(rlp(tx))), size(rlp(tx))) fn compressed_size(&self) -> Option; } From 9b27dc17e1e5d6aa9b488881a1a0c6f0a47e2a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 4 Nov 2025 20:42:28 +0100 Subject: [PATCH 4/9] add test cases --- src/l1block.rs | 53 ++++++++++++++++++++++++++++++++++++++++------ src/transaction.rs | 8 +++---- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/l1block.rs b/src/l1block.rs index edd5636..6e0d26a 100644 --- a/src/l1block.rs +++ b/src/l1block.rs @@ -250,9 +250,9 @@ impl L1BlockInfo { fn calculate_tx_l1_cost_galileo( &self, - input: &[u8], + tx_size: u32, // size of the original rlp-encoded transaction spec_id: ScrollSpecId, - compressed_size: U256, + compressed_size: u32, // size of the compressed rlp-encoded transaction ) -> U256 { // Post Galileo rollup fee formula: // rollup_fee(tx) = fee_per_byte * compressed_size(tx) * (1 + penalty(tx)) / PRECISION @@ -262,13 +262,13 @@ impl L1BlockInfo { // compressed_size(tx) = min(len(zstd(rlp(tx))), len(rlp(tx))) // penalty(tx) = compressed_size(tx) / penalty_factor - let tx_size = U256::from(input.len()); - assert!( compressed_size <= tx_size, "transaction compressed size {compressed_size} must be less than or equal to the original size {tx_size}" ); + let compressed_size = U256::from(compressed_size); + let exec_scalar = self .l1_commit_scalar .unwrap_or_else(|| panic!("missing exec scalar in spec_id={spec_id:?}")); @@ -306,7 +306,7 @@ impl L1BlockInfo { input: &[u8], spec_id: ScrollSpecId, compression_ratio: Option, - compressed_size: Option, + compressed_size: Option, ) -> U256 { let l1_cost = if !spec_id.is_enabled_in(ScrollSpecId::CURIE) { self.calculate_tx_l1_cost_shanghai(input, spec_id) @@ -320,8 +320,49 @@ impl L1BlockInfo { } else { let compressed_size = compressed_size .unwrap_or_else(|| panic!("compressed size should be set in spec_id={spec_id:?}")); - self.calculate_tx_l1_cost_galileo(input, spec_id, compressed_size) + self.calculate_tx_l1_cost_galileo(input.len() as u32, spec_id, compressed_size) }; l1_cost.min(U64_MAX) } } + +#[cfg(test)] +mod tests { + use super::*; + use revm::primitives::uint; + use std::str::FromStr; + + #[test] + fn test_rollup_fee_galileo() { + struct TestCase<'a> { + name: &'a str, // test case label + csize: u32, // compressed size + expected: &'a str, // use string to avoid long literal issues + } + + let tests = [ + TestCase { name: "50-byte tx", csize: 50, expected: "171557471810" }, /* ~0.06 cents */ + TestCase { name: "100-byte tx", csize: 100, expected: "344821983141" }, /* ~0.12 cents */ + TestCase { name: "1-KiB tx", csize: 1024, expected: "3854009072433" }, /* ~1.35 cents */ + TestCase { name: "10-KiB tx", csize: 10 * 1024, expected: "70759382824796" }, /* ~24.77 cents */ + TestCase { name: "1-MiB", csize: 1024 * 1024, expected: "378961881717079120" }, /* ~1325 USD */ + ]; + + let gpo = L1BlockInfo { + l1_base_fee: uint!(1_000_000_000_U256), // 1 gwei + l1_blob_base_fee: Some(uint!(1_000_000_000_U256)), // 1 gwei + l1_commit_scalar: Some(uint!(2394981796_U256)), // 2.39 + l1_blob_scalar: Some(uint!(1019097245_U256)), // 1.02 + penalty_factor: Some(uint!(10000_U256)), + ..Default::default() + }; + + for tt in tests { + println!("Running test: {}", tt.name); + let spec = ScrollSpecId::GALILEO; + let expected = U256::from_str(tt.expected).unwrap(); + let actual = gpo.calculate_tx_l1_cost_galileo(1e10 as u32, spec, tt.csize); + assert_eq!(expected, actual, "failed case: {}", tt.name); + } + } +} diff --git a/src/transaction.rs b/src/transaction.rs index 5f88769..d0d4d38 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -30,7 +30,7 @@ pub trait ScrollTxTr: Transaction { /// The size of the full rlp-encoded transaction after compression. /// This is used for calculating the cost associated with posting the transaction on L1. /// Note: compressed_size(tx) = min(size(zstd(rlp(tx))), size(rlp(tx))) - fn compressed_size(&self) -> Option; + fn compressed_size(&self) -> Option; } /// A Scroll transaction. Wraps around a base transaction and provides the optional RLPed bytes for @@ -41,7 +41,7 @@ pub struct ScrollTransaction { pub base: T, pub rlp_bytes: Option, pub compression_ratio: Option, - pub compressed_size: Option, + pub compressed_size: Option, } impl ScrollTransaction { @@ -49,7 +49,7 @@ impl ScrollTransaction { base: T, rlp_bytes: Option, compression_ratio: Option, - compressed_size: Option, + compressed_size: Option, ) -> Self { Self { base, rlp_bytes, compression_ratio, compressed_size } } @@ -154,7 +154,7 @@ impl ScrollTxTr for ScrollTransaction { self.compression_ratio } - fn compressed_size(&self) -> Option { + fn compressed_size(&self) -> Option { self.compressed_size } } From b8aafd63af5dff3692baed0875b9ea694c6f8675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 4 Nov 2025 20:49:00 +0100 Subject: [PATCH 5/9] sanitize zero penalty factor --- src/l1block.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/l1block.rs b/src/l1block.rs index 6e0d26a..386eabb 100644 --- a/src/l1block.rs +++ b/src/l1block.rs @@ -281,9 +281,11 @@ impl L1BlockInfo { .l1_blob_base_fee .unwrap_or_else(|| panic!("missing l1 blob base fee in spec_id={spec_id:?}")); - let penalty_factor = self - .penalty_factor - .unwrap_or_else(|| panic!("missing penalty factor in spec_id={spec_id:?}")); + let penalty_factor = match self.penalty_factor { + Some(f) if f == U256::from(0) => U256::from(1), // sanitize zero penalty factor + Some(f) => f, + None => panic!("missing penalty factor in spec_id={spec_id:?}"), + }; // fee_per_byte = (exec_scalar * l1_base_fee) + (blob_scalar * l1_blob_base_fee) let component_exec = exec_scalar.saturating_mul(self.l1_base_fee); From ae65f3a6b1de21f63f0844e6243305ace95fa3a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 4 Nov 2025 20:50:52 +0100 Subject: [PATCH 6/9] fix ci test run --- src/l1block.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/l1block.rs b/src/l1block.rs index 386eabb..c1bb005 100644 --- a/src/l1block.rs +++ b/src/l1block.rs @@ -360,7 +360,6 @@ mod tests { }; for tt in tests { - println!("Running test: {}", tt.name); let spec = ScrollSpecId::GALILEO; let expected = U256::from_str(tt.expected).unwrap(); let actual = gpo.calculate_tx_l1_cost_galileo(1e10 as u32, spec, tt.csize); From c67e2de1d79cba4bc958d87d79d93f37469d9238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Tue, 4 Nov 2025 20:59:58 +0100 Subject: [PATCH 7/9] fix --- src/l1block.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/l1block.rs b/src/l1block.rs index c1bb005..72333dd 100644 --- a/src/l1block.rs +++ b/src/l1block.rs @@ -360,9 +360,10 @@ mod tests { }; for tt in tests { + let tx_size = 1e10 as u32; // dummy, but make sure this value is larger than the compressed size let spec = ScrollSpecId::GALILEO; let expected = U256::from_str(tt.expected).unwrap(); - let actual = gpo.calculate_tx_l1_cost_galileo(1e10 as u32, spec, tt.csize); + let actual = gpo.calculate_tx_l1_cost_galileo(tx_size, spec, tt.csize); assert_eq!(expected, actual, "failed case: {}", tt.name); } } From 261ada59103e75cf8691c99a9ed34b7c1dea35fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 5 Nov 2025 10:45:53 +0100 Subject: [PATCH 8/9] use usize --- src/l1block.rs | 10 +++++----- src/transaction.rs | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/l1block.rs b/src/l1block.rs index 72333dd..fd6db2a 100644 --- a/src/l1block.rs +++ b/src/l1block.rs @@ -250,9 +250,9 @@ impl L1BlockInfo { fn calculate_tx_l1_cost_galileo( &self, - tx_size: u32, // size of the original rlp-encoded transaction + tx_size: usize, // size of the original rlp-encoded transaction spec_id: ScrollSpecId, - compressed_size: u32, // size of the compressed rlp-encoded transaction + compressed_size: usize, // size of the compressed rlp-encoded transaction ) -> U256 { // Post Galileo rollup fee formula: // rollup_fee(tx) = fee_per_byte * compressed_size(tx) * (1 + penalty(tx)) / PRECISION @@ -282,7 +282,7 @@ impl L1BlockInfo { .unwrap_or_else(|| panic!("missing l1 blob base fee in spec_id={spec_id:?}")); let penalty_factor = match self.penalty_factor { - Some(f) if f == U256::from(0) => U256::from(1), // sanitize zero penalty factor + Some(f) if f == U256::ZERO => U256::ONE, // sanitize zero penalty factor Some(f) => f, None => panic!("missing penalty factor in spec_id={spec_id:?}"), }; @@ -308,7 +308,7 @@ impl L1BlockInfo { input: &[u8], spec_id: ScrollSpecId, compression_ratio: Option, - compressed_size: Option, + compressed_size: Option, ) -> U256 { let l1_cost = if !spec_id.is_enabled_in(ScrollSpecId::CURIE) { self.calculate_tx_l1_cost_shanghai(input, spec_id) @@ -322,7 +322,7 @@ impl L1BlockInfo { } else { let compressed_size = compressed_size .unwrap_or_else(|| panic!("compressed size should be set in spec_id={spec_id:?}")); - self.calculate_tx_l1_cost_galileo(input.len() as u32, spec_id, compressed_size) + self.calculate_tx_l1_cost_galileo(input.len(), spec_id, compressed_size) }; l1_cost.min(U64_MAX) } diff --git a/src/transaction.rs b/src/transaction.rs index d0d4d38..4bfd8fa 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -30,7 +30,7 @@ pub trait ScrollTxTr: Transaction { /// The size of the full rlp-encoded transaction after compression. /// This is used for calculating the cost associated with posting the transaction on L1. /// Note: compressed_size(tx) = min(size(zstd(rlp(tx))), size(rlp(tx))) - fn compressed_size(&self) -> Option; + fn compressed_size(&self) -> Option; } /// A Scroll transaction. Wraps around a base transaction and provides the optional RLPed bytes for @@ -41,7 +41,7 @@ pub struct ScrollTransaction { pub base: T, pub rlp_bytes: Option, pub compression_ratio: Option, - pub compressed_size: Option, + pub compressed_size: Option, } impl ScrollTransaction { @@ -49,7 +49,7 @@ impl ScrollTransaction { base: T, rlp_bytes: Option, compression_ratio: Option, - compressed_size: Option, + compressed_size: Option, ) -> Self { Self { base, rlp_bytes, compression_ratio, compressed_size } } @@ -154,7 +154,7 @@ impl ScrollTxTr for ScrollTransaction { self.compression_ratio } - fn compressed_size(&self) -> Option { + fn compressed_size(&self) -> Option { self.compressed_size } } From c87b934962b84bcb6fda0fe49bd248d87ff6766e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 5 Nov 2025 10:53:39 +0100 Subject: [PATCH 9/9] update test --- src/l1block.rs | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/src/l1block.rs b/src/l1block.rs index fd6db2a..0442874 100644 --- a/src/l1block.rs +++ b/src/l1block.rs @@ -332,24 +332,15 @@ impl L1BlockInfo { mod tests { use super::*; use revm::primitives::uint; - use std::str::FromStr; - - #[test] - fn test_rollup_fee_galileo() { - struct TestCase<'a> { - name: &'a str, // test case label - csize: u32, // compressed size - expected: &'a str, // use string to avoid long literal issues - } - - let tests = [ - TestCase { name: "50-byte tx", csize: 50, expected: "171557471810" }, /* ~0.06 cents */ - TestCase { name: "100-byte tx", csize: 100, expected: "344821983141" }, /* ~0.12 cents */ - TestCase { name: "1-KiB tx", csize: 1024, expected: "3854009072433" }, /* ~1.35 cents */ - TestCase { name: "10-KiB tx", csize: 10 * 1024, expected: "70759382824796" }, /* ~24.77 cents */ - TestCase { name: "1-MiB", csize: 1024 * 1024, expected: "378961881717079120" }, /* ~1325 USD */ - ]; - + use rstest::rstest; + + #[rstest] + #[case(50, uint!(171557471810_U256))] // ~0.06 cents + #[case(100, uint!(344821983141_U256))] // ~0.12 cents + #[case(1024, uint!(3854009072433_U256))] // ~1.35 cents + #[case(10 * 1024, uint!(70759382824796_U256))] // ~24.77 cents + #[case(1024 * 1024, uint!(378961881717079120_U256))] // ~1325 USD + fn test_rollup_fee_galileo(#[case] compressed_size: usize, #[case] expected: U256) { let gpo = L1BlockInfo { l1_base_fee: uint!(1_000_000_000_U256), // 1 gwei l1_blob_base_fee: Some(uint!(1_000_000_000_U256)), // 1 gwei @@ -359,12 +350,9 @@ mod tests { ..Default::default() }; - for tt in tests { - let tx_size = 1e10 as u32; // dummy, but make sure this value is larger than the compressed size - let spec = ScrollSpecId::GALILEO; - let expected = U256::from_str(tt.expected).unwrap(); - let actual = gpo.calculate_tx_l1_cost_galileo(tx_size, spec, tt.csize); - assert_eq!(expected, actual, "failed case: {}", tt.name); - } + let tx_size = 1e10 as usize; // dummy, but make sure this value is larger than the compressed size + let spec = ScrollSpecId::GALILEO; + let actual = gpo.calculate_tx_l1_cost_galileo(tx_size, spec, compressed_size); + assert_eq!(expected, actual); } }