Documentation Index
Fetch the complete documentation index at: https://compact-by-example.org/llms.txt
Use this file to discover all available pages before exploring further.
The Contract
pragma language_version >= 0.17.0;
import CompactStandardLibrary;
// Simple balance tracker
export ledger balances: Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>;
// Get balance for an account
export circuit getBalance(account: Either<ZswapCoinPublicKey, ContractAddress>): Uint<128> {
// Check if account exists in map
if (!balances.member(disclose(account))) {
return 0; // Return 0 for accounts with no balance
}
return balances.lookup(disclose(account));
}
// Set balance for an account
export circuit setBalance(
account: Either<ZswapCoinPublicKey, ContractAddress>,
amount: Uint<128>
): [] {
balances.insert(disclose(account), disclose(amount));
}
// Add to existing balance
export circuit addBalance(
account: Either<ZswapCoinPublicKey, ContractAddress>,
amount: Uint<128>
): [] {
const currentBalance = getBalance(account);
// Check for overflow
const MAX_UINT128 = 340282366920938463463374607431768211455 as Uint<128>;
assert(currentBalance <= MAX_UINT128 - amount, "Balance overflow");
const newBalance = currentBalance + amount;
balances.insert(disclose(account), disclose(newBalance));
}
// Subtract from balance
export circuit subtractBalance(
account: Either<ZswapCoinPublicKey, ContractAddress>,
amount: Uint<128>
): [] {
const currentBalance = getBalance(account);
// Check sufficient balance
assert(currentBalance >= amount, "Insufficient balance");
const newBalance = currentBalance - amount;
balances.insert(disclose(account), disclose(newBalance));
}
How It Works
Map Declaration
export ledger balances: Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>;
Maps have key and value type parameters. This one maps accounts to balance amounts.
Checking Membership
if (!balances.member(disclose(account))) {
return 0;
}
Use member(key) to check if a key exists before lookup.
Looking Up Values
return balances.lookup(disclose(account));
Use lookup(key) to get the value for a key.
Inserting or Updating
balances.insert(disclose(account), disclose(amount));
Use insert(key, value) to add or update an entry.
Safe Arithmetic
const currentBalance = getBalance(account);
// Check for overflow before adding
const MAX_UINT128 = 340282366920938463463374607431768211455 as Uint<128>;
assert(currentBalance <= MAX_UINT128 - amount, "Balance overflow");
const newBalance = currentBalance + amount;
balances.insert(disclose(account), disclose(newBalance));
Always validate before modifying balances to prevent overflow and underflow.
Common Patterns
Initialize with Default
export circuit ensureAccount(account: Either<ZswapCoinPublicKey, ContractAddress>): [] {
if (!balances.member(disclose(account))) {
balances.insert(disclose(account), 0);
}
}
Create an entry if it doesn’t exist.
Nested Maps
// Allowances: owner -> (spender -> amount)
export ledger allowances: Map<
Either<ZswapCoinPublicKey, ContractAddress>,
Map<Either<ZswapCoinPublicKey, ContractAddress>, Uint<128>>
>;
export circuit getAllowance(
owner: Either<ZswapCoinPublicKey, ContractAddress>,
spender: Either<ZswapCoinPublicKey, ContractAddress>
): Uint<128> {
if (!allowances.member(disclose(owner))) {
return 0;
}
const spenderAllowances = allowances.lookup(disclose(owner));
if (!spenderAllowances.member(disclose(spender))) {
return 0;
}
return spenderAllowances.lookup(disclose(spender));
}
Maps can contain other Maps for complex relationships (used in approval systems).
Iterating Over Maps
Compact doesn’t support iterating over Map keys directly. Track keys separately if needed.
What’s Next
Transfer Function
Build a token transfer system
ERC20 Token
See Maps in a complete token