AsseteraAssetera Docs
Smart contracts

Attestations

The EIP-712 KYC and fee attestation model that authorizes every AsseteraECS action.

Assetera authorizes each on-chain action by issuing a single-use, signed approval: an EIP-712 attestation. Every state-changing call on AsseteraECS 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.

The EIP-712 domain name

The domain separator every attestation is signed under uses the name "AsseteraExchange", not AsseteraECS. This is deliberate and is not a typo.

EIP712Domain(name: "AsseteraExchange", version: "1", chainId, verifyingContract)

The venue was renamed to AsseteraECS, but the domain name is written into the deployed proxies' ERC-7201 namespaced storage by the initializer, which runs exactly once at deploy time. It cannot be changed by an upgrade, and changing it would in any case change the domain separator and invalidate every attestation already signed. So for the current deployments the domain name stays "AsseteraExchange". Hardcode that literal when you build the typed data, or read it from eip712Domain() on the contract.

Signing under "AsseteraECS" produces a different domain separator, and the contract will reject the attestation as an invalid signature. This is the one place the old name survives on purpose.

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:

FieldPurpose
accountThe user the attestation is for; must equal _msgSender().
actionWhich action it authorizes (Place, Fill, Settle, MakeOffer, ReplaceOffer, AcceptOffer, CancelOffer, SettleOffer, …).
orderIdThe order/offer it binds to (0 for Place / MakeOffer, which have no id yet).
nonceSingle-use; a consumed nonce cannot be replayed (usedNonce(account, nonce)).
deadlineTime-bound; expires, and cannot exceed the contract's MAX_KYC_TTL.
paramsHashBinds the attestation to the exact call parameters.
signatureThe 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 live in 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.

Both attestations are verified, and both nonces burned, before the order or offer is created. The fee terms are then snapshotted on chain, so every later action on that order or offer needs only a KYC attestation. The contract re-checks the fee cap and the collector allowlist on chain either way.

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.

On this page