CNT Proxy validates transactions through two app tags, dispatched in app_contract():
| Tag | Name | Purpose |
|---|---|---|
c |
Cellar | Enforces 1:1 backing between Cardano native assets and proxy tokens |
t |
Token | Fungible proxy token; delegates validation to the cellar |
Each Cardano native asset maps to a 32-byte proxy token identity:
identity = [0x00; 12] ++ blake2b_160(policy_id ++ asset_name)
ADA (lovelace) uses the same scheme with an empty input:
identity = [0x00; 12] ++ blake2b_160([])
The 12 zero-prefix bytes distinguish proxy token identities from other identity schemes.
All Cardano assets (ADA and CNTs) map to Charms tag t (fungible token).
The cellar is the core contract. It validates that the net change in Cardano native assets across cellar-marked UTXOs matches the net change in proxy tokens across the transaction.
Validation steps:
-
Find cellar UTXOs. Inputs and outputs are "cellared" if they contain a charm with tag
cand the app's VK. -
Extract Cardano assets. Parse each cellared UTXO's native content (Alonzo or Conway format) to get ADA lovelace and multiasset values.
-
Compute Cardano deltas. For each asset:
delta = output_amount - input_amount. Zero deltas are discarded. -
Compute proxy token deltas. For each proxy token app (same VK, tag
t) intx.app_public_inputs:delta = output_amount - input_amount. -
Compare deltas. The Cardano delta map must exactly equal the proxy token delta map. Any mismatch fails validation.
The token contract verifies that the cellar app (same VK, zeroed identity, tag c) is present in tx.app_public_inputs. All actual asset validation is handled by the cellar.