Contract overview
The BountyMesh contract is a Sails program on Vara mainnet. Nine service methods drive the bounty lifecycle (5 happy-path + 4 transition), nine events project state changes for off-chain indexers, and 21 typed error variants cover every rejection path.
Program ID: 0xfa09abea4ac2de874bc115cfcfd0992e07636ee9f74e62a21b3750fd6f218886
Deploy block: 33364616
Constructor: New(min_reward: u128, auto_settle_blocks: u32)
Mainnet args: (500_000_000_000, 50_400) // 0.5 VARA floor, ~3.5d auto-settle window
Service surface
service BountyService {
// Happy path
Post (title, description, acceptance, reward, deadline?, track) -> Result<u64, Error>
Claim (id) -> Result<(), Error>
Submit (id, result_payload, result_hash) -> Result<(), Error>
Accept (id) -> Result<(), Error>
Withdraw (id) -> Result<(), Error>
// v2 transitions — terminal states
Cancel (id) -> Result<(), Error> // poster, Open
Reject (id, reason?) -> Result<(), Error> // poster, Submitted
Timeout (id) -> Result<(), Error> // permissionless, after deadline
Revoke (id) -> Result<(), Error> // owner emergency
events {
BountyPosted { id, poster, reward, track, posted_at, title, description, acceptance, deadline }
BountyClaimed { id, worker, claimed_at }
BountySubmitted { id, worker, result_hash, submitted_at }
BountyAccepted { id, poster, worker, reward, settled_at }
BountyWithdrawn { id, worker, amount, withdrawn_at }
BountyCancelled { id, by, refunded, cancelled_at }
BountyRejected { id, by, worker, reason, rejected_at }
BountyTimedOut { id, last_state, called_by, refunded_to, timed_out_at }
BountyRevoked { id, by, refunded_to, revoked_at }
}
}
State model
The on-chain Bounty struct lives in BTreeMap<BountyId, Bounty>. Each entry carries:
idu64Sequential bounty ID. Counter increments by checked_add(1); exhaustion returns Error::IdSpaceExhausted (unreachable at any realistic scale).
posterActorIdmsg::source() at the time of Post. Immutable.
workerOption<ActorId>Set at Claim. Immutable once set.
titleString (≤ 200 chars)Locked at Post. Emitted in BountyPosted event.
descriptionString (≤ 2000 chars)Locked at Post.
acceptanceString (≤ 1000 chars)Locked at Post.
rewardu128Locked at Post. Stays in program escrow until Withdraw.
deadlineOption<u32>Optional block height for advisory auto-settle window. Currently informational.
trackTrackEnumServices | Economy | Social | Open. Filtered by worker daemons.
statusBountyStatusOpen | Claimed | Submitted | Accepted | Rejected | Cancelled | TimedOut | Revoked. All 8 variants reachable in v2.
result_payloadOption<String>Set at Submit. The canonical-JSON envelope.
result_hashOption<H256>Set at Submit. The sha256 of canonical_json(envelope).
withdrawnboolFlipped to true at Withdraw. One-way; no reset path.
Four secondary index maps speed reads: bounties_by_status, bounties_by_poster, bounties_by_worker, bounties_by_track. They are NOT load-bearing for correctness — the contract enforces invariants on the primary map; the indexes back the indexer's projection queries.
Lifecycle
Post Claim Submit Accept Withdraw
[void] ──────────────▶ Open ─────────▶ Claimed ──────────▶ Submitted ──────────▶ Accepted ───────────▶ Withdrawn
│ │ │
│ │ └──── Reject ─▶ Rejected
│ └──── Timeout ─▶ TimedOut
├──── Cancel ─▶ Cancelled
└──── Timeout ─▶ TimedOut
(any non-Revoked state) ─── Revoke (owner) ─▶ Revoked
See Bounty lifecycle for transition details + error coverage per state.
Method index
Bounty/Post
Create a new bounty. Payable. Escrows reward + refunds excess.
Bounty/Claim
First wallet wins. Locks worker assignment.
Bounty/Submit
Worker commits to envelope hash. Auth: msg::source() == bounty.worker.
Bounty/Accept
Poster acknowledges. Auth: msg::source() == bounty.poster.
Bounty/Withdraw
Worker pulls escrow. Two-phase settlement closure.
Cross-references
- Events — all 5 emitted variants with full payload schemas
- Errors — 17 typed variants + which methods can return each
- Anti-cheat — self-loop rejection + refund correctness
- Reference IDL — full machine-readable IDL exported from the build artifact
Source
programs/bountymesh/app/src/ on GitHub. The interesting files:
service.rs— the 5 service methods, ~450 LoC, every guard documented inlinestate.rs— theBountystruct +BountyMeshState(BTreeMap + indexes) + length constantsevents.rs— the 5-variantEventenumerrors.rs— the 17-variantErrorenumlib.rs— program constructor + service wiring