diff --git a/docs/LP-0013-README.md b/docs/LP-0013-README.md index f757892..b11a848 100644 --- a/docs/LP-0013-README.md +++ b/docs/LP-0013-README.md @@ -26,7 +26,7 @@ The `lez-authority` crate provides a reusable, program-agnostic authority librar | Instruction | Description | |---|---| | `NewFungibleDefinitionWithAuthority` | Create token with mint authority | -| `Mint` (updated) | Now authority-gated — rejects if authority is None | +| `Mint` (updated) | Now authority-gated — Now authority-gated | | `SetAuthority` | Rotate or revoke mint authority | ### Atomicity @@ -37,9 +37,12 @@ The `lez-authority` crate provides a reusable, program-agnostic authority librar | 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 | +| Mint when authority revoked | Mint authority check failed: Revoked | +| Mint by non-authority signer | Mint authority check failed: Unauthorized | +| Mint/SetAuthority without signed authority | Mint authority must sign the transaction | +| SetAuthority on already-revoked | SetAuthority failed: AlreadyRevoked | +| SetAuthority by wrong signer | SetAuthority failed: Unauthorized | +| Create/rotate with all-zero authority | Mint authority must be a valid non-zero account ID | ## Crate Structure @@ -81,8 +84,12 @@ The `lez-authority` crate was also submitted as part of [RFP-001 PR #212](https: ## Deployment -### Program ID (LEZ localnet) -efdf86b1127c57c4653903e78bd2174b539fd688054331618c48f98c8fc057bd +The program ID is the hash of the compiled guest ELF and will change whenever +the guest is rebuilt. Obtain the current ID after building: + +```bash +lgs deploy --program-path target/riscv-guest/token-methods/token-guest/riscv32im-risc0-zkvm-elf/release/token.bin +``` ### Build the guest binary @@ -127,6 +134,7 @@ spel --idl artifacts/token-idl.json --program \ spel --idl artifacts/token-idl.json --program \ -- mint \ --definition-account \ + --authority-account \ --user-holding-account \ --amount-to-mint 500000 ``` @@ -137,6 +145,7 @@ spel --idl artifacts/token-idl.json --program \ spel --idl artifacts/token-idl.json --program \ -- set-authority \ --definition-account \ + --authority-account \ --new-authority ``` @@ -146,6 +155,7 @@ spel --idl artifacts/token-idl.json --program \ spel --idl artifacts/token-idl.json --program \ -- set-authority \ --definition-account \ + --authority-account \ --new-authority none ``` @@ -185,7 +195,7 @@ The script will: 4. Submit `NewFungibleDefinitionWithAuthority` (creates "DemoCoin" with 1M supply) 5. Submit `Mint` (mints 500K to recipient → total supply 1.5M) 6. Submit `SetAuthority` with `None` (permanently revokes minting) -7. Run unit tests to verify authority logic (60 tests) +7. Run unit tests to verify authority logic (64 tests) ## Compute Unit (CU) Costs diff --git a/programs/token/core/src/lib.rs b/programs/token/core/src/lib.rs index befa140..2b5add2 100644 --- a/programs/token/core/src/lib.rs +++ b/programs/token/core/src/lib.rs @@ -52,9 +52,9 @@ pub enum Instruction { /// Mint new tokens to the holder's account. /// /// Required accounts: - /// - Token Definition account (initialized, authorized), - /// - Token Holding account (initialized, or uninitialized with holder authorization in the - /// same transaction). + /// - Token Definition account (initialized). + /// - Authority account: must sign and match the stored mint authority. + /// - Token Holding account (uninitialized or authorized and initialized). Mint { amount_to_mint: u128 }, /// Print a new NFT from the master copy. @@ -81,7 +81,8 @@ pub enum Instruction { /// Pass `new_authority: None` to permanently revoke minting (fixed supply). /// /// Required accounts: - /// - Token Definition account (initialized, authorized by current mint authority). + /// - Token Definition account (initialized). + /// - Authority account: must sign and match the current mint authority. SetAuthority { new_authority: Option<[u8; 32]> }, } diff --git a/programs/token/src/set_authority.rs b/programs/token/src/set_authority.rs index 5b664d5..a7ce696 100644 --- a/programs/token/src/set_authority.rs +++ b/programs/token/src/set_authority.rs @@ -19,6 +19,13 @@ pub fn set_authority( authority_account.is_authorized, "Mint authority must sign the transaction" ); + + if let Some(new_key) = new_authority { + assert!( + new_key != [0u8; 32], + "New mint authority must be a valid non-zero account ID" + ); + } let signer: [u8; 32] = authority_account .account_id .as_ref() diff --git a/programs/token/src/tests.rs b/programs/token/src/tests.rs index dce7638..b31399e 100644 --- a/programs/token/src/tests.rs +++ b/programs/token/src/tests.rs @@ -1485,6 +1485,12 @@ mod authority_tests { ); } + #[test] + #[should_panic(expected = "New mint authority must be a valid non-zero account ID")] + fn set_authority_rejects_zero_new_authority() { + let _ = set_authority(def_with_authority(), authority_signer(), Some([0u8; 32])); + } + #[test] fn set_authority_rotates_to_new_key() { let new_key = [7_u8; 32];