Conditional Settlement (v1)
Status: Draft v1 — 2026-05-19
Extension URI: https://projectmaya.deoscomputing.io/settlement/conditional/v1
Maintainer: DEOS Computing (did:web:deos.computing)
Depends on: Receipt format v1, UCAN tokens v1
Companions: Receipt-Rooted Reputation white paper, a2a-ext/substrate-receipts/v1
1. Motivation
Agent-to-agent payments today move unconditionally: funds transfer when the action initiates, regardless of whether the outcome is acceptable. Disputes are post-hoc and live in a parallel evidence world (chargebacks, support tickets, arbitration) with no link back to the signed action history. The receipt-reputation white paper §1 calls this the aggregator problem; conditional settlement is the same problem applied to money.
Conditional settlement composes substrate receipts with payment rails so the release/refund decision is computed from receipt presence and absence, not negotiated out-of-band:
- An escrow receipt at
action_can = settlement.conditional/escrownames the funds, the rail, the success condition (typically: an outcome receipt from a specific principal matching a pattern), the deadline, and the refund policy. - The escrow holder (smart contract, payment processor, or substrate operator) reads the substrate and computes the current disposition:
await|release|refund_timeout|refund_disputed. - When the disposition transitions to a terminal state, the rail moves funds and the holder appends a
settlement.conditional/settledreceipt naming the disposition and the on-rail transaction reference.
A relying party — user, regulator, counterparty's customer — re-proves the payment-vs-outcome state purely from receipts. No chargeback portal, no out-of-band reconciliation.
This spec defines:
- The wire shape for
settlement.conditional/escrowandsettlement.conditional/settledreceipts. - The escrow holder's verification obligations.
- Composition with the substrate-receipts A2A extension.
- A minimum-viable disposition algorithm every conforming holder MUST implement.
Rail-specific integrations are out of scope — those are operator deployments. §6 lists rails this spec considers but does not bundle.
2. Wire format
2.1 Escrow receipt
The action that creates a conditional payment. Issued by the principal authorizing the spend; signed by the substrate per the normal receipt flow.
{
"id": "<blake3 of canonical body>",
"principal": "did:deos:alice",
"subject": "did:deos:agent-alice",
"issued_at": 1716000000000000000,
"capability": { "chain": [/* UCAN chain rooted at alice */] },
"action": {
"type": "escrow",
"inputs_hash": "<...>",
"metadata": {
"rail": "ethereum/usdc",
"rail_chain_id": 1,
"rail_asset": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"amount": "87.99",
"currency": "USDC",
"from": "0xAlice...",
"to": "0xBob...",
"escrow_holder": "0xEscrow...",
"memo": "amazon order B0XXX dog food",
"condition": {
"release_on": {
"outcome_principal": "did:deos:bob-courier",
"action_can_pattern": "shipment.delivered/v1",
"metadata_match": { "to": "0xAlice..." }
},
"deadline_ns": 1716604800000000000,
"refund_on_timeout": true,
"refund_on_disputed": true,
"dispute_principal": "did:deos:alice"
}
},
"result_hash": null
},
"signatures": [/* substrate signature */]
}
action.action_can
MUST be settlement.conditional/escrow. This is what the escrow holder filters on when scanning the log.
metadata.rail
The payment rail identifier, free-form but SHOULD be one of:
ethereum/usdc,ethereum/usdt,ethereum/dai,ethereum/ethsolana/usdc,solana/solbase/usdc,arbitrum/usdc,polygon/usdc,optimism/usdcfednow(US Federal Reserve instant rail)rtp(The Clearing House Real-Time Payments)sepa-inst(EU SEPA Instant Credit Transfer)lightning/btcinternal(substrate-operator-held balance, no external rail)
Custom rails MUST namespace under their operator's URI prefix.
metadata.rail_chain_id, metadata.rail_asset
Required for EVM rails; identify the network + token contract. Other rails define their own analogues (fednow.routing, lightning.network).
metadata.amount, metadata.currency
Amount as a base-10 decimal string (NOT a float — exact). Currency is the ISO-4217 code or the asset symbol where ISO doesn't apply. currency SHOULD match rail's native denomination; conversions are out of scope.
metadata.escrow_holder
Address (or DID, depending on rail) of the party that holds funds during the conditional window. For on-chain rails this is typically a deployed escrow contract. For FedNow/RTP it's a regulated PSP. The principal MUST have ensured escrow_holder is operationally bound to honor this spec; this spec does not certify holders.
metadata.condition.release_on
Defines the success outcome.
| Field | Required | Meaning |
|---|---|---|
outcome_principal |
✓ | DID expected to issue the outcome receipt |
action_can_pattern |
✓ | The outcome receipt's action_can must equal this (no wildcards in v1 — exact string match) |
metadata_match |
optional | Sub-object; every key must appear in the outcome receipt's action.metadata with the same scalar value |
The outcome receipt MUST be issued at or after the escrow receipt's issued_at and strictly before deadline_ns.
metadata.condition.deadline_ns
Absolute deadline in unix nanoseconds. After this point the holder MAY transition to refund_timeout (per refund_on_timeout) without waiting for further outcome receipts.
metadata.condition.refund_on_timeout, metadata.condition.refund_on_disputed
Booleans. If both are false and the timeout / dispute occurs, the funds remain in escrow (a frozen disposition — see §3) until the dispute resolution flow ships in v1.1.
metadata.condition.dispute_principal
DID authorized to issue a settlement.conditional/dispute receipt that, if refund_on_disputed is true, terminates the escrow into refund_disputed. Typically the original principal (Alice) but MAY differ (a regulator, a guardian).
2.2 Outcome receipt (referenced, not defined here)
The outcome receipt is just an ordinary substrate receipt whose action_can matches the release_on.action_can_pattern. It's issued by outcome_principal per its own normal authorization. The escrow receipt does NOT need to know how the outcome is generated — it just specifies what to look for.
Example outcome shape (informative, not normative):
{
"principal": "did:deos:bob-courier",
"subject": "did:deos:agent-bob-courier",
"action": {
"type": "delivered",
"metadata": {
"to": "0xAlice...",
"tracking_id": "1Z999...",
"delivered_at": "2026-05-21T17:42:11Z"
}
}
}
action.metadata.to matches escrow.metadata.condition.release_on.metadata_match.to. That match is what lets the holder bind this outcome to this escrow, not another from the same courier.
2.3 Dispute receipt
An action receipt by dispute_principal at action_can = settlement.conditional/dispute. Its metadata MUST include the escrow receipt's id in metadata.escrow_receipt_id and SHOULD include reason (free-form string).
2.4 Settled receipt
Once the holder moves funds, it appends an action receipt at action_can = settlement.conditional/settled to its own substrate (typically the holder's substrate, not the principal's). Metadata names the escrow + disposition + rail-side transaction reference.
{
"principal": "did:deos:escrow-holder",
"subject": "did:deos:escrow-holder-agent",
"action": {
"type": "settled",
"metadata": {
"escrow_receipt_id": "<id of the original escrow receipt>",
"disposition": "release",
"rail": "ethereum/usdc",
"rail_tx": "0xabcd...",
"settled_at": "2026-05-22T01:13:00Z"
}
}
}
The settled receipt's existence is itself part of the audit chain — anyone (including the original principal) verifies fund movement against the rail and against this receipt.
3. Disposition algorithm
Given an escrow receipt and a substrate (or substrates, when the outcome principal uses a different substrate from the principal — see §5), the holder computes one of:
| Disposition | Meaning |
|---|---|
await |
Outcome not yet observed, deadline not yet passed. Hold funds. |
release |
Matching outcome receipt observed within deadline. Release funds to metadata.to. |
refund_timeout |
now_ns >= deadline_ns and no matching outcome. If refund_on_timeout, refund to metadata.from; else frozen. |
refund_disputed |
A dispute receipt by dispute_principal was observed before the matching outcome (or before the deadline). If refund_on_disputed, refund; else frozen. |
frozen |
Terminal state reached but neither refund flag was true. Funds remain in escrow pending v1.1 resolution flow. |
The MUST-implement algorithm (informative pseudocode):
def disposition(escrow, now_ns, substrate):
e = escrow.metadata
c = e.condition
# Disputed beats outcome (unless outcome came first chronologically)
outcome = substrate.find_outcome(escrow, e, c) # see below
dispute = substrate.find_dispute(escrow, c.dispute_principal)
if dispute and (not outcome or dispute.issued_at_ns < outcome.issued_at_ns):
return "refund_disputed" if c.refund_on_disputed else "frozen"
if outcome:
return "release"
if now_ns >= c.deadline_ns:
return "refund_timeout" if c.refund_on_timeout else "frozen"
return "await"
def find_outcome(escrow, e, c):
for r in substrate.iter_receipts_since(escrow.issued_at_ns):
if r.principal != c.release_on.outcome_principal: continue
if r.action.action_can != c.release_on.action_can_pattern: continue
if r.issued_at_ns >= c.deadline_ns: continue
if c.release_on.metadata_match:
if not metadata_subset(c.release_on.metadata_match, r.action.metadata):
continue
return r
return None
The algorithm is monotonic in time: a release at T is still release at T+1; same for refund states. Only await transitions out. Once the holder writes a settled receipt for any terminal state, the conditional is closed.
4. Holder obligations
A conforming escrow holder MUST:
- Verify the escrow receipt's substrate signature and capability chain before accepting funds. If the chain doesn't authorize the escrow action, reject without holding.
- Verify that the
fromaddress (or equivalent) is bound to the principal — either by capability metadata or by rail-side proof. - Monitor the substrate for outcome and dispute receipts. Polling cadence is operator policy; SSE / webhooks recommended where the substrate supports them.
- On terminal disposition, move funds within an operator-published SLA. The SLA MUST be at least monotone: once the holder commits to a disposition, it does not reverse.
- Append the
settledreceipt to its own substrate before the user-visible funds-moved status flips. If the holder fails to settle within its SLA, the relying party can re-derive the disposition and pursue rail-side remedies; the absent settled receipt is itself evidence. - Treat its own substrate signatures as binding — a holder who issues a contradictory settled receipt (two settled receipts for the same escrow with different dispositions) has self-doxxed and SHOULD be rejected by downstream parties.
A conforming holder MUST NOT:
- Release funds on an outcome receipt whose
action_candoesn't exactly matchrelease_on.action_can_pattern. - Wait past
deadline_ns + holder_grace_seconds(holder policy, typically ≤ 600s) before transitioning out ofawait. - Issue a
settledreceipt for a disposition that isn't computed by the algorithm in §3.
5. Cross-substrate composition
The escrow receipt lives on the principal's substrate. The outcome receipt may live on a different substrate — typically the outcome principal's own substrate (e.g., Bob's courier substrate).
The holder MUST be able to read from both. Two acceptable patterns:
- Replication: the principal's substrate is configured to mirror outcome receipts from a list of trusted source substrates. The holder reads only the principal's substrate. Simple but requires operator coordination.
- Federation manifest (preferred): the escrow receipt's
metadata.condition.release_onincludes an optionalsubstrate_urlfor the outcome substrate. The holder reads both. Uses the federation extension defined in did:deos v1 §12.
"release_on": {
"outcome_principal": "did:deos:bob-courier",
"action_can_pattern": "shipment.delivered/v1",
"substrate_url": "https://substrate.bob-courier.example.com",
"metadata_match": { "to": "0xAlice..." }
}
When the holder reads from a non-principal substrate, it MUST verify the outcome substrate's trust root and signatures independently. The principal's substrate's trust does not extend transitively.
6. Rail considerations (non-normative)
The spec is rail-agnostic. The following are the rails this design was sanity-checked against; conforming implementations on each are deferred to operator deployments.
6.1 EVM stablecoins (USDC / USDT / DAI)
Natural fit. escrow_holder is a deployed escrow contract whose code reads the substrate via an oracle (or via a trusted relayer that submits substrate inclusion proofs). Funds enter via ERC-20 transferFrom into the contract; release/refund are contract calls authorized by the relayer-signed disposition.
Practical concern: the substrate is off-chain. The escrow contract trusts whoever submits a "this disposition is final" proof. Reasonable v1 designs:
- Trusted relayer (the holder operator). Simplest. Trust assumption is "the holder follows §4."
- Threshold-signed relayer set. Resists single-party corruption.
- Substrate inclusion proof on-chain. Requires the substrate's signing keys to be EVM-recoverable (Ed25519 → secp256k1 conversion or a per-chain bridge); shipping in v1.1.
6.2 FedNow / RTP
US instant-payment rails. escrow_holder is a regulated PSP that holds funds during the conditional window. Disposition decisions are made off-rail (per §3) and translated into FedNow / RTP messages. Refund is a reverse credit transfer; release is a normal credit transfer.
Practical concern: FedNow and RTP have settlement finality measured in seconds, not hours, which is faster than typical conditional windows (delivery confirmations come in days). The PSP holds the float; the spec assumes the PSP is solvent and compliant with its regulator.
6.3 SEPA Instant
EU equivalent. Same shape as FedNow/RTP.
6.4 Lightning Bitcoin
escrow_holder is an HTLC counterparty with a custom preimage protocol: the preimage is revealed to the holder upon disposition computation, and the holder publishes settlement-as-onchain-tx or routes the preimage. Less smooth than EVM because Lightning's native conditionals are payment-hash-based, not application-state-based; the holder bridges.
6.5 Internal (substrate-operator-held)
Useful for substrate-internal economies — a substrate operator runs an L2-style balance system and conditional payments are just bookkeeping. No external rail. Suitable for closed-network deployments.
7. Composition with A2A and reputation
A conditional payment receipt flows through A2A Task artifacts like any other (per a2a-ext/substrate-receipts/v1). A counterparty requesting payment returns a Task=COMPLETED artifact whose receipt is at action_can = settlement.conditional/escrow. The relying party verifies the chain and MAY monitor the substrate for outcome/dispute progression.
For reputation, past escrow dispositions feed the outcomeRatio derivation directly: every escrow → release is a clean outcome, every escrow → refund_disputed is a disputed one. A counterparty with a high refund_disputed rate carries falsifiable bad reputation, signed and anchored.
8. Threat model
8.1 Holder corruption
The holder appends a settled receipt for release even though no outcome was observed. Defended by:
- The settled receipt is signed by the holder's substrate, not the principal's. The relying party verifies both and cross-checks the disposition algorithm.
- The principal can pursue rail-side remedies (chargeback, regulator complaint) with the substrate receipts as evidence.
- A holder with a pattern of
release-without-outcomesettlements becomes detectable across many escrows — reputation contracts.
8.2 Outcome forgery
The outcome principal fakes a delivery receipt. Defended by:
- The outcome receipt must be on a substrate the holder trusts (see §5). Faking requires substrate-level access.
- For high-stakes payments, the principal SHOULD require multiple outcome receipts from independent principals (multi-confirm pattern, v1.1).
- Disputes by the original principal flip the disposition to
refund_disputed.
8.3 Timing attacks (last-minute outcome)
The outcome principal posts a delivered receipt one second before deadline_ns but the delivery didn't actually happen. Defended only by:
- Disputes by the principal (within the holder's pre-settlement window, typically
deadline_nstodeadline_ns + holder_grace_seconds). - v1.1 will add a
outcome_settled_at_grace_nsfield allowing the principal to issue a dispute up to N seconds after the deadline.
8.4 Substrate downtime
The holder cannot read the principal's substrate at deadline. Conservative behavior: stay in await until reachable, then run the algorithm. SLA breach belongs to the substrate operator, not the holder. The holder MAY define a maximum-await ceiling and transition to frozen after it; this is operator policy and SHOULD be advertised.
8.5 Dispute spam
A misconfigured dispute_principal issues a dispute on every escrow, freezing all funds. Defended by:
dispute_principalis set by the original principal at escrow creation — they choose carefully.- Reputation: a dispute_principal whose disputes never correlate with actual problems has high "wash-dispute" reputation, and downstream relying parties may discount their disputes.
9. Reference implementation
The TS SDK ships @deos/receipt/settlement exposing:
parseEscrow(receipt)— validate and parse asettlement.conditional/escrowreceipt.computeDisposition(escrow, source, now)— pure function implementing the §3 algorithm over aReceiptSource.metadataSubset(constraint, observed)— the metadata-match helper.
The TS verifier does not move funds — that is rail-specific. It produces the disposition a holder would act on.
The Maya substrate ships no holder code. A holder is whoever the principal contractually engaged; this spec defines what they have to honor.
10. Versioning
v1.0. The URI https://projectmaya.deoscomputing.io/settlement/conditional/v1 is immutable; breaking changes go to /v2.
Planned for v1.1:
- On-chain substrate-inclusion-proof bridge (EVM contracts verify outcomes without a trusted relayer).
- Multi-outcome required-of-N (the "two independent confirms" pattern for high-stakes payments).
- Post-deadline dispute grace window.
- Resolution flow out of
frozen(multisig of holder, principal, arbitrator).
11. Maintainer
DEOS Computing — pull requests, rail-integration prototypes, and threat-model critiques to github.com/DEOS-Computing.
License: CC BY 4.0 (text), Apache-2.0 (reference code).