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
132 changes: 132 additions & 0 deletions solutions/LP-0013.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Solution: LP-0013 — Token Program Improvements: Authorities

**Submitted by:** bristinWild

## Summary

This submission implements a complete mint authority model for the LEZ Token program. Fungible tokens can now be created with a designated mint authority that can mint additional supply, rotate control to a new key, or permanently revoke minting to fix the supply. A standalone `lez-authority` crate provides the reusable authority primitive as defined in RFP-001.

## Demo Video

Link - https://www.youtube.com/watch?v=Q_uAv7xRD-c

## Repository

- **Repo:** https://github.com/bristinWild/lez-programs (PR: https://github.com/logos-blockchain/lez-programs/pull/125)
- **Fork:** https://github.com/bristinWild/lez-programs
- **Branch:** `solution/lp-0013-authorities`
- **Commit:** `c2d259e`
- **Key files:**
- `lez-authority/src/lib.rs` — `Authority` type + `Ownable` trait (RFP-001)
- `programs/token/core/src/lib.rs` — `TokenDefinition::Fungible` with `authority: Authority` field
- `programs/token/src/mint.rs` — authority-gated `Mint` handler (self/external authority)
- `programs/token/src/set_authority.rs` — `SetAuthority` handler (rotation + revocation)
- `programs/token/src/new_definition.rs` — `NewFungibleDefinition` with `mint_authority: Option<AccountId>`
- `programs/token/methods/guest/src/bin/token.rs` — guest binary dispatch for all instructions
- `programs/integration_tests/tests/token.rs` — 17 integration tests including full rotation flow
- `scripts/demo-full-flow.sh` — end-to-end demo script
- `scripts/examples/fixed_supply_token.sh` — fixed supply example
- `scripts/examples/variable_supply_token.sh` — variable supply + rotation example
- `docs/LP-0013-README.md` — architecture, CU costs, CLI usage, design docs
- `artifacts/token-idl.json` — regenerated IDL via SPEL framework

## Approach

### Authority Model

`authority: Authority` is embedded directly in `TokenDefinition::Fungible` via the `lez-authority` crate:
- `Authority(Some(key))` — the key holder controls minting and can rotate/revoke
- `Authority(None)` — supply is permanently fixed; minting is rejected deterministically

### `lez-authority` Crate (RFP-001)

A standalone crate with zero dependency on any specific program or `nssa_core`. Provides:
- `Authority(Option<[u8; 32]>)` newtype with `authority()`, `require()`, `rotate()`
- `Ownable` trait with `require_owner`, `transfer_ownership`, `renounce_ownership`

All logic is unit-tested independently (8 tests).

### Instructions

| Instruction | Description |
|---|---|
| `NewFungibleDefinition` | Create token with optional mint authority (`mint_authority: Option<AccountId>`) |
| `Mint` (updated) | Authority-gated — self-authority (empty rest accounts) or external rotated authority (rest account) |
| `SetAuthority` | Rotate to new key (`Some(key)`) or revoke permanently (`None`) |

### Authority Transfer (RFP-001)

The `Mint` and `SetAuthority` instructions support both self/PDA authority and external rotated authority passed as a rest account. After rotation, the new key can actually mint — proven by the `token_rotate_authority_then_new_authority_can_mint` integration test.

### Atomicity

`SetAuthority` only mutates `authority` after all authorization checks pass. Unauthorized calls return before any write — prior authority is preserved. Structural guarantee via `Authority::rotate()`.

## Success Criteria Checklist

