Attestation format
What is signed today, the EIP-712 payload it grows into, and the two fields that carry more weight than their size suggests.
Argued in full in the whitepaper at §7.
There are two formats on this page, and they are not the same thing. What Cleaton signs today is a seven-field canonical JSON. What §7 specifies, and what the registry will verify once it is deployed, is the EIP-712 struct below it.
What is signed today#
Canonical JSON — keys sorted alphabetically, every value a string — signed with personal_sign (EIP-191, secp256k1).
{"chainId":"4663","confidence":"0.65","expiresAt":"1787411823","horizonDays":"90","issuedAt":"1787325423","pool":"0xbeeff033f34c046626b8d0a041844c5d1a5409dd","v":"1"}| Field | Notes |
|---|---|
pool | Lowercase 20-byte address. Checksum casing would fork one pool into two digests. |
chainId | The subject chain. An address is unique within a chain, not across them, so the pair is the identity. |
horizonDays | The published horizon. |
confidence | Fixed two decimals, as text. Never a float — see below. |
issuedAt | Unix seconds; the API returns it under the same name. |
expiresAt | Unix seconds; the API returns it as expiry. Default validity 24h. |
v | Format version, "1". Signed, so a format change cannot be applied retroactively. |
The struct#
The specified on-chain form. Everything a consumer needs to decide whether to trust the claim is inside the signed payload — including how the liquidity was measured and which model produced the number.
struct Attestation {
address pool; // subject
uint256 chainId; // subject chain
bytes32 accountingId; // committed liquidity measurement method
uint256 refLiquidity; // TWAP liquidity at observation, 18 decimals
uint32 horizonDays; // published horizon H_pub
uint16 confidenceBps; // conformal coverage, basis points
uint16 thresholdBps; // retention threshold theta, basis points
uint64 observedAt; // observation timestamp
uint64 validUntil; // attestation staleness expiry
bytes32 modelHash; // model + pipeline commitment
bytes32 featureRoot; // Merkle root of feature vector
uint8 flags; // OUT_OF_SUPPORT, LOW_DATA, REGIME_SHIFT
uint64 nonce;
}Field reference#
| Field | Notes |
|---|---|
accountingId | Which function defines this pool’s liquidity — totalAssets() for an ERC-4626 vault, reserves against a reference price for a constant-product pool, supplied minus borrowed for a lending market. Registered at attestation time so it cannot be contested after a breach. |
refLiquidity | The six-hour time-weighted average at observation, 18 decimals. Never an instantaneous read. |
thresholdBps | The retention floor the horizon is measured against. Default 7000 — the claim is that liquidity holds at 70% of refLiquidity, not at 100%. |
modelHash | Hash of the serialised model artefacts and preprocessing pipeline. A methodology change produces a different hash, visible in the public record. |
nonce | Also determines calibration-set membership, fixed before outcomes are known — see calibrated confidence. |
featureRoot#
A Merkle root over the feature vector used for this specific attestation. Not every raw feature is published immediately — computing them is the operational work — but all of them are committed. Any individual feature can later be revealed with an inclusion proof through the Feature Disclosure surface.
The point is what it prevents: Cleaton cannot claim, after a miss, to have seen different inputs than it did.
validUntil is not the horizon#
Flags#
| Flag | Meaning |
|---|---|
OUT_OF_SUPPORT | The current feature distribution sits outside every calibration stratum. Confidence is reduced and the bond terms differ. Refusing to make a confident claim is a supported output. |
LOW_DATA | Too few rate-change events for a stable elasticity estimate; the value is hierarchically pooled toward its class mean. |
REGIME_SHIFT | Conformalised against a regime stratum that has recently changed. Treat coverage as weaker than stated. |