CRITICAL - Enables state-root manipulation in rollups
Detects ZK-rollup batch state transitions (old_root, new_root, proof) that write new_root without first verifying old_root matches current stored root.
// ❌ BAD: No old-root validation
pub fn apply_batch(
env: Env,
old_root: BytesN<32>,
new_root: BytesN<32>,
proof: Proof,
transactions: Vec<Transaction>
) {
// Verify proof is valid
verify_batch_proof(&env, proof, &[old_root, new_root]);
// ❌ Never checks: old_root == get_current_root()
// Directly write new root!
set_current_root(&env, new_root);
}Attack: Submit batch with arbitrary old_root, manipulate state chain.
// ✅ GOOD: Validate old-root matches current
pub fn apply_batch(
env: Env,
old_root: BytesN<32>,
new_root: BytesN<32>,
proof: Proof,
transactions: Vec<Transaction>
) {
let current_root = get_current_root(&env);
// Verify old_root matches what we expect
if old_root != current_root {
panic!("Old root mismatch - invalid state transition");
}
// Verify proof with validated old_root
verify_batch_proof(&env, proof, &[old_root, new_root]);
// Safe to apply transition
set_current_root(&env, new_root);
}- State chain breaks: Rollup state becomes inconsistent
- Reorg attacks: Rewrite history arbitrarily
- Fund loss: Users' rollup balances manipulated
- Find functions accepting
(old_root, new_root)pattern - Check for proof verification
- Verify old_root compared to storage BEFORE new_root written
- Flag if validation missing
- #1192, #1194: ZK infrastructure
- #1220: Rollup test fixture
See contracts/fixtures/finding-codes/z013_batch_root_validation.rs