The Contract
pragma language_version >= 0.17.0;
import CompactStandardLibrary;
// Account balances
export ledger balances: Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>;
// Total token supply
export ledger totalSupply: Uint<128>;
// Get total circulating supply
export circuit getTotalSupply(): Uint<128> {
return totalSupply;
}
// Burn your own tokens
export circuit burn(amount: Uint<128>): [] {
const account = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
_burn(account, amount);
}
// Burn tokens from another account (with approval)
export circuit burnFrom(
account: Either<ZswapCoinPublicKey, ContractAddress>,
amount: Uint<128>
): [] {
const spender = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
// Check and spend allowance (requires approval system)
_spendAllowance(account, spender, amount);
_burn(account, amount);
}
// Internal: Burn tokens
circuit _burn(
account: Either<ZswapCoinPublicKey, ContractAddress>,
amount: Uint<128>
): [] {
// Get current balance
const currentBalance = getBalance(account);
// Check sufficient balance
assert(currentBalance >= amount, "Burn amount exceeds balance");
// Decrease account balance
balances.insert(disclose(account), disclose(currentBalance - amount));
// Decrease total supply
totalSupply = disclose(totalSupply - amount);
}
// Helper: Get balance
circuit getBalance(account: Either<ZswapCoinPublicKey, ContractAddress>): Uint<128> {
if (!balances.member(disclose(account))) {
return 0;
}
return balances.lookup(disclose(account));
}
// Helper: Spend allowance (simplified - see Approval tutorial for full implementation)
circuit _spendAllowance(
owner: Either<ZswapCoinPublicKey, ContractAddress>,
spender: Either<ZswapCoinPublicKey, ContractAddress>,
amount: Uint<128>
): [] {
// Check allowance and decrease it
// See Approval & Allowance tutorial for complete implementation
}
How It Works
Burning Process
circuit _burn(
account: Either<ZswapCoinPublicKey, ContractAddress>,
amount: Uint<128>
): [] {
// Get current balance
const currentBalance = getBalance(account);
// Check sufficient balance
assert(currentBalance >= amount, "Burn amount exceeds balance");
// Decrease account balance
balances.insert(disclose(account), disclose(currentBalance - amount));
// Decrease total supply
totalSupply = disclose(totalSupply - amount);
}
Burning flow:
- Get current balance: Check how many tokens account has
- Check sufficient balance: Ensure account has enough tokens to burn
- Decrease account balance: Remove tokens from account
- Decrease total supply: Remove tokens from circulation
Result: Tokens are permanently destroyed and removed from total supply.
Burning Your Own Tokens
export circuit burn(amount: Uint<128>): [] {
const account = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
_burn(account, amount);
}
Users can always burn their own tokens:
ownPublicKey(): Automatically gets caller’s address
- Self-burn: No approval needed to burn your own tokens
- Deflationary: Reduces circulating supply permanently
- Voluntary: Anyone can choose to burn their tokens
Delegated Burning
export circuit burnFrom(
account: Either<ZswapCoinPublicKey, ContractAddress>,
amount: Uint<128>
): [] {
const spender = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
// Check allowance (requires approval system)
_spendAllowance(account, spender, amount);
_burn(account, amount);
}
Burn someone else’s tokens (with their approval):
- Requires approval: Account must first approve the burner (see Approval tutorial)
- Useful for contracts: Contracts that burn tokens as part of their logic
- Spends allowance: Decreases the approved amount
Use case: A staking contract that burns tokens when users stake, or a
buyback contract that burns purchased tokens.
What’s Next