Proof of Reserves
Under MiCA (Art. 22, Art. 56), EMT issuers must periodically report the value of issued tokens and demonstrate that reserves cover all outstanding supply. In a standard ERC-20 this is trivial — totalSupply() is public. In a privacy system, it is not: individual balances are ElGamal ciphertexts (and later UTXOs), and the total amount held across all users is not directly observable on-chain.
The total encrypted supply equals the total amount of public tokens shielded minus the total unshielded. Tracking this via public counters would work, but it would leak information about particular burns (and hence private offramps). Instead, the total supply is stored as an encrypted counter that only an authorized party (auditor, regulator, or reserve custodian) can decrypt.
Encrypted Total Supply Counter
The contract stores a single ElGamal ciphertext TS = (R_ts, C_ts) encrypted under a dedicated total_supply_key (a Grumpkin public key). This counter is updated homomorphically on every operation that changes the total amount held in the concealed and shielded layers:
| Operation | Effect on total supply counter |
|---|---|
| Concealed burn (encrypted → nowhere) | TS -= Enc(amount, total_supply_key, r) |
| Public burn (Public → nowhere) | TS -= Enc(amount, total_supply_key, r) |
| Mint to public | TS += Enc(amount, total_supply_key, r) |
| Mint to concealed (if ever supported) | TS += Enc(amount, total_supply_key, r) |
The counter starts at the identity ciphertext (O, O), which encrypts zero.
On-chain mechanics
The contract stores:
mapping(address => (Point, Point)) public encryptedTotalSupply;
Point public totalSupplyKey;
On each mint/burn, the contract performs ElGamal homomorphic addition (or subtraction) on encryptedTotalSupply[token] using the amount and a fresh randomizer. For public-amount operations (mint to public, public burn, mint to concealed), the contract computes Enc(amount, TPK, r) on-chain — no circuit changes needed. For concealed burns, the amount is hidden, so a ZK circuit must output Enc(amount, TPK, r) as a public output for the contract to subtract from TS.
Key management
The total_supply_key is a Grumpkin keypair (tsk, TPK) where:
TPKis stored on-chain and used by the contract (and circuits, for private burns) to encrypt amounts into the counter.tskis held by the authorized party (e.g., the EMI compliance team).
The key holder can decrypt the total supply counter at any time: total_supply · G = C_ts - tsk · R_ts, then solve the discrete log. Since total supply is bounded by reasonable token economics — e.g., 10^13 micro-units for a $10M stablecoin with 6 decimals, roughly 2^43 — the discrete log solver using Boosted Kangaroos recovers the plaintext total supply in milliseconds.
Verification
To prove reserves, the keyholder generates a ZK proof that a given total_supply value matches encryptedTotalSupply at a given block. This can be done on regulator request, or periodically by publishing the current total supply on-chain together with the proof.
Private burns
When a user's funds are seized or burned via a compliance action (see AML Enforcement), the funds are transferred to an unspendable burn BPK derived via RFC 9380 hash-to-curve. Because no entity knows the corresponding secret key, the funds are provably irrecoverable. If this is done without going through the public unshield path, the total supply counter must still be decremented. The burn circuit (or the contract logic for administrative burns) must include an encryption of the burned amount under totalSupplyKey so the counter remains consistent.
Costs and risks
Every supply-changing operation (shield, unshield, burn, mint) pays an additional on-chain cost: one ElGamal encryption + one point addition on the counter — roughly 2 EC point operations, comparable to the existing concealed-layer cost. Private burns require circuit changes to output an encryption under totalSupplyKey.
Managing the total_supply_key requires key rotation, backup, and access control. If tsk is compromised, the attacker learns total supply (but not individual balances). If tsk is lost, the counter becomes undecryptable — the system continues to function, but auditing is impossible until a new counter is initialized.