Non-EVM Standards
Tezos CMTAT
Learn how Tezos CMTAT enables compliant multi-token transfers with built-in regulatory controls and permissioned features.
Tezos CMTAT (Compliant Multi-Token Asset Transfer), the Swiss-compliant token standard implemented on Tezos' self-amending blockchain, defines a regulatory-focused extension to FA2 (TZIP-012) for tokenizing equity, debt securities, and structured products with mandatory metadata, snapshots, and rule-based validation. For Real World Asset (RWA) protocols, this standard is especially valuable, as tokens can represent whole-unit claims on tokenized shares, bonds, or non-voting rights while maintaining a compliant, interoperable interface for transfers, minting, pausing, and external validations aligned with Swiss DLT Act and EU MiCA.
Before CMTAT, Tezos RWA projects adapted FA2 ad-hoc for compliance, leading to inconsistent metadata, siloed validations, and regulatory risks. CMTAT resolved this by mandating Swiss-legal fields (e.g., terms URI, no decimals) and integrating modules for snapshots and rule engines, leveraging Tezos' liquid proof-of-stake for verifiable, upgradable contracts. For RWA builders, the standard provides a certified abstraction layer supporting off-chain KYC via rules, oracle-fed snapshots, and asynchronous pauses, while enabling composability with DeFi protocols like Quipuswap or Plenty.
A key design principle is modular compliance, where contracts expose FA2 entrypoints augmented by CMTAT-specific hooks without exposing internal admin logic. This is well suited to RWA tokens where operations may depend on off-chain legal docs or board approvals, yet integrators like wallets or aggregators still need reliable, auditable flows.
Use of CMTAT in RWA Contexts
CMTAT is the foundational standard for compliant RWA tokens on Tezos because it abstracts the complexity of tokenizing and managing regulated assets into a FA2-extended, Swiss-legal framework. While traditional DeFi tokens use FA2 for unrestricted multi-token transfers, RWA tokens adapt the model to illiquid, securities-like assets, tokenized equity shares, debt instruments, structured products, or bond portfolios, where on-chain tokens represent legally backed off-chain value held by custodians or SPVs, with rule engines for Swiss/EU regulations like Article 973d CO or MiCA.
Key Applications in RWA Development
Fractional Ownership and Liquidity Provision
Many RWAs are high-value and indivisible (for example, a ten-million-dollar equity stake or a portfolio of debt notes). CMTAT allows developers to mint whole-unit tokens (decimals=0) proportional to deposits, unlocking ownership and secondary-market liquidity under compliance rules.
- Implement
transferwith rule engine to restrict to authorized holders via external validation. - Tokens can trade freely on DEXs like Quipuswap within policy bounds, offering liquidity for assets that would otherwise be locked for years.
- Example: An equity token where metadata links to prospectus, and snapshots track eligible shareholders for rights.
Yield Accrual and NAV Management
Snapshot mechanisms automate dividend distribution (e.g., interest from debt tokens), with schedule_snapshot querying oracles (e.g., Chainlink) for historical balances at timestamps. This supports merkle-based claiming without manual interventions, ideal for tokenized securities or funds.
Using trusted sources (Chainlink, Pyth) ensures accurate historical ledgers, critical for compliance and for investor claims. Regulators increasingly expect transparent snapshot reporting, and CMTAT provides this without exposing internal rule state.
Redemption and Settlement Mechanics
RWA redemptions are inherently asynchronous, as physical settlement layers (banks, custodians, transfer agents) cannot finalize instantly.
Patterns include:
burnwith pause for queued releases.- Rule engine revocations for invalid holdings.
- Memo callbacks for signed claims.
- Proof-of-reserve checks before fulfillment.
These guardrails prevent unauthorized burns and ensure token solvency, especially for semi-liquid assets like private credit or T-bills.
Composability Across the RWA Stack
CMTAT tokens plug directly into Tezos DeFi:
- Plenty accepts tokens as collateral within rule restrictions.
- Quipuswap pairs can provide deep secondary liquidity for permitted transfers.
- Aggregators (e.g., Kelp) route into CMTAT natively.
For regulated RWAs:
- Pair with rule engines for investor eligibility gating.
- Combine with snapshots for modular corporate actions.
- Integrate identity proofs via metadata.
This drastically reduces integration complexity, for example, a tokenized bond token can list across lending markets without custom adapters.
Developer Advantages in RWA Builds
- Regulatory Alignment: Mandatory metadata and rule engines hide off-chain legal processes while preserving accurate validations for Swiss DLT Act/MiCA-aligned disclosures.
- Extensibility: External rule contracts and snapshots allow injecting RWA-specific logic i.e., pricing oracles, geofencing, or IPFS-pinned compliance policies.
- Risk Isolation: Tokens remain fully FA2 compliant, pauses do not impact wallet-held balances outside rules.
- Upgrade Path: Tezos governance enables self-amends, preserving TVL and simplifying audits.
To visualize the end-to-end flow in an RWA token, the following sequence diagram captures the typical mint - transfer - snapshot cycle. It illustrates how users interact with the CMTAT contract, how rules interact with engines and oracles, and how off-chain compliance updates flow back on-chain through validations or callbacks. This representation is especially important for understanding asynchronous transfers, delayed settlements, and rule-driven compliance in RWA systems.
This diagram highlights how CMTAT acts as the connective tissue between on-chain token operations and off-chain asset realities. Mints enforce rules proportional to issued value, engines capture real-world compliance as transfers execute, and snapshot functions help manage distributions during corporate actions. For illiquid RWA portfolios, the model can be extended with explicit rule modules between the contract (C) and the custodian or SPV (Cust) to handle delayed settlement cycles.
Core Specification
A CMTAT contract must implement the FA2 (TZIP-012) interface extended with CMTAT entrypoints for its multi-token structure, the compliant representation of a user’s whole-unit claim on the underlying security. Optional rule engines enable advanced features like transfer validation, a valuable enhancement for RWA use cases where institutions manage access without needing full custom contracts.
In CMTAT, the contract behaves like any FA2 token (balance queries, total supply via views, transfers), while token_id refers to appended modules for securities management. The specification enforces a clean separation between base ledgers and compliance params, ensuring predictable operations and seamless integration across Tezos and RWA systems.
Key Definitions
- Token ID: The nat identifier for security types within the contract, e.g., 0 for equity shares or 1 for debt notes.
- Ledger: The big_map storage for balances, extensible for single/multi-token with decimals=0.
- Total Supply: The aggregate token value managed by the contract, equal to the sum of principal, snapshotted amounts, and adjustments for fees or burns.
- Rule Engine: External contracts (e.g., FreezeRuleEngine) providing validation hooks for transfers, freezes, and compliance.
- Entrypoint Functions: (e.g., transfer, schedule_snapshot) Provide near-exact estimates of expected outcomes, reflecting rules, rounding, or terms changes, without executing state updates. These enable accurate transaction planning.
- Rounding Rules: CMTAT mandates rounding in favor of the contract (decimals=0):
- Round down when issuing tokens or deductions, preventing dilution.
- Round up when applying rules or requirements, protecting existing participants. These rules ensure fair distribution and discourage precision-based attacks.
CMTAT defines FA2 core plus 10+ CMTAT entrypoints, organized by their roles in transfers, admins, snapshots, and rules. Every contract implements these atomically, ensuring a single source of truth for behavior and movements. Below is the Ligo-equivalent interface (adapted from SmartPy), accompanied by developer notes covering edge cases, rounding behavior, and considerations specific to RWA tokens such as asynchronous rules and oracle-driven updates.
1// Ligo (PascaLigo) CMTAT Interface (FA2 Extended)
2type token_id = nat;
3type balance = nat; // Decimals = 0
4type transfer = (address * (address * (token_id * balance)));
5type transfer_list = list(transfer);
6type transfer_param = (address * transfer_list);
7
8type balance_request = (address * token_id);
9type balance_response = ((address * token_id) * balance);
10type balance_callback = list(balance_response);
11
12type snapshot_request = (address * token_id * timestamp);
13type snapshot_response = ((address * token_id * timestamp) * balance);
14type snapshot_callback = list(snapshot_response);
15
16type rule_engine = contract(bool); // External validation
17
18type fa2_entry_points =
19 | Transfer of transfer_param
20 | Balance_of of (list(balance_request) * contract(balance_callback))
21 | Update_operators of list((address * address * token_id));
22
23type cmtat_entry_points =
24 | Mint of (token_id * balance * address) // Admin mint
25 | Burn of (token_id * balance * address) // Admin burn
26 | Pause of token_id // Pause token
27 | Unpause of token_id
28 | Schedule_snapshot of (token_id * timestamp)
29 | Set_rule_engines of (token_id * list(rule_engine))
30 | Set_token_metadata of (token_id * bytes) // URI or inline
31 | Propose_administrator of (token_id * address)
32 | Confirm_administrator of (token_id * address)
33 | Kill of unit; // Destroy contract
34
35type full_entry_points = or(fa2_entry_points, cmtat_entry_points);
36
37// Views
38type view_balance_of_param = (address * token_id);
39type view_balance_of_response = balance;
40
41type view_snapshot_balance_of_param = (address * token_id * timestamp);
42type view_snapshot_balance_of_response = balance;
Detailed Function Breakdown (with RWA Developer Notes)
Below is an entrypoint-by-entrypoint explanation of the CMTAT interface, including edge cases, rounding behavior, and RWA-specific implementation guidance for regulated assets, off-chain settlement, and rule-driven validation.
Transfer
FA2 batch transfers with pre/post hooks to rule engines. In RWA tokens, this enforces validation for tokenized equity, debt wrappers, or structured notes.
- This is atomic; partial failure reverts all.
Mint / Burn
Admin-only supply changes for token_id, checked against rules.
- RWA Integration: For compliance-based assets, tie to oracle-fed issuances (Chainlink / Pyth).
- Edge Case: Must handle zero amounts or undefined token_ids (error: CMTAT_TOKEN_UNDEFINED).
Pause / Unpause
Toggles operations for token_id.
- Formula: Global flag per token.
- Usage: UI quoting, risk dashboards.
- RWA Note: Reflects pure regulatory pause, does not account for settlement delays or custody fees.
Schedule_snapshot
Queues balance snapshot at future timestamp for token_id.
- Ensures no precision-based arbitrage on historicals.
- RWA Note: Useful for dividend eligibility in regulated markets.
Set_rule_engines
Attaches list of external contracts for validation.
- Return empty for “no rules.”
- RWA Note: Enforce investor caps, jurisdiction restrictions, or temporary freezes due to regulatory flags.
Set_token_metadata
Sets URI/inline bytes for token_id (mandatory fields: name, terms).
- Discrepancies vs FA2 reveal compliance impact.
- RWA Note: Useful for quote generation in metadata-heavy vaults or those with legal fees.
Propose_administrator / Confirm_administrator
Two-step admin transfer for token_id.
- Requires prior proposal check.
- Includes errors for unauthorized (e.g., CMTAT_NOT_ADMIN).
- RWA Note:
- For illiquid assets (such as real estate and private credit): pair with pause asynchronous resolutions.
- Trigger oracle checks for board approval validation.
Kill
Super-admin destroys contract (token_id 0 only).
- Irreversible; burns all.
- RWA Use Case: Deactivation for token switch per Swiss law.
Reference Implementation
CMTA’s CMTAT-Tezos-FA2 offers a mature, audited foundation for building compliant tokens via SmartPy. The implementation extends FA2, providing a clean entrypoint surface for RWA-specific logic. Its design encourages minimal overrides while still supporting custom rule models, snapshot maps, admin flows, and oracle integration.
Key capabilities include:
- Inflation Attack Protection: The implementation prevents dilution by enforcing admin mints and rule invariants. Early admins cannot exploit low-supply corner cases to extract excess value.
- Rounding Compliance: All operations use nat arithmetic for precise, deterministic handling (decimals=0) that adheres to CMTAT requirements of whole-unit rounding in favor of the contract. This eliminates subtle precision-drift exploits.
- Extensible Rules: Hooks such as view_is_transfer_valid allow developers to embed RWA-specific functionality, NAV oracle checks, compliance gating, settlement status validation, or fee accounting, without modifying core logic.
- Flexible Structure: CMTAT builds on FA2’s base, with optional governance or access controls for regulated administration. This makes it straightforward to integrate custodial controls, upgrade pathways, or rule-gated operations required in regulated RWA environments.
1// Ligo Snippet (Adapted from SmartPy for CMTAT Transfer with Rule)
2type storage = {
3 ledger : big_map((address * nat), nat);
4 token_metadata : big_map(nat, bytes);
5 rule_engines : big_map(nat, list(contract(bool)));
6 admins : big_map(nat, address);
7 paused : big_map(nat, bool);
8 snapshots : big_map((nat * timestamp), big_map((address * nat), nat));
9 policy : transfer_policy; // CMTAT-specific
10};
11
12let validate_transfer = fun (token_id : nat) (tx : transfer) (s : storage) : unit =
13 if Big_map.mem token_id s.paused && s.paused[token_id] then
14 failwith "CMTAT_PAUSED"
15 else
16 let engines = match Big_map.find_opt token_id s.rule_engines with Some e -> e | None -> [] in
17 let check_engine = fun (e : contract(bool)) (valid : bool) : bool =
18 let op = transaction((tx.0, tx.1.0, tx.1.1), 0tez, e) in // Simplified CPI
19 valid && true // Assume response
20 in
21 let all_valid = List.fold check_engine engines true in
22 if not all_valid then failwith "CMTAT_RULE_VIOLATION" else unit;
23
24let transfer = fun (p : transfer_param) (s : storage) : (list(operation) * storage) =
25 let src = p.0 in
26 let txs = p.1 in
27 let validate_all = List.iter (fun (tx : transfer) -> validate_transfer tx.1.1.0 tx s) txs in
28 let update_ledger = fun (tx : transfer) (l : big_map((address * nat), nat)) : big_map((address * nat), nat) =
29 let key_from = (src, tx.1.1.0) in
30 let bal_from = match Big_map.find_opt key_from l with Some b -> b | None -> 0n in
31 let key_to = (tx.1.0, tx.1.1.0) in
32 let bal_to = match Big_map.find_opt key_to l with Some b -> b | None -> 0n in
33 if bal_from < tx.1.1.1 then failwith "FA2_INSUFFICIENT_BALANCE" else
34 let new_bal_from = bal_from - tx.1.1.1 in
35 let new_bal_to = bal_to + tx.1.1.1 in
36 let l' = Big_map.remove key_from l in
37 let l'' = if new_bal_from = 0n then l' else Big_map.add key_from new_bal_from l' in
38 Big_map.add key_to new_bal_to l''
39 in
40 let new_ledger = List.fold (fun (acc, tx) -> update_ledger tx acc) txs s.ledger in
41 ([] : list(operation), { s with ledger = new_ledger });
42
43// Snapshot Scheduling
44let schedule_snapshot = fun (params : (nat * timestamp)) (s : storage) : (list(operation) * storage) =
45 let token_id, ts = params in
46 let new_snap = Big_map.map (fun ((addr, tid), bal) -> bal) s.ledger in // Copy at schedule? Future eval
47 let snapshots' = Big_map.add (token_id, ts) new_snap s.snapshots in
48 ([] : list(operation), { s with snapshots = snapshots' });
- The transfer pins rules at storage. For RWA tokens, prefer external engines and link metadata to IPFS for terms.
- Ledger can be extended for snapshot mode in UIs.
Transfer Flow (User-Facing)
User-level entrypoints call core logic with rules.
1// As above in transfer()
2// Pre-transfer: Rule CPI to engines
- Use atomic batches for safe multi-txns.
- Override pre-transfer to add compliance checks (KYC, terms) and revert early if rule fails.
- For illiquid or async-backed assets, combine transfer with provisional mints and oracle finalization to avoid over-issuance.
Mint Flow
Symmetric to transfer, mint updates ledger post-admin confirm.
1let mint = fun (params : (nat * nat * address)) (s : storage) : (list(operation) * storage) =
2 let token_id, amount, to_addr = params in
3 let admin = match Big_map.find_opt token_id s.admins with Some a -> a | None -> failwith "CMTAT_NOT_ADMIN" in
4 if not (Tezos.sender = admin) then failwith "CMTAT_UNAUTHORIZED" else
5 let key_to = (to_addr, token_id) in
6 let bal_to = match Big_map.find_opt key_to s.ledger with Some b -> b | None -> 0n in
7 let new_bal_to = bal_to + amount in
8 let ledger' = Big_map.add key_to new_bal_to s.ledger in
9 ([] : list(operation), { s with ledger = ledger' });
- Admin-first follows checks-effects-interactions and reduces reentrancy risk.
- For queued mints, implement off-chain proposal for board.
- Add mint limits via rules.
Snapshot Flow
Default snapshots are timestamped; RWA overrides query historicals.
1let view_snapshot_balance_of = fun (params : (address * nat * timestamp)) (s : storage) : balance =
2 let addr, token_id, ts = params in
3 let snap_key = (token_id, ts) in
4 match Big_map.find_opt snap_key s.snapshots with
5 | Some snap -> match Big_map.find_opt (addr, token_id) snap with Some b -> b | None -> 0n
6 | None -> match Big_map.find_opt (addr, token_id) s.ledger with Some b -> b | None -> 0n;
- Snapshot uses map copy for precision.
- Consider a staleness policy for queries.
Adding Rule Engine (Example: Freeze Check)
Rule handling keeps execution consistent.
1// External contract view_is_transfer_valid
2let is_transfer_valid_cpi = fun (from, to, tid) (engine : contract(bool)) : bool =
3 let param = (from, to, tid) in // Simplified
4 let op = transaction(param, 0tez, engine) in
5 true; // Assume success response
- Keep rule accounting transparent: Emit events via callbacks and track via explorer.
- For RWA products, rules may address regulatory events, document in metadata.

