onus. documentation
How to write, lock, prove and lapse a conditional payment on Arc. Sections 01–05 get you to a first release; the rest is reference.
01Overview
onus. is conditional settlement on Arc. An onus is a contract instance holding stablecoins (USDC, EURC or JPYSC) that releases to a payee when a condition is proven by a named witness, or returns to the payer when a lapse date passes without proof.
There is no admin key, no pause and no discretionary release. onus. the company operates a registry and an SDK; it cannot move funds in any onus.
02Vocabulary
| term | meaning |
|---|---|
| onus | One conditional payment: payer, payee, amount, currency, condition, witness, lapse. |
| condition | A predicate over Arc state (C1 delivery · C2 oracle · C3 result · C4 time). |
| witness | The source that supplies the state: attester, feed, checker, clock, resolver. |
| lapse | Timestamp after which funds return to the payer if not released. |
| tranche | A portion of the amount tied to its own condition. |
| checker | A contract returning true/false on (spec, result). |
| resolver | The witness that decides a dispute in a C4 onus. |
03Quickstart
import { onus } from "@onus/sdk";
const o = await onus.write({
payee: "0x9f2a…c41e", amount: "12500", currency: "USDC",
condition: { kind: "delivery", attester: "0x7d…a1", schema: "delivery/v1", ref: "PO-4127" },
lapse: "30d"
}); // payer signs
await onus.accept(o.id); // payee countersigns
await onus.lock(o.id); // payer funds
// … carrier attests on Arc …
await onus.prove(o.id); // anyone; verifies + releases04Install
npm install @onus/sdk
Targets Arc mainnet by default; { network: "arc-testnet" } for testnet. Gas is paid in USDC; the SDK estimates it per call.
05Write your first onus
- Pick a witness from the registry (§20) or an address you both trust.
onus.write()with payee, amount, currency, condition, lapse. You sign.- Send the id to the payee; they
accept(). Terms are frozen at this point. lock()transfers funds in.- When the witness has supplied the state, anyone calls
prove(); the contract verifies and releases.
06Onuses
Each onus is a minimal proxy contract on Arc. Immutable after accept(): payee, amount, currency, condition, witness, lapse, tranches, payout currency and band. The payer can cancel before the payee accepts; after acceptance only the condition or the lapse can end it.
07Conditions
| kind | reads | releases when |
|---|---|---|
| C1 delivery | EAS attestation | attester signs schema against ref |
| C2 oracle | feed value | comparison holds (optionally sustained) |
| C3 result | checker(spec, result) | checker returns true |
| C4 time | block time + dispute flag | T reached and no dispute |
Combine with and, or, then. Every branch must terminate in release or lapse (§16).
08Witnesses
Named by address at write time; frozen at accept. The contract only accepts state from that address (attester, feed, checker, resolver) or from the chain (clock). A witness cannot be swapped after acceptance, even by both parties — write a new onus instead.
09Lapse
Every onus has a lapse timestamp. After it, lapse() is callable by anyone and returns funds to the payer. A pending dispute (C4) suspends lapse until the resolver decides. Maximum lapse is 365 days.
10Tranches
tranches: [
{ amount: "5000", condition: { kind: "result", spec: "0xaaa…", checker: "0xC…" } },
{ amount: "7500", condition: { kind: "result", spec: "0xbbb…", checker: "0xC…" } }
]
Each tranche releases independently. Unreleased tranches lapse together at the onus lapse date.
11Disputes & resolvers
Only C4 conditions carry a dispute path. The named disputant calls dispute() before lapse; the onus freezes; the named resolver calls resolve(release | return). Resolvers are registry witnesses with records. C1–C3 have no dispute path by design.
12Currencies & StableFX
Lock in USDC, EURC or JPYSC. Optionally set payout: { currency, band }; at release the onus converts via StableFX on Arc if the rate is inside the band, otherwise pays in the locked currency. An onus never fails to pay on a valid release.
13Nano-onuses
Amounts down to 0.000001 USDC via Arc nanopayments. For chains of tiny onuses the SDK batches write+accept+lock into one call per step and prove into one call per batch of results.
14Architecture
payer ── write/lock ──▶ OnusFactory ──▶ Onus (proxy) ◀── accept ── payee
│ reads
attester (EAS) · feed · checker · clock · resolver = witnesses
│ release / lapse
payee / payer (StableFX hop optional)
No off-chain component is in the settlement path. The registry and SDK are conveniences.
15Onus contract
| function | caller | does |
|---|---|---|
accept() | payee | freezes terms |
lock() | payer | pulls funds (after approval) |
cancel() | payer | only before accept |
prove(bytes) | anyone | verifies condition against witness; releases |
lapse() | anyone | after lapse timestamp; returns funds |
dispute() / resolve() | disputant / resolver | C4 only |
No owner, no upgrade, no pause.
16Condition language
cond := atom | cond "and" cond | cond "or" cond | cond "then" cond
atom := attest(by, schema, ref)
| feed(addr).field cmp value [for window]
| check(addr, spec, result)
| time(T) [unless dispute(by)]
cmp := >= | <= | == | > | <
Compiled at write time into a small bytecode the onus contract evaluates. Rejected if any branch fails to terminate in release or lapse.
17Attestations (EAS)
C1 uses the Ethereum Attestation Service deployment on Arc. Core schema delivery/v1: ref (string), deliveredAt (uint64), by (address). Custom schemas may be named; the onus stores the schema UID.
18Feeds
C2 reads any contract exposing latest() → (value, timestamp). The onus stores the feed address and required freshness. onus. recommends naming a second feed as a bound: feed(A) within 1% of feed(B).
19Checker interface
interface IChecker {
function check(bytes32 spec, bytes calldata result) external view returns (bool);
}
Must be view/pure so release is deterministic. Checkers needing off-chain computation post a signed verdict via an attestation instead (pattern in §31).
20Witness registry
Open registry on Arc: name, kind, schema/interface, and a live record (served, released, lapsed, disputed). Listing is permissionless; onus. endorses nothing. The SDK shows the record at write time.
21Fees
- Write / accept / lock / prove / lapse: Arc gas in USDC, each well under a cent.
- Protocol fee: a small flat fee at release, none at lapse.
- StableFX hop: Circle's rate; no onus. markup.
22Security model
| if compromised | can | cannot |
|---|---|---|
| onus. servers / SDK | show wrong data | move funds — no key exists |
| a witness | release or withhold on its onuses | touch other witnesses' onuses; escape the registry record |
| payer key | write/lock/cancel-before-accept | release or reclaim a locked onus early |
| payee key | accept; receive | release |
23onus.write()
onus.write(o: {
payee: Address; amount: string; currency: "USDC"|"EURC"|"JPYSC";
condition: Condition; witness?: Address; // inferred from condition where unique
lapse: string; // "30d", ISO date
tranches?: Tranche[];
payout?: { currency: string; band?: [number, number] };
}): Promise<{ id: string; address: Address }>24onus.lock() / accept()
await onus.accept(id) // payee await onus.lock(id) // payer; handles ERC-20 approval await onus.cancel(id) // payer; before accept only
25onus.prove() / lapse()
await onus.prove(id, proof?) // proof optional: attestation uid, result bytes await onus.lapse(id) // after lapse timestamp await onus.status(id) // draft | accepted | locked | released | lapsed | disputed
26Contract interface
interface IOnus {
function terms() external view returns (Terms memory);
function status() external view returns (uint8);
function accept() external;
function lock() external;
function cancel() external;
function prove(bytes calldata proof) external;
function lapse() external;
function dispute() external;
function resolve(bool release) external;
}27Events
Written(id, payer, payee, amount, currency, lapse) Accepted(id) Locked(id, amount) Released(id, payee, amount, currency, tranche) Lapsed(id, payer, amount) Disputed(id, by) Resolved(id, release)
28Errors
| code | meaning |
|---|---|
E_NOT_ACCEPTED | lock before payee accepted |
E_TERMS_FROZEN | cancel after accept |
E_WITNESS | proof not from the named witness |
E_CONDITION | proof supplied but condition not satisfied |
E_NOT_LAPSED | lapse called before timestamp |
E_DISPUTED | onus frozen pending resolver |
E_BAND | payout currency outside band; paid in locked currency instead (not an error to the payee) |
29Guide: pay a supplier on delivery
- Agree a carrier or receiving party as attester; check their registry record.
- Write a C1 onus with the PO number as
refand a lapse after the latest acceptable delivery date. - Supplier accepts; you lock.
- On delivery the attester signs; anyone calls
prove(); supplier is paid the same block.
30Guide: pay an agent per result
- Hash the task spec; pick or deploy a checker (§31).
- Write a C3 onus with a short lapse (hours).
- The working agent accepts and submits;
prove(result)runs the checker. - For long tasks, one nano-onus per step.
31Guide: write a checker
Implement IChecker.check() as a view. For off-chain verification (running tests, calling a model), have the verifier post an EAS attestation verdict/v1 (spec, resultHash, pass) and make the checker read it. Register the checker so others can name it.
32Safety checklist
- Read the witness's record before naming it.
- Name a second feed as a bound on C2.
- Keep lapse as short as the task allows.
- Use tranches for anything with milestones.
- Set a payout band if converting currency.
- Remember: after accept, nothing can be changed.
33FAQ
Can onus. release funds if a witness disappears?
No. The onus lapses and funds return to the payer.
Can both parties agree to cancel a locked onus?
No. Write the lapse you can live with.
Is this escrow?
Functionally. Legally, onus. is software and holds nothing; the contract holds the funds.
Which chains?
Arc only. Gas in USDC, StableFX and nanopayments are the reason.
Can a person be a witness?
Yes, as an attester or resolver with an address and a record.
34Glossary
attester — signs EAS attestations. band — acceptable FX range at release. checker — result verifier contract. condition — release predicate. lapse — return-to-payer deadline. onus — one conditional payment. resolver — dispute decider. tranche — sub-amount with its own condition. witness — state source.