feat(contracts): add permissionless arbitrator pool selection - #289
Merged
jotel-dev merged 2 commits intoJul 29, 2026
Merged
Conversation
|
@Tijesunimi004 is attempting to deploy a commit to the jotelfootball-tech's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Adds an opt-in arbitrator pool to the escrow contract, layered on top of the single-arbitrator dispute foundation from Nullifier-Systems#275 (raise_dispute, resolve_dispute, the single Arbitrator address, DisputeDeadline). When a dispute is raised, arbitrator eligibility is snapshotted immediately (active pool members registered for at least a day), and a winner is drawn by a separate, permissionless, one-shot select_arbitrator() call after a short delay. resolve_dispute() then requires that specific arbitrator's authorization instead of the single Arbitrator, once a pool exists for that dispute. This closes the collusion risk in the single-arbitrator flow: neither party can predict or influence who resolves their dispute, join/leave timing around a specific dispute has no effect on its outcome, and an unresponsive arbitrator can never freeze funds (reuses Nullifier-Systems#275's existing DisputeDeadline/refund_after_dispute_timeout, with added bookkeeping to free the drawn arbitrator's pending-dispute slot). Deployments with no arbitrators registered are unaffected: raise_dispute()/resolve_dispute() behave exactly as Nullifier-Systems#275 built them, falling back to the single Arbitrator. No changes to htlc-core or atomic-swap. See docs/arbitrator-pool-selection.md for the full design rationale, including why the underlying randomness source is unpredictable at the point selection actually happens.
Tijesunimi004
force-pushed
the
feat/arbitrator-pool-selection
branch
from
July 26, 2026 10:50
555bb04 to
8bbf180
Compare
Contributor
|
fix conflict |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #279.
What changed
Adds an opt-in arbitrator pool to
contracts/escrow/src/lib.rs:join_arbitrator_pool/leave_arbitrator_pool: permissionless registry membership.dispute()now snapshots which pool members are eligible (active, registered at leastARBITRATOR_ACTIVATION_LEDGERSago) the moment the dispute is raised, before anyone could react to it existing.select_arbitrator(): a separate, permissionless, one-shot call that draws a winner from that frozen snapshot after a short reveal delay. The result never depends on who calls it.resolve()now requires the drawn arbitrator's authorization once a pool exists for that dispute, instead of admin/multisig.refund_disputed_after_timeout(): permissionless full refund to the buyer if the arbitrator never resolves, mirroring the existingrefund()timeout pattern.Deployments with no arbitrators registered are unaffected —
dispute()/resolve()behave exactly as before (all existing tests pass unmodified). No changes tohtlc-coreoratomic-swap.Why this shape
This issue is scoped to selection mechanics; the on-chain arbitrator concept and dispute-timeout fallback it depends on (issue #275) hadn't landed yet, so this PR builds the minimal version of that foundation directly rather than blocking on it.
resolve()stays binary (full to buyer/seller), matching its pre-existing behavior — partial-split resolution remains #275's scope, not duplicated here.docs/arbitrator-pool-selection.mdhas the full design writeup, including the anti-gaming reasoning (activation delay, raise-time snapshot, one-shot draw) and why the underlying randomness source (env.prng(), consensus-seeded per Soroban's own docs) is unpredictable at the moment selection actually happens, plus an honest note on its limits (a corrupt validator could in principle bias it — out of scope for a contract-side mechanism).Testing
contracts-cipipeline locally:cargo fmt --check,cargo build --workspace,cargo test --workspace,soroban-lint, andcargo build --workspace --exclude soroban-lint --target wasm32v1-none --release.Test plan
cargo test --workspace(contracts)cargo fmt --all --checksoroban-lint