Category: bug
Problem
dabdub_contracts/contracts/reconciliation/src/lib.rs's submit_merkle_root (lines 46-65) writes the new ReconciliationBatch to the single key DataKey::CurrentBatch, unconditionally overwriting whatever batch was previously stored — there is no historical list or mapping of past batches. verify_settlement (lines 68-86) always reads DataKey::CurrentBatch and compares a caller-supplied Merkle proof against only that one, current root.
Impact
Once a new batch is submitted (presumably on a recurring cadence, e.g. daily), any Merkle proof generated for a payment that was reconciled in a previous batch becomes permanently unverifiable via verify_settlement, even though it was validly included and provable at the time — the proof will compute a root that no longer matches DataKey::CurrentBatch. Any auditor, dispute-resolution flow, or downstream contract that needs to verify a settlement from more than one reconciliation cycle ago has no on-chain way to do so. (Separately, verify_settlement's return value is inverted from what its name suggests — it returns true when a mismatch is detected per its own doc comment, which is a footgun for any integrator who assumes true means "verified OK".)
Suggested fix
Store batches keyed by an incrementing batch ID or by submitted_ledger (e.g. DataKey::Batch(u32)) in addition to (or instead of) a single "current" pointer, and let verify_settlement accept a batch identifier so proofs remain verifiable against the historical root they were actually generated for. Also consider renaming verify_settlement or flipping its return semantics to reduce integrator error.
Category: bug
Problem
dabdub_contracts/contracts/reconciliation/src/lib.rs'ssubmit_merkle_root(lines 46-65) writes the newReconciliationBatchto the single keyDataKey::CurrentBatch, unconditionally overwriting whatever batch was previously stored — there is no historical list or mapping of past batches.verify_settlement(lines 68-86) always readsDataKey::CurrentBatchand compares a caller-supplied Merkle proof against only that one, current root.Impact
Once a new batch is submitted (presumably on a recurring cadence, e.g. daily), any Merkle proof generated for a payment that was reconciled in a previous batch becomes permanently unverifiable via
verify_settlement, even though it was validly included and provable at the time — the proof will compute a root that no longer matchesDataKey::CurrentBatch. Any auditor, dispute-resolution flow, or downstream contract that needs to verify a settlement from more than one reconciliation cycle ago has no on-chain way to do so. (Separately,verify_settlement's return value is inverted from what its name suggests — it returnstruewhen a mismatch is detected per its own doc comment, which is a footgun for any integrator who assumestruemeans "verified OK".)Suggested fix
Store batches keyed by an incrementing batch ID or by
submitted_ledger(e.g.DataKey::Batch(u32)) in addition to (or instead of) a single "current" pointer, and letverify_settlementaccept a batch identifier so proofs remain verifiable against the historical root they were actually generated for. Also consider renamingverify_settlementor flipping its return semantics to reduce integrator error.