Mastering Shielded Token Lifecycles with Midnight's Compact Language
These articles are AI-generated summaries. Please check the original sources for full details.
Build shielded token mint, transfer, and burn flows in Compact
Developer Ritwika Kancharla outlines the implementation of shielded token operations within the Midnight network using the Compact language. The system distinguishes between fresh coins and committed ledger coins, requiring a Merkle tree index for spent committed value.
Why This Matters
In the technical reality of privacy-preserving blockchains, a newly minted shielded coin is not yet a committed ledger coin. Developers often face logic failures when they attempt to use sendShielded on fresh outputs that lack a Merkle tree index, a requirement enforced by the Compact standard library for committed state. This distinction necessitates specific API choices like sendImmediateShielded for atomic flows to prevent transaction failures and state desynchronization. Failing to track change outputs returned in ShieldedSendResult can lead to permanent loss of accessible user funds in application wallets as the remaining value becomes untraceable without its corresponding Merkle position.
Key Insights
- ShieldedCoinInfo represents fresh transaction outputs that can be spent immediately via sendImmediateShielded without requiring a Merkle tree index.
- QualifiedShieldedCoinInfo is required for ledger-committed coins and must include an mtIndex representing its position in the Merkle tree.
- The evolveNonce function provides deterministic nonce derivation by combining a private witness seed with a public index to prevent material reuse.
- Burning shielded value is executed as a transfer to a specialized recipient generated by the shieldedBurnAddress() standard library function.
- ShieldedSendResult returns both the sent coin and a change output, which must be persisted by the application to maintain balance accuracy.
Working Examples
Minting a shielded token to the current contract address using mintShieldedToken.
export circuit mint_to_contract(domainSep: Bytes<32>, value: Uint<64>, nonce: Bytes<32>): ShieldedCoinInfo { assert(disclose(value) > 0, "mint amount must be non-zero"); const coin = mintShieldedToken(disclose(domainSep), disclose(value), disclose(nonce), right<ZswapCoinPublicKey, ContractAddress>(kernel.self())); mintedOperations.increment(1); return coin; }
Transferring a committed shielded coin which requires QualifiedShieldedCoinInfo and its Merkle index.
export circuit send_committed(input: QualifiedShieldedCoinInfo, recipient: ZswapCoinPublicKey, value: Uint<128>): ShieldedSendResult { assert(disclose(value) > 0, "send amount must be non-zero"); assert(disclose(input).value >= disclose(value), "send amount exceeds coin value"); return sendShielded(disclose(input), left<ZswapCoinPublicKey, ContractAddress>(disclose(recipient)), disclose(value)); }
Practical Applications
- DApps performing atomic mint-and-send operations using sendImmediateShielded to deliver value to users in a single transaction.
- Pitfall: Attempting to call sendShielded on a coin without an mtIndex, resulting in runtime execution errors during the verification phase.
- Wallet integrations tracking ShieldedSendResult.change to ensure subsequent transactions can spend the remaining balance.
- Pitfall: Resetting local nonce seeds in production, which causes nonce reuse and potential privacy leaks or transaction collisions.
References:
Continue reading
Next article
How to Build a Zero-Cost Landing Page Stack for Business Validation
Related Content
Building Unshielded Token Smart Contracts on Midnight Network
Develop unshielded token contracts on the Midnight network using the UTXO model and CompactStandardLibrary for transparent public fund management.
Building Unshielded Token dApps with Compact and React on Midnight
A technical guide to developing unshielded token dApps on Midnight using Compact DSL and React, focusing on public ledger state and low-fee transactions.
Web-Aware AI Smart Contracts: Bridging On-Chain and Off-Chain Worlds with GenLayer
GenLayer introduces Trustless Decision-Making via Intelligent Contracts in Python, enabling native web access and LLM integration for non-deterministic on-chain consensus.