Attestations
The EIP-712 KYC and fee attestation model that authorizes every AsseteraExchange action.
Assetera authorizes each on-chain action by issuing a single-use, signed approval: an EIP-712 attestation. Every state-changing call on AsseteraExchange must carry one, and it authorizes exactly one action. This keeps personal data and business rules off chain: the contract only checks a signature from a trusted operator role. See Compliance gating for the wider model.
KYC attestation
Each KYC-gated call takes a KycAttestation in calldata (two, for two-party settlement). It is
not stored on chain: it is verified, its nonce is burned, and a KycConsumed event records that
it was consumed. It is signed by the operator key holding KYC_OPERATOR_ROLE.
Key fields:
| Field | Purpose |
|---|---|
account | The user the attestation is for; must equal _msgSender(). |
action | Which action it authorizes (Place, Fill, Settle, MakeOffer, ReplaceOffer, AcceptOffer, CancelOffer, SettleOffer, …). |
orderId | The order/offer it binds to (0 for Place / MakeOffer, which have no id yet). |
nonce | Single-use; a consumed nonce cannot be replayed (usedNonce(account, nonce)). |
deadline | Time-bound; expires, and cannot exceed the contract's MAX_KYC_TTL. |
paramsHash | Binds the attestation to the exact call parameters. |
signature | The KYC operator's EIP-712 signature over the above. |
Because each attestation is bound to one account, one action, one orderId, one nonce, and a
short deadline, it cannot be reused, retargeted at a different action, or replayed. The action set is
deliberately granular: for example a CancelOffer attestation can never be replayed as a Cancel.
Fee attestation
Fees are a separate concern from compliance, so they are being moved out of the KYC attestation
into their own FeeAttestation, signed by a distinct FEE_OPERATOR_ROLE. It mirrors the KYC
pattern: single-use nonce (its own namespace), deadline bound by MAX_FEE_TTL, a paramsHash, and
the fee terms makerFeeBps / takerFeeBps / feeCollector.
Only the fee-setting actions (placeOrder, placeOrderWithPermit, makeOffer) take both
a KYC and a fee attestation. The two are bound together: same account, same paramsHash, same
action, and both are verified before either nonce is burned. Downstream actions (fillOrder,
cancelOrder, settlement) carry only a KYC attestation and read the fee terms already snapshotted
onto the order or offer. The contract still re-checks the fee cap and the collector allowlist on
chain as defence in depth.
Roadmap: fee decoupling is not yet shipped and is off-chain-breaking: it changes the
calldata of placeOrder / makeOffer and both EIP-712 typehashes, so backend signing and the
event schema must move in lockstep. On the current testnet contract (v3.1.0) the fee fields
(makerFeeBps, takerFeeBps, feeCollector) still live inside the KycAttestation and are
signed by the KYC operator. Treat the separate fee attestation as the production target, not the
current testnet behaviour.
How attestations are produced
A user never signs an attestation themselves. They request an action through the Assetera app; Assetera decides whether it is allowed; and Assetera's attestation authority (an operator key Assetera controls) issues the matching single-use EIP-712 signature. The (gasless, ERC-2771-relayed) call then carries that attestation on chain.
Because approval is gated by Assetera, a frozen or non-compliant user is stopped simply by Assetera declining to issue an attestation: no on-chain block list is needed. See the Assetera app for the user-facing side and Compliance gating for the wider model. For what the contract does once an attestation is accepted, see the Order lifecycle and Offer lifecycle.
Events
The AsseteraExchange event catalog: what each event means, its indexed fields, and the meta-transaction actor model.
Issuer portal
Where a token issuer signs in to configure and issue their own tokenized assets. Listing details, catalog status, and compliance metadata. Currently in build and role-gated.