Skip to main content
Every settlement runs the dvp/v1 machine. The machine is fixed in code - templates select it (and pin it on the settlement as machine_version at creation) but cannot change its states or transitions. The on-chain KeystoneSettlement contract implements the chain-owned part of the machine natively.

One owner per state

Every state has exactly one owner - the only writer that can advance out of it: KeyStone never sends state-transition transactions. Its only chain writes are registerSettlement, the compliance attest, and the operator abort. Everything in the chain-owned region - deposits, execution, timeout, refunds - happens autonomously on the contract, and the observed events drive the settlement record.

The walk

  1. INSTRUCTED - Settlement created from matched instructions, machine version pinned. When the contract is configured, the engine registers the settlement on-chain: recipients bound per leg, deposit keys, party hashes, timeout.
  2. COMPLIANCE_CHECKING - The engine screens all parties via the template’s providers (LSEG entity screening, CipherOwl wallet screening). A failure routes to REJECTED - the terminal taxonomy for pre-deposit compliance failures.
  3. COMPLIANCE_CLEARED - Checks passed. The engine continues the walk.
  4. AWAITING_DEPOSITS - The handoff point. The engine yields; only contract events advance past here.
  5. SETTLED - The observed SettlementExecuted event landed: the contract paid out every leg atomically. The engine resumes for close-out bookkeeping.
  6. FINALIZED - Done.

Terminal states

MANUAL_REVIEW is not terminal: it parks a settlement for an operator after an operational dead end (a failed post-clearance action, or a stale settlement past its deadline in an engine-owned state).

Autonomous execution

On the last depositLeg, the contract checks the compliance gate (ComplianceRegistry.areAllPartiesCleared) and executes inline in the same transaction - every leg pays out to its recipient bound at registration, all-or-nothing. If attestations are still pending at the last deposit, the settlement stays registered and once the gate clears execute() can be called by the operator or any depositor: the caller only triggers the pre-committed plan, no one can steer it.

Depositor-driven recovery

Deposits and execution are live strictly before timeoutAt; recovery is live at and after it - the two windows never overlap. claimTimeout and claimRefund can be called by any depositor (or the operator) and cannot be paused - funds are never locked indefinitely, even if KeyStone is down. Refunds are per-leg pull payments: one blocked depositor can never strand another leg’s funds.

Events

The contract emits a fixed event set - SettlementRegistered, LegDeposited, SettlementExecuted, SettlementAborted, SettlementTimedOut, RefundClaimed, LegPaidOut, FeesCollected. These form the complete on-chain audit trail; KeyStone’s database mirrors them through a deduplicated indexer/webhook intake, mapping events to states by name through the settlement’s pinned machine.

Error handling

  • A failed engine action routes to the machine’s failure target for that state (REJECTED from compliance, MANUAL_REVIEW after clearance). If no legal failure transition exists, the settlement parks in place with a durable audit record instead of corrupting the walk.
  • A settlement past timeout_at in an engine-owned state escalates to MANUAL_REVIEW. TIMED_OUT itself only ever comes from the contract.
  • A chain event that contradicts the database state is surfaced to operators as a divergence - never silently absorbed, never retried forever.
See KeystoneSettlement for the full contract documentation.