7.7 KiB
LP-0013: Token Program Mint Authority
This document describes the mint authority model added to the LEZ Token program as part of LP-0013.
Overview
The LEZ Token program now supports a mint authority model for fungible tokens:
- Mint authority set at initialization — create a token with a designated minter
- Minting by the authority — the authority can mint additional tokens at any time
- Authority rotation — transfer minting rights to a new key
- Authority revocation — permanently fix the supply by setting authority to
None
The lez-authority crate provides a reusable, program-agnostic authority library (RFP-001).
Architecture
Authority Model
mint_authority: Option<[u8; 32]> is added to TokenDefinition::Fungible:
Some(key)— the key holder can mint and rotate/revokeNone— supply is permanently fixed, minting rejected
New Instructions
| Instruction | Description |
|---|---|
NewFungibleDefinitionWithAuthority |
Create token with mint authority |
Mint (updated) |
Now authority-gated — rejects if authority is None |
SetAuthority |
Rotate or revoke mint authority |
Atomicity
SetAuthority only mutates state after all checks pass. A failed authorization check returns an error before any write occurs, leaving the prior authority intact.
Error Codes
| Condition | Message |
|---|---|
| Mint with revoked authority | Mint authority has been revoked; this token has a fixed supply |
| SetAuthority without authorization | Definition account authorization is missing |
| SetAuthority on already-revoked | Mint authority already revoked; supply is permanently fixed |
Crate Structure
lez-authority/— Agnostic AuthoritySlot library (RFP-001)programs/token/core/— TokenDefinition with mint_authority fieldprograms/token/src/mint.rs— Authority-gated mintingprograms/token/src/set_authority.rs— Rotation and revocation handlerprograms/token/src/new_definition.rs— NewFungibleDefinitionWithAuthority handlerprograms/token/methods/guest/src/bin/token.rs— Guest binary dispatch
Module/SDK
token_core provides the reusable types and instructions for building Logos modules. It is already consumed by amm, ata, stablecoin, and integration_tests in this workspace:
[dependencies]
token_core = { path = "programs/token/core" }
Key types:
TokenDefinition::Fungible { mint_authority, .. }— token definition with authorityInstruction::NewFungibleDefinitionWithAuthority— create with authorityInstruction::SetAuthority— rotate or revoke
RFP-001 Compliance
LP-0013 has a formal dependency on RFP-001 — the standardised admin authority library. The lez-authority crate in this submission directly implements the approval pattern defined in RFP-001:
| RFP-001 Requirement | How lez-authority satisfies it |
|---|---|
| Self-sufficient, agnostic authority library | lez-authority has zero program-specific dependencies — it only uses borsh for serialisation |
| Authority slot abstraction | AuthoritySlot struct wraps Option<[u8; 32]> with check, set, and revocation semantics |
| Approval check | AuthoritySlot::check(signer) returns an error if the signer does not match or authority is revoked |
| Rotation | AuthoritySlot::set(Some(new_key)) atomically rotates to a new authority |
| Permanent revocation | AuthoritySlot::set(None) permanently fixes the supply — subsequent set calls are rejected |
| Reusable by other programs | Any LEZ program can add lez-authority as a workspace dependency and use AuthoritySlot directly |
The lez-authority crate was also submitted as part of RFP-001 PR #212 (the spel-admin-authority library with the #[require_admin] macro). The two are complementary: lez-authority is the lightweight on-chain primitive; spel-admin-authority is the SPEL framework macro layer built on top of the same pattern.
Deployment
Program ID (LEZ localnet)
efdf86b1127c57c4653903e78bd2174b539fd688054331618c48f98c8fc057bd
Build the guest binary
cargo risczero build --manifest-path programs/token/methods/guest/Cargo.toml
Deploy to the sequencer
wallet deploy-program target/riscv-guest/token-methods/token-guest/riscv32im-risc0-zkvm-elf/release/token.bin
Running Tests
# Authority unit tests
cargo test -p lez-authority --lib
cargo test -p token_program --lib
# Authority integration tests (zkVM, dev mode)
RISC0_DEV_MODE=1 cargo test -p integration_tests --test token -- token_new_fungible_definition_with_authority token_set_authority_revoke
CLI Usage (via spel)
Create token with mint authority
spel --idl artifacts/token-idl.json --program <token-binary> \
-- new-fungible-definition-with-authority \
--definition-target-account <DEF_ID> \
--holding-target-account <SUPPLY_ID> \
--name "MyToken" \
--initial-supply 1000000 \
--mint-authority <AUTHORITY_KEY_HEX>
Mint tokens
spel --idl artifacts/token-idl.json --program <token-binary> \
-- mint \
--definition-account <DEF_ID> \
--user-holding-account <HOLDER_ID> \
--amount-to-mint 500000
Rotate authority
spel --idl artifacts/token-idl.json --program <token-binary> \
-- set-authority \
--definition-account <DEF_ID> \
--new-authority <NEW_KEY_HEX>
Revoke authority (fix supply permanently)
spel --idl artifacts/token-idl.json --program <token-binary> \
-- set-authority \
--definition-account <DEF_ID> \
--new-authority none
Example Scripts
# Fixed supply token (creates with authority, then revokes)
bash scripts/examples/fixed_supply_token.sh
# Variable supply token (creates with authority, mints more, optionally rotates)
bash scripts/examples/variable_supply_token.sh
End-to-End Demo
The demo script must be run from inside an lgs scaffold project directory (where the localnet and wallet live):
# 1. Set up an lgs scaffold (if you don't have one):
cargo install logos-scaffold
lgs new my-scaffold && cd my-scaffold
lgs setup
lgs localnet start
lgs wallet topup
# 2. Deploy the token program:
lgs deploy --program-path /path/to/lez-programs/target/riscv-guest/token-methods/token-guest/riscv32im-risc0-zkvm-elf/release/token.bin
# 3. Run the demo:
RISC0_DEV_MODE=0 bash /path/to/lez-programs/scripts/demo-full-flow.sh
The script will:
- Verify the localnet is running
- Fund the wallet
- Create 3 token accounts (definition, supply holder, recipient)
- Submit
NewFungibleDefinitionWithAuthority(creates "DemoCoin" with 1M supply) - Submit
Mint(mints 500K to recipient → total supply 1.5M) - Submit
SetAuthoritywithNone(permanently revokes minting) - Run unit tests to verify authority logic (60 tests)
Compute Unit (CU) Costs
Measured on LEZ localnet with RISC0_DEV_MODE=1 (execution only, no proof):
| Operation | Execution Time | Notes |
|---|---|---|
NewFungibleDefinitionWithAuthority |
~11ms | Creates token with mint authority |
Mint (with authority) |
~10ms | Authority-gated mint |
SetAuthority (rotate) |
~8ms | Rotates to new key |
SetAuthority (revoke) |
~8ms | Permanently revokes, sets None |
Note: With RISC0_DEV_MODE=0, full ZK proof generation takes 3–10 minutes per transaction on Apple M-series hardware. LEZ's per-transaction compute budget may change during testnet.