Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
217 changes: 217 additions & 0 deletions solutions/LP-0013.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
# Solution: LP-0013 — Token program improvements: authorities

**Submitted by:** aegonmyy

## Summary

This submission adds a fully auditable **mint-authority model** to the LEZ
fungible-token program: variable-supply minting controlled by an authority, the
authority set at token initialization, atomic authority **rotation**, permanent
**revocation to `None`** (making supply fixed), and deterministic rejection of
any post-revocation mint via a documented error code. It ships the RFP-001
admin-authority library as a standalone, LEZ-agnostic crate, an SDK, two example
integrations, SPEL-generated IDL, integration tests wired into CI, and a
reproducible demo.

The program is **deployed and exercised end-to-end on the current public LEZ
testnet** (`https://testnet.lez.logos.co/`, LEZ `v0.2.0` commit `a58fbce2`,
`RISC0_DEV_MODE=0`). The full lifecycle — create -> mint -> rotate -> mint by the
rotated authority -> revoke -> post-revoke mint rejected — is confirmed on-chain
and independently re-verifiable.

## Repository

```text
https://github.com/aegonmyy/token-authority
```

**License:** MIT OR Apache-2.0

## Approach

The token-authority surface is split into reusable and LEZ-facing layers:

| Layer | Crate | Role |
|---|---|---|
| Authority primitive (RFP-001) | `admin_authority` | `AdminConfig { admin: Option<[u8;32]> }`, `require_admin()` gate, initialize / transfer / revoke — **zero SPEL/LEZ dependencies**, usable anywhere |
| Token state | `token_authority_core` | `TokenDef { name, decimals, total_supply, mint_authority }`, `TokenHolding { definition_id, balance }`, pure arithmetic helpers |
| On-chain program | `methods/guest` | `#[lez_program]` SPEL guest wiring the two layers into 6 instructions |
| Host SDK | `token_authority_sdk` | typed instruction args, account seeds, `SimulatedLedger` for host-side flows |

**Instructions:** `new_fungible_token`, `mint_tokens` (authority-gated),
`transfer_tokens`, `burn_tokens`, `rotate_authority`, `revoke_authority`
(irreversible). Account identities are signer-derived (no PDAs).

## Success Criteria Checklist

Mirrors the criteria in `prizes/LP-0013.md`:

**Functionality**
- [x] Variable-size tokens via a mint-authority model (fixed / variable /
permissioned / governance-controlled supply)
- [x] Documentation and examples
- [x] Self-sufficient, agnostic RFP-001 approval library (`admin_authority`)

**Usability**
- [x] Module/SDK for interacting with the token program (`token_authority_sdk`)
- [x] IDL for the token program via the SPEL framework
(`idl/token_authority.idl.json`)

**Reliability**
- [x] Authority rotation and revocation are atomic
- [x] Minting with a revoked authority is rejected deterministically with a
documented error code (`1003`)

**Performance**
- [x] CU cost of each new operation (mint, rotate, revoke) documented

**Supportability**
- [x] Program deployed and tested on the LEZ testnet
- [x] End-to-end integration tests against a LEZ sequencer, included in CI
- [x] CI green on the default branch
- [x] README documents end-to-end deployment + CLI usage
- [x] Reproducible demo script against a real local sequencer at
`RISC0_DEV_MODE=0`
- [x] Recorded video demo showing terminal output including proof generation

## FURPS Self-Assessment

### Functionality

- [x] **Mint-authority model** — mint authority set at initialization
(`new_fungible_token`), minting restricted to the authority (`mint_tokens`),
authority **rotation** (`rotate_authority`) and **revocation to `None`**
(`revoke_authority`) that permanently fixes supply. Demonstrated on-chain
(lifecycle table below).
- [x] **Two example integrations** — `examples/fixed_supply.rs` (no mint
authority from genesis) and `examples/variable_supply.rs` (authority
rotation -> revoke). Both run with `cargo run --bin fixed_supply` /
`--bin variable_supply` (no RISC-Zero toolchain needed).
- [x] **RFP-001 agnostic approval library** — `admin_authority` is a
self-sufficient crate with no SPEL/LEZ dependencies, providing the single-admin
account, gated access, initialize, transfer, and revoke operations.

### Usability

- [x] **SDK/module** — `token_authority_sdk` exposes typed instruction args,
account seeds, and a simulated ledger for building host-side Logos-module
flows against the token program.
- [x] **SPEL IDL** — `idl/token_authority.idl.json`, generated for the deployed
instruction surface via the SPEL framework.

### Reliability

- [x] **Atomic rotation/revocation** — each mutates the single `AdminConfig`
account in one write; a rejected transaction leaves the prior authority intact
(no partial state). Covered by contract tests and the on-chain lifecycle.
- [x] **Deterministic revoked-authority rejection** — a mint after revocation is
rejected by the `require_admin` guard with documented error **`1003` (Revoked)**;
supply is unchanged. Verified on-chain (post-revoke mint not included) and by
`integration_tests`.

### Performance

- [x] **CU cost documented** for each operation, measured with `RISC0_DEV_MODE=0`
from the guest's `log_cycles()` output (the executor's cycle count — the public
testnet does not expose per-transaction CU, so no chain-native CU figures are
invented):

