diff --git a/solutions/LP-0013.md b/solutions/LP-0013.md new file mode 100644 index 0000000..a0c61d3 --- /dev/null +++ b/solutions/LP-0013.md @@ -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.