Skip to main content
The ComplianceRegistry stores compliance attestations on-chain, authorized by an M-of-N threshold of attester signatures (EIP-712). The KeystoneSettlement contract consults this registry as its execution gate: every party hash bound at registration must be attested Pass before the contract pays out. Screening and attestation are the only steps that require KeyStone’s off-chain involvement - everything else is handled autonomously by the contract.
The attester set is immutable per deployment and the threshold gate is enforced entirely on-chain. Who operates the keys in that set is a separate question from what the contract enforces: on the current testnet deployments KeyStone operates all of them. See attester operation below.

How it works

  1. Off-chain compliance screening runs per party via LSEG World-Check (entity) and CipherOwl (wallet)
  2. On a passing result, an EIP-712 Attestation message is signed by M of the N configured attester keys
  3. The signed bundle is submitted on-chain: attest(attestation, signatures). The submitter is not trusted - the signatures authorize, so no single key (and no submitter) can forge a Pass
  4. At the last deposit (or a later execute() call), the KeystoneSettlement contract calls areAllPartiesCleared(settlementId, partyHashes) with the hashes bound at registration
  5. If every bound hash has a passing attestation, the settlement executes; otherwise it stays registered until attestation lands

Functions

attest()

Submit an M-of-N signed compliance attestation for a party in a settlement.
The registry verifies the bundle before writing anything:
  • Pass only. Only Pass attestations exist on-chain - a failed or flagged screening is never written to the registry; the gate simply never clears for that party. Any other status reverts InvalidComplianceStatus.
  • Deadline. A bundle submitted after deadline reverts AttestationExpired, so a leaked old signature cannot be replayed indefinitely.
  • M-of-N signatures. Each signature must recover to a configured attester, signers must be in strictly ascending address order (rejects duplicates), and at least the threshold M must be present - otherwise SignersNotSortedOrDuplicate, UnknownAttester, or ThresholdNotMet.
  • Sequence. Re-attesting the same party increments a per-record sequence counter, so downstream systems can distinguish the first attestation from a re-screen.
No personal data is stored on-chain. The partyHash is a one-way hash that cannot be reversed to identify the party. The referenceHash is a hash of the provider’s reference ID, not the ID itself.

isCleared()

Check if a specific party has a passing attestation.

areAllPartiesCleared()

Check if every supplied party hash has a passing attestation for the settlement. This is the function the KeystoneSettlement contract calls as its execution gate, passing the party hashes bound at registration (the gate can never pass vacuously - registration rejects empty hash lists).

Party hash computation

Party hashes are computed as keccak256(abi.encode(partyId_bytes32, walletAddress)). The same inputs MUST be used at registration (KeystoneSettlement partyHashes) and at attestation, or the gate never clears: This allows separate attestations for entity-level and wallet-level screening while maintaining a consistent hashing scheme.

Status mapping

Off-chain, KeyStone tracks three screening outcomes per party: PASS, FLAGGED, and FAIL. On-chain, only one of them ever becomes a record: Deposits are still accepted while the gate is closed - only execution is blocked. The ComplianceStatus enum retains Flagged (2) and Fail (3) values for ABI compatibility, but attest rejects them.

Immutable M-of-N threshold

The attester set and the threshold are fixed at deployment and immutable: the contract has no function to add or remove an attester or to change the threshold. Changing the set means deploying a fresh registry, deploying KeystoneSettlement against it, and repointing the backend - a visible, coordinated, multi-step operation that cannot happen in a single transaction. There is no on-chain path to forge a Pass. The pause authority (PAUSER_ROLE, with DEFAULT_ADMIN_ROLE existing only to rotate it) is halt-only: it can freeze new attestations in an emergency but cannot forge, alter, or delete one.

Attester operation

The current testnet deployments run a 2-of-3 attester set, and KeyStone operates every key in it as an interim arrangement. What the contract guarantees and what the deployment currently delivers are therefore different things, and it is worth being precise about which is which: The design goal is independent attester operators, at which point no single organization can clear the gate alone. Until then, the honest description of the gate is that it prevents any other party from clearing a settlement, and that KeyStone can decline to clear one. Neither the contract nor any key in the set can redirect a payout: an attestation permits a settlement to execute along the path fixed at registration and carries no recipient or amount.

Events

What KeyStone stores

KeyStone never stores raw KYC/AML data. The compliance flow stores: The compliance provider (LSEG, CipherOwl) remains the source of truth for the actual screening data. KeyStone only records the outcome.