| Instruction | CU (cycles) |
|---|---|
| `new_fungible_token` | 1 380 |
| `mint_tokens` | 4 072 |
| `rotate_authority` | 3 166 |
| `revoke_authority` | 2 708 |
| `transfer_tokens` | 2 606 |
| `burn_tokens` | 2 510 |

### Supportability

- [x] **Deployed & tested on LEZ testnet** — program `63a29a4e…` deployed and
the full lifecycle confirmed on-chain (evidence below).
- [x] **Integration tests in CI** — `integration_tests` drive the prebuilt guest
ELF through lee's `V03State` (the state machine the LEZ sequencer runs); the
`.github/workflows/ci.yml` `integration-test` job runs them on every push/PR.
- [x] **CI green on the default branch** — both jobs (`test`, `integration tests`)
pass on `main` (latest commit `62157ec`).
- [x] **README end-to-end usage** — deployment steps, program ID, and the
scripted create/mint/rotate/revoke CLI lifecycle
(`scripts/testnet-lifecycle.sh`, which issues each instruction via the SPEL/
wallet CLI and prints every tx hash).
- [x] **Reproducible demo script** — `scripts/demo.sh` starts a standalone LEZ
sequencer under `RISC0_DEV_MODE=0`, deploys `token_authority.bin` to it, then
drives the **full create -> mint -> rotate -> mint(rotated) -> revoke -> post-revoke
reject lifecycle through that sequencer** over the CLI, printing each real tx
hash and the on-chain `1003` rejection. It reuses the same lifecycle script
that produced the public-testnet evidence, pointed at the local sequencer.
- [x] **Narrated video demo** — narrated end-to-end walkthrough showing terminal
output including proof generation at `RISC0_DEV_MODE=0`:
https://youtu.be/zyPMxCXMFIQ

## Public-testnet evidence

> The public testnet is periodically reset. The lifecycle below was deployed and
> confirmed on the current network on **2026-07-02** and re-verified live at
> submission time. Re-produce on the current network in one command with
> `scripts/testnet-lifecycle.sh`.

**Network:** `https://testnet.lez.logos.co/` — LEZ `v0.2.0`, commit `a58fbce2`,
`RISC0_DEV_MODE=0`.

**Program ID (RISC-Zero image id):**
`63a29a4ec2b24402807c319d14e5d9a6bd5b26a49088cb3c6c2c8cd6187d2a60`
(deterministic — `spel program-id` == `methods/build.rs` == `cargo risczero`).

| # | Operation | Effect | Tx hash |
|---|---|---|---|
| 1 | `new_fungible_token` | create `AUTHDEMO`, supply 1000, authority = creator | `4fee352813b6e36bfc226432c7379deb3943f5b6eaa0b0c7c8b14477254ad94d` |
| 2 | `mint_tokens` (creator) | mint 500 -> supply 1500 | `112459026bc3114ad86b13d33edf2cdb1f11fc1a249f22b1c28de59689563bda` |
| 3 | `rotate_authority` | authority creator -> authority #2 | `bfd1f1bef1c7797e6a375129a2e7d59a4e92b27715c0fd3b671cd147ce87cc44` |
| 4 | `mint_tokens` (authority #2) | mint 300 -> supply 1800 (proves rotation) | `3da0cf3edc3ae61cfaccc661837803ef7023b5cc67c1b0b23ec9a8eb4a3721ad` |
| 5 | `revoke_authority` | authority -> `None` (supply now fixed) | `2097083f54e07f8a60348244b1ecbfb493818209b05f56474812a38b04055cbe` |
| 6 | `mint_tokens` after revoke | **rejected** by the authority guard (error `1003`); supply stays 1800 | not included (deterministic rejection) |

**Final on-chain state:** `TokenDef { name: "AUTHDEMO", decimals: 6,
total_supply: 1800, mint_authority: None }`; holding balance `1800`;
`AdminConfig { admin: None }`. The post-revoke mint did not change supply — the
on-chain proof that revocation makes supply fixed.

Full evidence + reproduction: `docs/testnet-v020-evidence-20260702.md`.

## Local verification

```bash
# Library + simulation tests (no toolchain):
cargo test --workspace --exclude token-authority-guest --exclude integration_tests

# Integration tests through lee V03State (real proofs at DEV_MODE=0):
RISC0_DEV_MODE=0 cargo test -p integration_tests -- --nocapture

# Run the examples:
cargo run --bin fixed_supply
cargo run --bin variable_supply
```

## Video

**Narrated end-to-end walkthrough:** https://youtu.be/zyPMxCXMFIQ

The recording covers the architecture and key decisions, then runs the full flow
with terminal output including proof generation, confirming `RISC0_DEV_MODE=0`.

## Honesty notes

- On-chain evidence lives on a **periodically-reset public testnet**; the hashes
above are current as of 2026-07-02 and re-producible with
`scripts/testnet-lifecycle.sh` on whatever network state is live at review time.
- CU figures are executor cycle counts (`log_cycles`), not chain-native
per-transaction CU, which the testnet does not expose.
- The fast `integration_tests` suite runs the guest through lee's in-process
`V03State` (the sequencer's own state machine); `scripts/demo.sh` additionally
drives the lifecycle through a real standalone sequencer end-to-end.

## Terms & Conditions

By submitting this solution, I confirm that I have read and agree to the
[Terms & Conditions](../TERMS.md), and that the implementation is original work
published under MIT OR Apache-2.0 licensing.
Loading