Skip to content

Commit 254860f

Browse files
authored
chore(txpool): add sanity tests for blob fee bit handling (paradigmxyz#18258)
1 parent 4cc600c commit 254860f

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

‎crates/transaction-pool/src/pool/txpool.rs‎

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3940,4 +3940,108 @@ mod tests {
39403940
assert_eq!(t2.id(), tx2.id());
39413941
assert_eq!(t3.id(), tx3.id());
39423942
}
3943+
3944+
#[test]
3945+
fn test_non_4844_blob_fee_bit_invariant() {
3946+
let mut f = MockTransactionFactory::default();
3947+
let mut pool = TxPool::new(MockOrdering::default(), Default::default());
3948+
3949+
let non_4844_tx = MockTransaction::eip1559().set_max_fee(200).inc_limit();
3950+
let validated = f.validated(non_4844_tx.clone());
3951+
3952+
assert!(!non_4844_tx.is_eip4844());
3953+
pool.add_transaction(validated.clone(), U256::from(10_000), 0, None).unwrap();
3954+
3955+
// Core invariant: Non-4844 transactions must ALWAYS have ENOUGH_BLOB_FEE_CAP_BLOCK bit
3956+
let tx_meta = pool.all_transactions.txs.get(validated.id()).unwrap();
3957+
assert!(tx_meta.state.contains(TxState::ENOUGH_BLOB_FEE_CAP_BLOCK));
3958+
assert_eq!(tx_meta.subpool, SubPool::Pending);
3959+
}
3960+
3961+
#[test]
3962+
fn test_blob_fee_enforcement_only_applies_to_eip4844() {
3963+
let mut f = MockTransactionFactory::default();
3964+
let mut pool = TxPool::new(MockOrdering::default(), Default::default());
3965+
3966+
// Set blob fee higher than EIP-4844 tx can afford
3967+
let mut block_info = pool.block_info();
3968+
block_info.pending_blob_fee = Some(160);
3969+
block_info.pending_basefee = 100;
3970+
pool.set_block_info(block_info);
3971+
3972+
let eip4844_tx = MockTransaction::eip4844()
3973+
.with_sender(address!("0x000000000000000000000000000000000000000a"))
3974+
.with_max_fee(200)
3975+
.with_blob_fee(150) // Less than block blob fee (160)
3976+
.inc_limit();
3977+
3978+
let non_4844_tx = MockTransaction::eip1559()
3979+
.with_sender(address!("0x000000000000000000000000000000000000000b"))
3980+
.set_max_fee(200)
3981+
.inc_limit();
3982+
3983+
let validated_4844 = f.validated(eip4844_tx);
3984+
let validated_non_4844 = f.validated(non_4844_tx);
3985+
3986+
pool.add_transaction(validated_4844.clone(), U256::from(10_000), 0, None).unwrap();
3987+
pool.add_transaction(validated_non_4844.clone(), U256::from(10_000), 0, None).unwrap();
3988+
3989+
let tx_4844_meta = pool.all_transactions.txs.get(validated_4844.id()).unwrap();
3990+
let tx_non_4844_meta = pool.all_transactions.txs.get(validated_non_4844.id()).unwrap();
3991+
3992+
// EIP-4844: blob fee enforcement applies - insufficient blob fee removes bit
3993+
assert!(!tx_4844_meta.state.contains(TxState::ENOUGH_BLOB_FEE_CAP_BLOCK));
3994+
assert_eq!(tx_4844_meta.subpool, SubPool::Blob);
3995+
3996+
// Non-4844: blob fee enforcement does NOT apply - bit always remains true
3997+
assert!(tx_non_4844_meta.state.contains(TxState::ENOUGH_BLOB_FEE_CAP_BLOCK));
3998+
assert_eq!(tx_non_4844_meta.subpool, SubPool::Pending);
3999+
}
4000+
4001+
#[test]
4002+
fn test_basefee_decrease_preserves_non_4844_blob_fee_bit() {
4003+
let mut f = MockTransactionFactory::default();
4004+
let mut pool = TxPool::new(MockOrdering::default(), Default::default());
4005+
4006+
// Create non-4844 transaction with fee that initially can't afford high basefee
4007+
let non_4844_tx = MockTransaction::eip1559()
4008+
.with_sender(address!("0x000000000000000000000000000000000000000a"))
4009+
.set_max_fee(500) // Can't afford basefee of 600
4010+
.inc_limit();
4011+
4012+
// Set high basefee so transaction goes to BaseFee pool initially
4013+
pool.update_basefee(600);
4014+
4015+
let validated = f.validated(non_4844_tx);
4016+
let tx_id = *validated.id();
4017+
pool.add_transaction(validated, U256::from(10_000), 0, None).unwrap();
4018+
4019+
// Initially should be in BaseFee pool but STILL have blob fee bit (critical invariant)
4020+
let tx_meta = pool.all_transactions.txs.get(&tx_id).unwrap();
4021+
assert_eq!(tx_meta.subpool, SubPool::BaseFee);
4022+
assert!(
4023+
tx_meta.state.contains(TxState::ENOUGH_BLOB_FEE_CAP_BLOCK),
4024+
"Non-4844 tx in BaseFee pool must retain ENOUGH_BLOB_FEE_CAP_BLOCK bit"
4025+
);
4026+
4027+
// Decrease basefee - transaction should be promoted to Pending
4028+
// This is where PR #18215 bug would manifest: blob fee bit incorrectly removed
4029+
pool.update_basefee(400);
4030+
4031+
// After basefee decrease: should be promoted to Pending with blob fee bit preserved
4032+
let tx_meta = pool.all_transactions.txs.get(&tx_id).unwrap();
4033+
assert_eq!(
4034+
tx_meta.subpool,
4035+
SubPool::Pending,
4036+
"Non-4844 tx should be promoted from BaseFee to Pending after basefee decrease"
4037+
);
4038+
assert!(
4039+
tx_meta.state.contains(TxState::ENOUGH_BLOB_FEE_CAP_BLOCK),
4040+
"Non-4844 tx must NEVER lose ENOUGH_BLOB_FEE_CAP_BLOCK bit during basefee promotion"
4041+
);
4042+
assert!(
4043+
tx_meta.state.contains(TxState::ENOUGH_FEE_CAP_BLOCK),
4044+
"Non-4844 tx should gain ENOUGH_FEE_CAP_BLOCK bit after basefee decrease"
4045+
);
4046+
}
39434047
}

0 commit comments

Comments
 (0)