7 KiB
FairSettlement — plain-language explanation
Generated by the OSS Singularity contract lab for: Synthetic fair settlement example. Synthetic example: placeholder addresses, a digest over the public synthetic artifact, future deadlines. The lab explains signatures; it never requests one from a wallet, deploys anything, or holds funds.
What this contract models
The settlement design note, as a readable state machine. The agreement comes before the work and before any funds move. The actual budget sits with a SEPARATELY AUTHORIZED holder — an escrow instance or named human authority — that reads these records and executes transfers in its own audited system. This contract records states and who declared them; it never holds, receives, or moves value of any kind, and it is deliberately not payable. The Commons never holds funds and never gains custody.
funded → delivered → accepted → released
funded → delivered → disputed → resolved → released | refunded
funded → refunded (cancellation before delivery)
any waiting state past its deadline → the outcome the agreement already fixed
from the outer deadline on → refund only; no new release can succeed
States, named exactly as the design note names them
| State | Meaning |
|---|---|
none |
the agreement is recorded, funding not yet declared |
funded |
the agreed budget sits with the separately authorized holder |
delivered |
a delivery receipt links the declared digest to the work |
accepted |
the coordinator accepted exactly the newest revision — the release CONDITION, never the release itself |
disputed |
one of the two parties named the dispute path and its reason |
resolved |
the holder recorded the resolution decided under the agreed dispute rules |
released |
terminal: the settlement went to the contributor |
refunded |
terminal: the settlement went back to the coordinator |
Every function and its requested signature
| Function | Signature you would be asked to sign | What it establishes | Who may call |
|---|---|---|---|
recordFunding() |
a call declaring the budget sits with the holder | that funding exists — a declaration about the holder's custody, never a transfer | holder only |
recordDelivery(uint16 revision) |
a call naming the next revision number | that the contributor recorded revision N referencing the declared digest | contributor only |
accept(uint16 revision) |
a call naming the newest revision | that acceptance binds exactly that revision before the review deadline — the release condition | coordinator only |
release() |
a call executing the release | that the holder released the budget after acceptance satisfied its condition — before the outer deadline | holder only |
openDispute(string calldata reason) |
a call naming the reason for the dispute | that one party opened the agreed dispute path while the work awaits review | contributor or coordinator only |
resolveDispute(bool releases) |
a call declaring which way the resolution goes | that the holder recorded the resolution inside the dispute window | holder only |
executeResolution() |
a call executing the recorded resolution | that the holder carried out the resolution: released or refunded, exactly as resolved — a releasing execution only before the outer deadline | holder only |
applyDisputeFallback() |
a call taking the agreed fallback | that a dispute unresolved past its window ends in the outcome the agreement fixed (refund) — a releasing fallback only before the outer deadline | anyone, once the dispute window has passed |
refundAfterOuterDeadline() |
a call taking the refund path | that funds unreleased past the outer deadline flow back instead of sitting withheld | anyone, once the outer deadline has passed |
refundOnCancellation() |
a call recording the cancellation refund | that a cancelled agreement refunds the budget before delivery | holder only |
Timeouts for unresponsive participants
Every waiting state names a deadline and a defined default outcome:
- delivery not reviewed by
REVIEW_DEADLINE→ the dispute path (acceptis refused;openDisputeand the outer-deadline refund remain possible) — never a silent release - dispute unresolved by
DISPUTE_DEADLINE→ the agreement's fallback outcome (here: refund), executable by anyone viaapplyDisputeFallback - funds unreleased by
OUTER_DEADLINE→ the refund path viarefundAfterOuterDeadline, from every non-terminal state
Refund priority from the outer deadline on — the one precedence rule
this machine fixes: the refund window and every release window are disjoint.
Exactly from the outer deadline instant itself (inclusive — the moment
refundAfterOuterDeadline becomes available,
block.timestamp >= OUTER_DEADLINE), every release-minting transition is
refused with OuterDeadlinePassed — release, a releasing
executeResolution, and a releasing applyDisputeFallback alike. Before
the deadline, releases remain possible and the refund is refused
(OuterDeadlineNotPassed). At every timestamp exactly one direction can
act, so a release can never race the refund for the same state, whichever
transaction arrives first. Executions that already end in a refund stay
allowed from the deadline on: they cannot compete with the refund outcome
they share.
A timeout produces a DEFINED outcome; it never mints authority. The timeout paths are permissionless on purpose: they can only ever reach the outcome the agreement already fixed, so no caller gains control over the settlement.
What can fail, and how each failure is named
NotContributor/NotCoordinator/NotHolder— role checks at the decision point: nobody delivers, reviews, or declares custody for someone else.NotParty— only the two parties may open a dispute; outsiders cannot trigger it.WrongState— every transition demands the exact state the design note names; the failure reports the current one.DuplicateRevision— revisions only move forward, one at a time.NotNewestRevision— stale revisions are refused, not silently superseded.DeadlinePassed— acceptance after the review deadline and resolutions after the dispute deadline are refused.DisputeWindowStillOpen— the agreed fallback exists only for a dispute that outlived its window.OuterDeadlineNotPassed— the refund path exists only from the outer deadline instant onward (inclusive).OuterDeadlinePassed— every release path closes exactly from that instant on: once the refund is available, no new release can succeed.
Honest boundaries
This contract holds no funds and defines no payment mechanics. A digest proves which bytes were declared, not quality, authorship or availability. An acceptance record proves a decision, not fairness. The holder's custody is a separate, audited system with its own threat model; this design depends on it and says so. Deployment, testnet exercise, or any wallet interaction requires separate, explicit authorization — nothing here signs or deploys merely because it was generated.