Protocol
Mosaic v1 contract behavior for posters, tiles, grouts, and settlement.
Mosaic is an onchain USDC bounty protocol. The website, read API, and SDKs prepare and display actions. Onchain state owns bounty state, submission state, dispute state, credits, and token movement.
Contract Defaults
Amounts use USDC base units.
| Field | Value |
|---|---|
| Chain | Base mainnet (8453) |
| USDC | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Minimum reward | 15_000_000 |
| Submission bond | 10% of reward, rounded up |
| Post fee | 0.25% of reward, rounded up |
| Dispute bond | 10% of submission bond, rounded up |
| Review window | 3_600 seconds (1 hour) |
| Allowed durations | 6 hours, 24 hours, 3 days, 7 days |
Role Rules
Poster. Creates a bounty, escrows the reward, pays the post fee, and calls refundExpired after the bounty deadline when the review cursor is empty.
Tile. Submits work before the bounty deadline and locks the submission bond. Accepted submissions credit reward plus submission bond to the tile.
Grout. Whitelisted account allowed to call dispute for a submitted claim. The grout must not be the poster or the submission claimant.
Public caller. Finalizes eligible bounties, advances the review cursor, and cleans up closed disputes when contract preconditions pass.
Credited account. Withdraws its own credited USDC with withdraw or withdrawTo.
Creation
createBounty(metadataURI, metadataHash, rewardAmount, duration) creates an open bounty.
Required state:
rewardAmount >= minRewardAmount.durationis inallowedDurations.metadataURIis non-empty.metadataHashis non-zero.- Caller is an eligible poster.
- At least one eligible grout exists for review.
Effects:
- Pulls
rewardAmount + postFeeUSDC from the poster. - Credits the post fee to the protocol fee path.
- Stores reward, bond, dispute bond, deadline, review window, metadata URI, and metadata hash.
Submission
submit(bountyId, metadataURI, metadataHash) appends a submission to an open bounty.
Required state:
- Bounty exists and is
Open. - Caller is not the poster.
- Current time is before the bounty deadline.
- At least one eligible grout exists for this poster and claimant pair.
- Metadata URI is non-empty and metadata hash is non-zero.
Effects:
- Pulls the bounty submission bond from the claimant.
- Sets
reviewDeadline = block.timestamp + bounty.reviewWindow. - Links the submission into the bounty queue.
- Sets the first submission as
nextReviewSubmissionIdwhen the queue was empty.
Dispute
dispute(submissionId, metadataURI, metadataHash) opens a challenge against a submitted claim.
Required state:
- Submission exists and has status
Submitted. - Current time is not after
reviewDeadline. - Bounty status is
Open. - Caller is a whitelisted grout.
- Caller is not the bounty poster and not the submission claimant.
- Metadata URI is non-empty and metadata hash is non-zero.
Effects:
- Pulls the dispute bond from the grout.
- Creates a pending challenge.
- Sets submission status to
Disputed.
Dispute Resolution
Pending disputes resolve through Mosaic review.
When the submission is accepted:
- Challenge status becomes
Rejected. - Submission status returns to
Submitted. - Submission active challenge is cleared.
- Tile receives dispute bond credit.
When the dispute is upheld:
- Challenge status becomes
Upheld. - Submission status becomes
Rejected. - Submission active challenge is cleared.
- Grout receives submission bond plus dispute bond credit.
- Review cursor advances when the rejected submission was the current review target.
Finalization
finalize(bountyId) accepts the current review target.
Required state:
- Bounty status is
Open. nextReviewSubmissionIdis non-zero.- Current review submission status is
Submitted. - Current time is after the bounty deadline.
- Current time is after the submission review deadline.
Effects:
- Submission status becomes
Accepted. - Bounty status becomes
Resolved. - Tile receives reward plus submission bond credit.
Refunds And Cleanup
refundExpired(bountyId) is poster-only. It requires an open bounty, an empty review cursor, and time after the bounty deadline. It marks the bounty Refunded and credits the reward to the poster.
refundSubmissionBond(submissionId) is claimant-only. It requires the bounty to be Resolved or Refunded; accepted, rejected, and already refunded submissions are rejected. If the submission is disputed, the pending dispute is cancelled first. The claimant receives submission bond credit.
cancelResolvedDispute(challengeId) clears a pending dispute after its bounty is Resolved or Refunded. It cancels the dispute, refunds the dispute bond to the grout, sets the submission to Refunded, and credits the submission bond to the tile.
advanceReviewCursor(bountyId) moves nextReviewSubmissionId to the next queued submission when the current target is Rejected or Refunded.
Credits
Mosaic uses a pull-payment credit ledger. Settlement adds USDC credit to credits[account]. withdraw() sends caller credit to the caller. withdrawTo(recipient) sends caller credit to recipient.
