Overview
Build a full dispute lifecycle into the contract. Any payer on an invoice can open a dispute before release. A configurable set of arbitrators votes to resolve or reject. Funds are frozen during dispute and released/refunded according to the outcome.
Requirements
open_dispute(env, invoice_id, payer, reason: String) — opens a dispute, freezes the invoice (cannot release/refund while open)
vote_dispute(env, invoice_id, arbitrator, approve: bool) — arbitrator casts a vote; requires the caller to be in the stored arbitrator set
resolve_dispute(env, invoice_id) — callable by anyone once quorum is reached; resolves the invoice according to majority vote (approve → release, reject → refund)
- Dispute state stored under a new
dispute_key(invoice_id) storage key
- Emit
DisputeOpened, DisputeVoteCast, DisputeResolved events
- Admin can configure
arbitrator_set and quorum_threshold (e.g. 2-of-3)
- Write unit tests for: open → vote → resolve (approve path), open → vote → resolve (reject path), duplicate vote rejected, non-arbitrator vote rejected, dispute on non-existent invoice
Acceptance Criteria
Definition of Done
All CI checks must pass before the PR is reviewed.
Overview
Build a full dispute lifecycle into the contract. Any payer on an invoice can open a dispute before release. A configurable set of arbitrators votes to resolve or reject. Funds are frozen during dispute and released/refunded according to the outcome.
Requirements
open_dispute(env, invoice_id, payer, reason: String)— opens a dispute, freezes the invoice (cannot release/refund while open)vote_dispute(env, invoice_id, arbitrator, approve: bool)— arbitrator casts a vote; requires the caller to be in the stored arbitrator setresolve_dispute(env, invoice_id)— callable by anyone once quorum is reached; resolves the invoice according to majority vote (approve → release, reject → refund)dispute_key(invoice_id)storage keyDisputeOpened,DisputeVoteCast,DisputeResolvedeventsarbitrator_setandquorum_threshold(e.g. 2-of-3)Acceptance Criteria
dispute_keycargo test --workspacepasses with zero failurescargo clippy --all-targets -- -D warningsproduces zero warningsDefinition of Done
All CI checks must pass before the PR is reviewed.