Tier: Hard
Description: Every normal escrow-mutating path calls persist_shipment, which writes both storage::set_shipment and storage::set_escrow together. unlock_escrow, recover_shipment, clear_finalization, rollback_on_external_failure (recovery.rs:149-357) call storage::set_shipment directly and never storage::set_escrow, guaranteeing consistency::check_shipment_invariants (which diffs shipment.escrow_amount against storage::get_escrow) will flag a false EscrowMismatch the moment any of them runs. They also bypass validate_shipment_invariants entirely.
Files: contracts/shipment/src/recovery.rs:149-357, contracts/shipment/src/lib.rs:194-199
Tasks:
Tier: Hard
Description: Every normal escrow-mutating path calls
persist_shipment, which writes bothstorage::set_shipmentandstorage::set_escrowtogether.unlock_escrow,recover_shipment,clear_finalization,rollback_on_external_failure(recovery.rs:149-357) callstorage::set_shipmentdirectly and neverstorage::set_escrow, guaranteeingconsistency::check_shipment_invariants(which diffsshipment.escrow_amountagainststorage::get_escrow) will flag a falseEscrowMismatchthe moment any of them runs. They also bypassvalidate_shipment_invariantsentirely.Files:
contracts/shipment/src/recovery.rs:149-357,contracts/shipment/src/lib.rs:194-199Tasks:
persist_shipment(or an equivalent that keepsstorage::set_escrowin sync), and runvalidate_shipment_invariantsAcceptance Criteria:
EscrowMismatch