Assetera Docs
Smart contracts

AsseteraECS

AsseteraECS (Execution, Clearing and Settlement): the escrow-based, UUPS-upgradeable, gasless, compliance-gated order and offer book behind Assetera trading.

AsseteraECS (Execution, Clearing and Settlement) is the Solidity contract that settles secondary trading on Assetera. It holds an order book and a targeted-offer book, escrows the tokens users trade, and gates every state change behind an off-chain compliance attestation. It is the on-chain record of what was traded, by whom, and under which terms.

A first acquisition settles somewhere else

A buyer's first acquisition of an asset goes through a different contract, with its own address, its own roles and its own EIP-712 domain. See Primary issuance.

What it is

PropertyWhat it means for you
Escrow-based, with no on-chain matching engineMakers post priced limit orders and the contract escrows the sell side at once. A taker executes against a specific order id, and nothing on chain scans the book for crosses. Every execution is an explicit call against an order the caller chose, which is why the lifecycle pages describe transitions rather than a matching algorithm.
UUPS-upgradeable (ERC-1967)Logic lives in an implementation behind a single proxy. Always index and interact with the proxy address. Confirm the live implementation via the eip1967.proxy.implementation storage slot.
Gasless (ERC-2771 meta-tx)Users pay no gas and hold no native tokens. Calls are relayed through a trusted Forwarder; the contract resolves the real actor with _msgSender(). Read identity from the address in each event (maker, taker, account, by, proposedBy), never from tx.from. See Events.
Compliance-gatedEvery state-changing call carries a single-use, deadline-bound EIP-712 KYC attestation signed off-chain. Fee terms travel in a separate fee attestation. See Attestations.
Source availableThe Solidity source, tests and audit scope are public: Assetera-AG/AsseteraEvmContracts. Read the contract itself in contracts/src/AsseteraECS.sol and the review boundary in AUDIT-SCOPE.md. Links are pinned to the evm-contracts-v8.1.0 tag so they cannot rot.

Formerly AsseteraExchange

The rename is cosmetic. Deployed addresses, the ABI, event and function selectors, and the storage layout are all unchanged, so no redeploy or migration is involved. One identifier deliberately keeps the old spelling, the EIP-712 domain name. See Attestations.

Roles

The contract uses OpenZeppelin AccessControl. The roles an integrator should know about:

RolePurpose
DEFAULT_ADMIN_ROLEGovernance: upgrades, pause/unpause, compliance toggles, fee-collector allowlist, and the emergency cancelOrderForUser / cancelOfferForUser exits. Held by a Safe multisig in production.
KYC_OPERATOR_ROLEThe operator key whose EIP-712 signature authorizes each KYC-gated action.
FEE_OPERATOR_ROLEThe operator key whose EIP-712 signature sets the fee terms snapshotted onto an order or offer.

Fee terms are authorized by a separate FeeAttestation signed by FEE_OPERATOR_ROLE, not the KYC attestation. See Attestations.

Where it runs

AsseteraECS is deployed on four networks: Ethereum and Polygon (mainnets), and Sepolia and Polygon Amoy (their testnets). Pick a network for its contract addresses:

Addresses exactly as published in @asseteragmbh/evm-contracts, the version these docs are built against.

Chain ID 1 · CAIP-2 eip155:1 · deployed at block 25,795,740

ContractAddress (integrate against this)
AsseteraECS0xf045d3FE81C14d8c13DbaB0b03a4Ea1505e499ad
AsseteraPrimarySales0xF62757dd232DC7582A5d46F62aAcDb6B739223Dc
Forwarder0x2244B33a97f91284D53d0A12d42F237927C3DBf7

Behind the proxy. The addresses above are the stable ones. The UUPS implementation below is what the proxy currently delegates to. It is useful for verifying the deployed bytecode, but it changes on every upgrade, so never hardcode it.

ContractImplementation (changes on every upgrade)
AsseteraECS0xF2f8Dfd9bbc1AD2A78447A0196deC84e3397737B
AsseteraPrimarySales0xB6De6C29f039ed53e993f916961A758D32C13c11

Chain ID 137 · CAIP-2 eip155:137 · deployed at block 92,344,157

