From b561f91db249b6e74a24a7da7ae2ae6a580fac6b Mon Sep 17 00:00:00 2001 From: bristinWild Date: Tue, 2 Jun 2026 02:03:35 +0530 Subject: [PATCH] fix: enforce mint authority key validation in mint and set_authority - mint.rs: validate caller account_id matches stored mint_authority key - set_authority.rs: validate caller matches mint_authority before rotation/revoke - tests.rs: align AUTHORITY constant and fixtures to match account_id [15; 32] - demo-full-flow.sh: fix --public flag, remove || true from spel commands, update test count to 60 --- programs/token/src/mint.rs | 14 ++++++++++---- programs/token/src/set_authority.rs | 14 ++++++++------ programs/token/src/tests.rs | 8 ++++---- scripts/demo-full-flow.sh | 14 +++++++------- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/programs/token/src/mint.rs b/programs/token/src/mint.rs index c08f8b7..2b21359 100644 --- a/programs/token/src/mint.rs +++ b/programs/token/src/mint.rs @@ -24,10 +24,16 @@ pub fn mint( // LP-0013: enforce mint authority — minting is only allowed if mint_authority is Some. if let TokenDefinition::Fungible { mint_authority, .. } = &definition { - assert!( - mint_authority.is_some(), - "Mint authority has been revoked; this token has a fixed supply" - ); + match mint_authority { + None => panic!("Mint authority has been revoked; this token has a fixed supply"), + Some(authority_key) => { + assert_eq!( + definition_account.account_id.as_ref(), + authority_key, + "Signer is not the mint authority" + ); + } + } } let mut holding = if user_holding_account.account == Account::default() { TokenHolding::zeroized_from_definition(definition_account.account_id, &definition) diff --git a/programs/token/src/set_authority.rs b/programs/token/src/set_authority.rs index 7a2d3a7..a4ae7ff 100644 --- a/programs/token/src/set_authority.rs +++ b/programs/token/src/set_authority.rs @@ -9,9 +9,6 @@ pub fn set_authority( definition_account: AccountWithMetadata, new_authority: Option<[u8; 32]>, ) -> Vec { - // The definition account must be authorized — this means the transaction - // signer controls the definition account, which is how mint authority - // is enforced in LEZ (account-level authorization). assert!( definition_account.is_authorized, "Definition account authorization is missing; only the mint authority can call SetAuthority" @@ -26,8 +23,13 @@ pub fn set_authority( None => { panic!("Mint authority already revoked; supply is permanently fixed"); } - Some(_) => { - // Rotate to new authority, or revoke by setting to None + Some(authority_key) => { + // Validate caller matches the stored mint authority key + assert_eq!( + definition_account.account_id.as_ref(), + authority_key.as_ref(), + "Signer does not match the stored mint authority" + ); *mint_authority = new_authority; } } @@ -41,4 +43,4 @@ pub fn set_authority( definition_post.data = Data::from(&definition); vec![AccountPostState::new(definition_post)] -} +} \ No newline at end of file diff --git a/programs/token/src/tests.rs b/programs/token/src/tests.rs index 7182e0f..01c56c9 100644 --- a/programs/token/src/tests.rs +++ b/programs/token/src/tests.rs @@ -42,7 +42,7 @@ impl AccountForTests { name: String::from("test"), total_supply: BalanceForTests::init_supply(), metadata_id: None, - mint_authority: Some([1_u8; 32]), + mint_authority: Some([15_u8; 32]), }), nonce: Nonce(0), }, @@ -160,7 +160,7 @@ impl AccountForTests { name: String::from("test"), total_supply: BalanceForTests::init_supply_burned(), metadata_id: None, - mint_authority: Some([1_u8; 32]), + mint_authority: Some([15_u8; 32]), }), nonce: Nonce(0), }, @@ -242,7 +242,7 @@ impl AccountForTests { name: String::from("test"), total_supply: BalanceForTests::init_supply_mint(), metadata_id: None, - mint_authority: Some([1_u8; 32]), + mint_authority: Some([15_u8; 32]), }), nonce: Nonce(0), }, @@ -1325,7 +1325,7 @@ mod authority_tests { use super::*; use crate::{mint::mint, set_authority::set_authority}; - const AUTHORITY: [u8; 32] = [9_u8; 32]; + const AUTHORITY: [u8; 32] = [15_u8; 32]; const TOKEN_PROGRAM_ID: [u32; 8] = [5_u32; 8]; fn def_with_authority() -> AccountWithMetadata { diff --git a/scripts/demo-full-flow.sh b/scripts/demo-full-flow.sh index ffe12ec..6a250ee 100755 --- a/scripts/demo-full-flow.sh +++ b/scripts/demo-full-flow.sh @@ -26,7 +26,7 @@ # 4. Submit NewFungibleDefinitionWithAuthority transaction # 5. Submit Mint transaction # 6. Submit SetAuthority (revoke) transaction -# 7. Run unit tests to verify authority logic (49 tests) +# 7. Run unit tests to verify authority logic (60 tests) set -euo pipefail @@ -66,11 +66,11 @@ lgs wallet topup 2>&1 | grep -E "complete|funded|Address" || true echo " Wallet funded." echo "[3/7] Creating token accounts..." -DEF_RESULT=$(lgs wallet -- account new public 2>&1) +DEF_RESULT=$(lgs wallet -- account new --public 2>&1) DEF_ID=$(echo "$DEF_RESULT" | grep -oE '[0-9a-f]{64}' | head -1) -SUPPLY_RESULT=$(lgs wallet -- account new public 2>&1) +SUPPLY_RESULT=$(lgs wallet -- account new --public 2>&1) SUPPLY_ID=$(echo "$SUPPLY_RESULT" | grep -oE '[0-9a-f]{64}' | head -1) -RECIPIENT_RESULT=$(lgs wallet -- account new public 2>&1) +RECIPIENT_RESULT=$(lgs wallet -- account new --public 2>&1) RECIPIENT_ID=$(echo "$RECIPIENT_RESULT" | grep -oE '[0-9a-f]{64}' | head -1) echo " Definition account: $DEF_ID" echo " Supply account: $SUPPLY_ID" @@ -84,7 +84,7 @@ ${TIMEOUT:+$TIMEOUT 30} "$SPEL" --idl "$IDL" --program "$TOKEN_BIN" \ --holding-target-account "$SUPPLY_ID" \ --name "DemoCoin" \ --initial-supply 1000000 \ - --mint-authority "$DEF_ID" 2>&1 || true + --mint-authority "$DEF_ID" echo " Token 'DemoCoin' submitted. Initial supply: 1,000,000" sleep 2 @@ -95,7 +95,7 @@ ${TIMEOUT:+$TIMEOUT 30} "$SPEL" --idl "$IDL" --program "$TOKEN_BIN" \ -- mint \ --definition-account "$DEF_ID" \ --user-holding-account "$RECIPIENT_ID" \ - --amount-to-mint 500000 2>&1 || true + --amount-to-mint 500000 echo " Mint transaction submitted. New total supply: 1,500,000" sleep 2 @@ -105,7 +105,7 @@ NSSA_WALLET_HOME_DIR="$WALLET_DIR" \ ${TIMEOUT:+$TIMEOUT 30} "$SPEL" --idl "$IDL" --program "$TOKEN_BIN" \ -- set-authority \ --definition-account "$DEF_ID" \ - --new-authority none 2>&1 || true + --new-authority none echo " Authority revoked. Supply permanently fixed at 1,500,000" sleep 2