Appeals¶
Permissionless escalation to a larger panel. Anyone may appeal a resolved round within the appeal window.
appeal()¶
| Gate | Error |
|---|---|
!pause_state.paused |
ProgramPaused |
state == RoundResolved |
InvalidState |
current_round < max_appeals |
MaxAppealsReached |
now < reveal_end + APPEAL_WINDOW_SECS |
AppealWindowClosed |
subaccord.staker_count ≥ new_panel |
InsufficientJurors |
Panel ladder¶
Closed form panel_k = (J+1)·2^k − 1, capped at MAX_JURORS (31).
current_round (after++) |
panel (J=3) |
|---|---|
| 1 | 7 |
| 2 | 15 |
| 3 | 31 |
Cost¶
fee_new = panel_new × fee_per_juror
bond = fee_new // bond == new-round fee
total = fee_new + bond // appellant ATA → vault
Bond settlement¶
- Recorded in
AppealBondPDA["bond", dispute, round_idx]whereround_idx= the new (larger) round. prior_result= winner of the round being appealed.finalize_disputechecks each bond:prior_result == final_ruling⇒ no flip ⇒ bond folded into the final-round coherent pool and zeroed.prior_result != final_ruling⇒ flip ⇒ bond left forclaim_appeal_refund.claim_appeal_refundreturns flipped bonds to their appellant (idempotent).
Round reset¶
appeal increments current_round and resets state → Created, so the snapshot → draw → vote cycle reruns for the larger panel.
accord::appeal(ctx.contexts)?;
// later, after Final:
accord::claim_appeal_refund(ctx.contexts, round_idx)?; // round_idx = appealed round
import { appeal, claimAppealRefund } from "@accord/sdk";
await appeal(accord.adapter, accord.PROGRAM_ID, { dispute });
// after finalize_dispute:
await claimAppealRefund(accord.adapter, accord.PROGRAM_ID, {
dispute,
roundIdx,
});
Why permissionless + bond economics: ADR-0004. Cross-round settlement against the final ruling: Kleros §4.6.