Staking as a Juror¶
Stake capital into a Subaccord; become draw-eligible. Capital moves between the Juror's ATA and the Subaccord-PDA-owned stake_vault (ADR-0020: collateral is separate from compensation fee_token).
stake(amount, leaf_path)¶
- SPL transfer
juror_token_account → stake_vault. - Credits the real delta the vault received (fee-on-transfer safe: Token-2022 fees make
delta ≤ amount). - Caller supplies the juror's Merkle path; the chain verifies it vs the stored accumulator root, reads the live
JurorStake.staked, applies the verified delta, and recomputes the root (O(log N)). - First stake (0 → positive) appends a leaf, assigns
tree_index(immutable), and incrementsSubaccord.staker_count. - Reverts while paused.
active_drawsuntouched (preserved on top-up).
unstake(amount, leaf_path)¶
- PDA-signed transfer
stake_vault → juror_token_account. - Caller supplies the juror's Merkle path; root recomputed the same way as
stake. - Reverts while
active_draws > 0(stake frozen until every drawn dispute settles — ADR-0003). - Caps at
JurorStake.staked. - Never halted by pause (capital is never trapped — ADR-0007).
- Full unstake (positive → 0) zeros the leaf (kept at zero selection weight;
tree_indexreused on re-stake) and decrementsSubaccord.staker_count.
staker_count — coarse gate only¶
- Counts distinct Jurors with
staked > 0. Maintained O(1). - Does not track
min_stakeeligibility (changes via timelock; recomputing needs the O(n) ledger ADR-0003 rejected). - Precise eligibility (staked ≥ min_stake, distinctness) is enforced at
draw_seatagainst the frozen accumulator root.
withdraw_fees — earned compensation (ADR-0020)¶
- Jurors accumulate earned fees on
JurorStake.fees_earned(infee_token), credited at settlement against the final ruling (ADR-0029;finalize_roundcredits nothing). withdraw_feespulls the entirefees_earnedbalance from the Subaccord'sfee_vault→ the juror'sfee_tokenATA.- No
active_drawsgate, no timelock — earned fees are not at-risk capital.
import { stake, unstake } from "@useaccord/sdk";
await stake(accord.adapter, accord.PROGRAM_ID, {
subaccord,
juror,
amount,
leafPath,
});
await unstake(accord.adapter, accord.PROGRAM_ID, {
subaccord,
juror,
amount,
leafPath,
});
PDA: ["stake", subaccord, juror]. Each JurorStake carries a tree_index (its leaf position in the Subaccord accumulator, assigned at first stake). The accumulator root lives on the Subaccord (ADR-0012); a wrong path reverts — root integrity never depends on the caller.