ContractAddress (integrate against this)
AsseteraECS0xf045d3FE81C14d8c13DbaB0b03a4Ea1505e499ad
AsseteraPrimarySales0xF62757dd232DC7582A5d46F62aAcDb6B739223Dc
Forwarder0x2244B33a97f91284D53d0A12d42F237927C3DBf7

Behind the proxy. The addresses above are the stable ones. The UUPS implementation below is what the proxy currently delegates to. It is useful for verifying the deployed bytecode, but it changes on every upgrade, so never hardcode it.

ContractImplementation (changes on every upgrade)
AsseteraECS0xB6De6C29f039ed53e993f916961A758D32C13c11
AsseteraPrimarySales0xCb0ef38528fd695116B745722d7d03485584175F

Chain ID 80002 · CAIP-2 eip155:80002 · deployed at block 45,229,125

ContractAddress (integrate against this)
AsseteraECS0xf045d3FE81C14d8c13DbaB0b03a4Ea1505e499ad
AsseteraPrimarySales0xF62757dd232DC7582A5d46F62aAcDb6B739223Dc
Forwarder0x2244B33a97f91284D53d0A12d42F237927C3DBf7
MockRWA0xECe9f75Eb6af58B7c70773BbC5922E49fD65F3E0
MockUSDC0x85D7B2569b3d69320F05A4FFB140Ca4521989A15

Behind the proxy. The addresses above are the stable ones. The UUPS implementation below is what the proxy currently delegates to. It is useful for verifying the deployed bytecode, but it changes on every upgrade, so never hardcode it.

ContractImplementation (changes on every upgrade)
AsseteraECS0xB6De6C29f039ed53e993f916961A758D32C13c11
AsseteraPrimarySales0xC0c7F32806a8C99287151B7F4886Ef2CDEFf2C7d

Chain ID 11155111 · CAIP-2 eip155:11155111 · deployed at block 11,514,803

ContractAddress (integrate against this)
AsseteraECS0xf045d3FE81C14d8c13DbaB0b03a4Ea1505e499ad
AsseteraPrimarySales0xF62757dd232DC7582A5d46F62aAcDb6B739223Dc
Forwarder0x2244B33a97f91284D53d0A12d42F237927C3DBf7
MockRWA0xECe9f75Eb6af58B7c70773BbC5922E49fD65F3E0
MockUSDC0x85D7B2569b3d69320F05A4FFB140Ca4521989A15

Behind the proxy. The addresses above are the stable ones. The UUPS implementation below is what the proxy currently delegates to. It is useful for verifying the deployed bytecode, but it changes on every upgrade, so never hardcode it.

ContractImplementation (changes on every upgrade)
AsseteraECS0xB6De6C29f039ed53e993f916961A758D32C13c11
AsseteraPrimarySales0xC0c7F32806a8C99287151B7F4886Ef2CDEFf2C7d

The ABI and every address above are published with each deployment in the TypeScript SDK; resolve them from the package rather than hardcoding.

The same address on every chain, and why that is safe to rely on

AsseteraECS, AsseteraPrimarySales and the Forwarder each carry the same proxy address on all four chains, because they are deployed with CREATE3. The implementation behind each proxy differs per chain, which is what the second table on each tab shows.

Address your calls to the proxy, and read the live implementation from the eip1967.proxy.implementation storage slot rather than from a document. Resolve even the proxy from the SDK: a chain with no deployment record returns undefined, which is the correct way to learn that a contract is not available there.

Where to go next

Read the source

The contract repository is public. These deep links are pinned to the evm-contracts-v8.1.0 tag.

FileWhat it covers
contracts/src/AsseteraECS.solThe assembled contract: UUPS, ERC-2771 and the initializer, over the OrderBook / OfferBook modules.
contracts/AUDIT-SCOPE.mdThe combined review boundary, and the entry point to the two below.
contracts/AUDIT-SCOPE-SECONDARY.mdThis contract's own scope: the order book and the offer book.
contracts/AUDIT-SCOPE-PRIMARY.mdThe settlement router's scope. A separate proxy, reviewable on its own.
contracts/docs/FUNCTIONAL_SPEC.mdThe behavioural specification the lifecycle pages summarize.
contracts/docs/INDEXER_EVENT_SCHEMA.mdThe event schema of record: canonical signatures, topic0 hashes, error selectors.

On this page