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 Pattern
pragma language_version >= 0.17.0;
import CompactStandardLibrary;
// Store contract owner
export ledger owner: Either<ZswapCoinPublicKey, ContractAddress>;
// Initialize owner in constructor
circuit constructor(): [] {
owner = disclose(left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey()));
}
// Owner-only function
export circuit restrictedFunction(): [] {
const caller = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
assert(caller == owner, "Only owner can call");
// Protected logic here
}
// Get caller address
export circuit getCaller(): Either<ZswapCoinPublicKey, ContractAddress> {
return left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
}
Owner-Only Pattern
Set Owner in Constructor
export ledger owner: Either<ZswapCoinPublicKey, ContractAddress>;
circuit constructor(): [] {
owner = disclose(left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey()));
}
The deployer automatically becomes the owner.
Restrict Function Access
export circuit mint(
account: Either<ZswapCoinPublicKey, ContractAddress>,
amount: Uint<128>
): [] {
// Only owner can mint
const caller = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
assert(caller == owner, "Only owner can mint");
_mint(account, amount);
}
Check caller matches owner before executing.
Transfer Ownership
export circuit transferOwnership(
newOwner: Either<ZswapCoinPublicKey, ContractAddress>
): [] {
const caller = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
assert(caller == owner, "Only owner can transfer");
owner = disclose(newOwner);
}
Allow current owner to transfer to new owner.
Caller Identification
Get Caller Address
// In any circuit
const caller = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
ownPublicKey() returns the public key of whoever called the circuit.
Authorize Sender
export circuit transfer(
to: Either<ZswapCoinPublicKey, ContractAddress>,
amount: Uint<128>
): [] {
// Sender is always the caller
const from = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
// Transfer from caller's balance
_transfer(from, to, amount);
}
The caller is automatically authorized to spend their own tokens.
Role-Based Access
Multiple Roles
export ledger owner: Either<ZswapCoinPublicKey, ContractAddress>;
export ledger minter: Either<ZswapCoinPublicKey, ContractAddress>;
export ledger burner: Either<ZswapCoinPublicKey, ContractAddress>;
// Owner can mint and burn
export circuit mint(account: Either<ZswapCoinPublicKey, ContractAddress>, amount: Uint<128>): [] {
const caller = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
assert(caller == owner || caller == minter, "Not authorized to mint");
_mint(account, amount);
}
export circuit burn(amount: Uint<128>): [] {
const caller = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
assert(caller == owner || caller == burner, "Not authorized to burn");
_burn(caller, amount);
}
Different roles for different operations.
Admin Functions
export circuit setMinter(newMinter: Either<ZswapCoinPublicKey, ContractAddress>): [] {
const caller = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
assert(caller == owner, "Only owner");
minter = disclose(newMinter);
}
export circuit setBurner(newBurner: Either<ZswapCoinPublicKey, ContractAddress>): [] {
const caller = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
assert(caller == owner, "Only owner");
burner = disclose(newBurner);
}
Owner manages role assignments.
What’s Next
Minting Apply access control to minting
ERC20 Token See access control in complete token