- Added mint_authority: Option<AccountId> to TokenDefinition::Fungible - NewFungibleDefinitionWithAuthority instruction - SetAuthority instruction (rotate or revoke to None) - Updated Mint with early authority guard - Fully backwards compatible - token_core SDK + regenerated SPEL IDL - End-to-end demo script + tests
7.1 KiB
LP-0013: Token Program — Mint Authority
This fork of logos-blockchain/lez-programs adds a mint authority model to the LEZ token program, enabling variable supply tokens, permissioned issuance, and the standard "revoke to fix supply" pattern expected by wallets and DeFi protocols.
For the LP-0013 contribution, what changed, and how to run it — see below.
For the wallet CLI additions (two new commands: token new-with-authority and token set-authority) — see the supporting fork: youthisguy/logos-execution-zone.
Everything else is the upstream lez-programs codebase.
What was added
mint_authority: Option<AccountId>field onTokenDefinition::FungibleNewFungibleDefinitionWithAuthorityinstruction — create a token with a mint authority at initializationSetAuthorityinstruction — rotate authority to a new account, or revoke it permanently by passingNone- Updated
Mintinstruction — enforces the authority check before any state write - Fully backwards compatible — the existing
NewFungibleDefinitioninstruction is unchanged
The design follows Solana's SPL Token: a single Option<AccountId> encodes both who the authority is and whether minting is possible. None is self-describing — no authority, no minting, ever.
Admin Authority Library (RFP-001)
The mint authority logic is implemented as a standalone, reusable crate — crates/lez-authority - This satisfies RFP-001: Admin Authority Library, which calls for standardised access control that any LEZ program can adopt.
lez-authority provides:
Authority— wrapsOption<AccountId>;Some(id)is an active authority,Noneis permanently renouncedAuthority::rotate()— transfer authority to a new signer (requires current authorization)Authority::revoke()— permanently renounce authority (irreversible)Authority::require()— gate a privileged instruction; returnsAuthorityError::UnauthorizedorAuthorityError::Renouncedrequire_authority!macro — panics with a clear message in LEZ guest programs
The token program is the first consumer: mint.rs and set_authority.rs both call into lez-authority instead of implementing authorization checks inline. See crates/lez-authority/README.md for integration instructions and a usage example.
Repositories
| Repo | Purpose |
|---|---|
| youthisguy/lez-programs ← this repo | Token program changes, token_core SDK, integration tests, demo script |
| youthisguy/logos-execution-zone | Sequencer, wallet CLI (token new-with-authority, token set-authority) |
Documentation
| Document | Description |
|---|---|
| programs/token/README.md | End-to-end usage: deploy steps, program addresses, CLI instructions for minting, rotating, and revoking authority |
| docs/authority-model.md | Full design spec: data model, instruction semantics, authority lifecycle diagram, atomicity proof, error codes, authorization model, backwards compatibility, threat model |
| artifacts/token-idl.json | SPEL-generated IDL for the updated token program (regenerate with cargo run -p idl-gen) |
Example Integrations
Two example Rust programs are in examples/program_deployment/src/bin/:
| Example | Description |
|---|---|
run_new_token_with_authority.rs |
Variable supply token — creates a token with an active mint authority, mints additional supply, then rotates the authority |
run_new_fixed_supply_token.rs |
Fixed supply token — creates a token with mint_authority: None at initialization; no revocation step needed |
Build & Test
git clone https://github.com/youthisguy/lez-programs.git
cd lez-programs
# All tests (skips ZK proof generation)
RISC0_DEV_MODE=1 cargo test --release
# Token unit tests only
RISC0_DEV_MODE=1 cargo test --release -p token_program
# Token integration tests only
RISC0_DEV_MODE=1 cargo test --release -p integration_tests --test token
End-to-End Demo
The demo script runs the full authority lifecycle against a real local sequencer with RISC0_DEV_MODE=0
Prerequisites
Clone and build the supporting repo first:
git clone https://github.com/youthisguy/logos-execution-zone.git
cd logos-execution-zone
cargo build --release
Start all three services in separate terminals:
# Terminal 1 — Bedrock
cd logos-execution-zone/bedrock && docker compose up
# Terminal 2 — Sequencer (after bedrock shows "proposed block")
cd logos-execution-zone/lez/sequencer/service
RUST_LOG=info RISC0_DEV_MODE=0 cargo run --release -p sequencer_service configs/debug/sequencer_config.json
# Terminal 3 — Indexer
cd logos-execution-zone/lez/indexer/service
RUST_LOG=info cargo run --release -p indexer_service configs/indexer_config.json
Run
RISC0_DEV_MODE=0 \
WALLET_BIN=/path/to/logos-execution-zone/target/release/wallet \
LEZ_WALLET_HOME_DIR=/path/to/logos-execution-zone/lez/wallet/configs/debug \
bash scripts/demo.sh
See scripts/demo.sh for what each step does. Execution times appear in the sequencer logs as execution time: lines.
Compute Unit Costs
Measured on local LEZ sequencer (standalone mode) with RISC0_DEV_MODE=0. Reproducible via scripts/demo.sh as above.
| Operation | Tx Hash | Block | Execution Time |
|---|---|---|---|
NewFungibleDefinitionWithAuthority |
14197f9113ff000e81b7545c671942b286ef19bae7122ba280a0a620b8e01ca1 |
410 | 15.92ms |
Mint (authority active) |
99f00dbe40600d0c8bb745b74980c2241f1e7a6daa1291f5cef6b9ea27c82bd9 |
411 | 19.29ms |
SetAuthority (rotate) |
d865e26dfb5f82a5528aa9a0882307a73b00ffc4fa7825f0e7b5d0888d5c87fc |
414 | 13.40ms |
SetAuthority (revoke to None) |
9408ef7ffd3efdbafbe2dd5bf243da32edd1a4d52f9709b5cfc92cb696b8956e |
415 | 15.74ms |
Mint (rejected — authority revoked) |
5228cc62094a91e479b86a3aee067809f18674465ac72d8623d1ed770ab496de |
416 | 9.84ms |
Rejected operations cost ~38% less than successful ones — execution halts at the authority guard before any account writes, confirming rejection is via the correct code path.
Note: These measurements use local sequencer executor timing with real proof generation (
RISC0_DEV_MODE=0). Testnet CU measurements will be added once the testnet exposes this data.
Video Demo
Narrated walkthrough showing terminal output with RISC0_DEV_MODE=0 active during proof generation:
https://youtu.be/mbNpOoOs7T4