- [x] **Variable-size tokens via mint authority** — `NewFungibleDefinition` sets authority at init; `Mint` checks it
- [x] **Minting by the authority** — self-authority and external rotated-authority paths both supported and tested
- [x] **Authority rotation and revocation** — `SetAuthority` with `Some(new_key)` rotates; with `None` revokes permanently
- [x] **Two example integrations** — `scripts/examples/fixed_supply_token.sh` and `scripts/examples/variable_supply_token.sh`
- [x] **Self-sufficient agnostic authority library (RFP-001)** — `lez-authority` crate, zero deps on token program or nssa
- [x] **SDK/module** — SPEL IDL + CLI integration; guest binary wired for all instructions
- [x] **IDL** — `artifacts/token-idl.json` regenerated via SPEL framework
- [x] **Atomicity** — structural guarantee in `Authority::rotate()`, verified by unit tests
- [x] **Deterministic rejection** — `"Mint authority check failed: Revoked"` on every revoked-authority mint attempt
- [x] **CU costs** — measured from LEZ sequencer execution logs on localnet:
`NewFungibleDefinition` ~11ms, `Mint` ~10ms, `SetAuthority` ~8ms (execution time
inside zkVM, measured via sequencer logs with `RISC0_DEV_MODE=1`; this reflects
actual program execution cost independent of proof generation). Full ZK proof
generation takes 3–10 minutes per tx with `RISC0_DEV_MODE=0` on Apple M-series
hardware. LEZ devnet/testnet deployment pending public sequencer availability.
- [x] **Integration tests** — 17 tests in `programs/integration_tests/tests/token.rs` against live sequencer (standalone mode), including full RFP-001 rotation flow
- [x] **CI green** — 60 unit tests + 17 integration tests passing
- [x] **README** — `docs/LP-0013-README.md` with deployment steps, CLI instructions, architecture, error codes
- [x] **Demo script** — `scripts/demo-full-flow.sh` — reproducible against local LEZ sequencer with `RISC0_DEV_MODE=0`
- [x] **Recorded video demo** — https://www.youtube.com/watch?v=Q_uAv7xRD-c (narrated, `RISC0_DEV_MODE=0` terminal output visible)

## FURPS Self-Assessment

### Functionality
- `NewFungibleDefinition`: creates fungible token with `mint_authority: Option<AccountId>` — `Some` = mintable, `None` = fixed supply
- `Mint`: self-authority (definition account is its own authority) or external rotated authority (rest account)
- `SetAuthority`: rotates to `Some(new_key)` or revokes to `None`; authorization check enforces caller identity
- Metadata fungibles carry a real `mint_authority` — intentional and tested
- AMM LP token authority correctly wired to pool PDA — all AMM tests pass unchanged

### Usability
- Single embedded `authority: Authority` field — minimal diff, easy to audit
- `lez-authority` importable by any LEZ program without token program dependency
- `artifacts/token-idl.json` enables full SPEL CLI interaction
- `docs/LP-0013-README.md` documents all flows with CLI examples and CU costs

### Reliability
- Atomicity: `Authority::rotate()` returns `Err` before mutating — no partial writes possible
- 13 dedicated authority unit tests cover all lifecycle cases
- 17 integration tests including full rotation flow at executor level
- All 60 unit tests + 17 integration tests pass

### Performance
- Authority check in `Mint`: single `Option` match — negligible overhead
- `SetAuthority`: single account read + write
- CU costs (LEZ localnet, `RISC0_DEV_MODE=1`): `NewFungibleDefinition` ~11ms, `Mint` ~10ms, `SetAuthority` ~8ms

### Supportability
- Demo script reproducible against local sequencer with `RISC0_DEV_MODE=0`
- `docs/LP-0013-README.md` documents deployment, CLI usage, architecture, error codes
- PR #125 on `logos-blockchain/lez-programs` — rebased onto upstream main

## Supporting Materials

- **PR:** https://github.com/logos-blockchain/lez-programs/pull/125
- **Architecture docs:** `docs/LP-0013-README.md`
- **Authority library:** `lez-authority/src/lib.rs`
- **SetAuthority handler:** `programs/token/src/set_authority.rs`
- **Mint handler:** `programs/token/src/mint.rs`
- **Demo script:** `scripts/demo-full-flow.sh`
- **Example scripts:** `scripts/examples/`
- **Demo video:** https://www.youtube.com/watch?v=Q_uAv7xRD-c

## Terms & Conditions

By submitting this solution, I confirm that I have read and agree to the [Terms & Conditions](../TERMS.md).
Loading