Skip to main content
The SettlementCoordinator is the core on-chain contract. It stores settlement state machine rules and enforces that every transition is valid. The settlement engine proposes transitions; the contract decides whether to accept them.

Functions

createSettlement()

Registers a new settlement on-chain with its state machine rules. This call is permissionless - anyone can call it. Gas cost is the natural spam filter.
function createSettlement(
    bytes32 settlementId,
    uint8 initialState,
    Transition[] transitions,
    Gate[] gates,
    bytes32[] partyHashes,
    uint256 timeoutAt
) external
ParameterDescription
settlementIdUUID converted to bytes32 (16 bytes UUID + 16 bytes zero padding)
initialStateIndex of the initial state in the template’s states list
transitionsArray of allowed (fromState, toState) pairs
gatesArray of (state, gateType) pairs defining preconditions
partyHashesKeccak256 hashes of party identifiers
timeoutAtUnix timestamp deadline for the settlement
The caller must specify both party wallet addresses (depositor addresses). The escrow contract validates that only the registered depositor for each leg can deposit. This means a malicious actor cannot create a settlement and trick an unrelated party into depositing. Emits: SettlementCreated(bytes32 settlementId)

transition()

Proposes a state transition. The contract validates the proposal against the registered rules and gate checks before accepting.
function transition(
    bytes32 settlementId,
    uint8 targetState,
    bytes32 evidenceHash
) external
ParameterDescription
settlementIdThe settlement to transition
targetStateIndex of the target state
evidenceHashSHA-256 of "fromState:toState:triggeredBy" for audit
The contract performs the following checks:
  1. Settlement exists and is not in a terminal state
  2. (currentState, targetState) is in the registered transitions list
  3. If the target state has a gate, the gate condition is met
  4. Caller is authorized (coordinator role)
Emits: StateTransition(bytes32 settlementId, uint8 fromState, uint8 toState, bytes32 evidenceHash)

timeout()

Triggers a timeout for an expired settlement. This call is permissionless - anyone can call it after the deadline. No dependency on KeyStone.
function timeout(bytes32 settlementId) external
The contract checks:
  1. Settlement exists and is not in a terminal state
  2. block.timestamp >= timeoutAt
When triggered, the coordinator dispatches rollback instructions to all escrow contracts (via LayerZero for cross-chain), returning deposits to their original owners. Emits: SettlementTimedOut(bytes32 settlementId)

View functions

function getSettlement(bytes32 settlementId) external view returns (Settlement)
function getState(bytes32 settlementId) external view returns (uint8)

Events

EventWhenPurpose
SettlementCreated(bytes32 settlementId)New settlement registeredAudit trail, indexer trigger
StateTransition(bytes32 settlementId, uint8 fromState, uint8 toState, bytes32 evidenceHash)Any state changeImmutable transition record
SettlementTimedOut(bytes32 settlementId)Timeout triggeredAudit trail, triggers rollback
These events form the complete settlement audit trail. Any third party can independently reconstruct the full settlement history by reading events from the chain.

Gate types

Gates are preconditions checked before a transition is accepted:
Gate TypeContract CheckedFunction Called
COMPLIANCE_CLEAREDComplianceRegistryareAllPartiesCleared(settlementId)
ALL_DEPOSITS_CONFIRMEDKeystoneEscrowallLegsDeposited(settlementId)
Gates are configured per-state at settlement creation time. The template’s action configuration determines which gates apply.

Access control

FunctionWho Can Call
createSettlement()Anyone (permissionless)
transition()Coordinator role only (KeyStone engine)
timeout()Anyone (permissionless, after deadline)
getSettlement() / getState()Anyone (view)
The coordinator role is the only privileged role. It allows the settlement engine to propose transitions. All other functions are either permissionless or view-only.

Data conversion

SourceTargetMethod
UUID (16 bytes)bytes32Right-pad with 16 zero bytes
State name (string)uint8Index in template’s states list
Evidencebytes32SHA-256 of "from_state:to_state:triggered_by"
Party identitybytes32keccak256(abi.encode(participantId_bytes32, walletAddress))