From 0ab90117c8fbaaf6b664b283ef2ef1d620875ba2 Mon Sep 17 00:00:00 2001 From: SONIA Date: Thu, 28 May 2026 14:59:22 +0000 Subject: [PATCH] test(energy_token): add access control tests for unauthorized mint and set_minter Closes #278 - test_mint_unauthorized_caller_panics: verifies mint() panics when called without minter auth (no mock_all_auths) - test_mint_succeeds_with_minter_auth: verifies authorized minter can mint - test_set_minter_unauthorized_caller_panics: verifies set_minter() panics without admin auth The minter role, set_minter(), and require_auth() were already implemented; these tests provide coverage for the unauthorized-caller acceptance criteria. --- apps/contracts/energy_token/src/lib.rs | 92 ++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/apps/contracts/energy_token/src/lib.rs b/apps/contracts/energy_token/src/lib.rs index 40f2f61..3b6a716 100644 --- a/apps/contracts/energy_token/src/lib.rs +++ b/apps/contracts/energy_token/src/lib.rs @@ -771,6 +771,98 @@ mod tests { assert_eq!(client.admin(), admin); } + // ── access control tests ───────────────────────────────────────────────── + + /// Unauthorized caller cannot mint — auth is required from the registered minter. + /// Soroban enforces this: calling without the minter's auth causes a host error. + #[test] + #[should_panic] + fn test_mint_unauthorized_caller_panics() { + let env = Env::default(); + // Do NOT mock_all_auths — real auth enforcement + let id = env.register(EnergyToken, ()); + let client = EnergyTokenClient::new(&env, &id); + let admin = Address::generate(&env); + let minter = Address::generate(&env); + let recipient = Address::generate(&env); + + // Initialize: mock only the initialize call + env.mock_auths(&[soroban_sdk::testutils::MockAuth { + address: &admin, + invoke: &soroban_sdk::testutils::MockAuthInvoke { + contract: &id, + fn_name: "initialize", + args: (&admin, &minter).into_val(&env), + sub_invokes: &[], + }, + }]); + client.initialize(&admin, &minter); + + // No auth mocked for mint — must panic (host auth failure) + client.mint(&recipient, &100_i128); + } + + /// Authorized minter can mint successfully. + #[test] + fn test_mint_succeeds_with_minter_auth() { + let env = Env::default(); + let id = env.register(EnergyToken, ()); + let client = EnergyTokenClient::new(&env, &id); + let admin = Address::generate(&env); + let minter = Address::generate(&env); + let recipient = Address::generate(&env); + + env.mock_auths(&[ + soroban_sdk::testutils::MockAuth { + address: &admin, + invoke: &soroban_sdk::testutils::MockAuthInvoke { + contract: &id, + fn_name: "initialize", + args: (&admin, &minter).into_val(&env), + sub_invokes: &[], + }, + }, + soroban_sdk::testutils::MockAuth { + address: &minter, + invoke: &soroban_sdk::testutils::MockAuthInvoke { + contract: &id, + fn_name: "mint", + args: (&recipient, &500_i128).into_val(&env), + sub_invokes: &[], + }, + }, + ]); + client.initialize(&admin, &minter); + client.mint(&recipient, &500_i128); + assert_eq!(client.balance(&recipient), 500_i128); + } + + /// Non-admin cannot call set_minter — host auth failure causes a panic. + #[test] + #[should_panic] + fn test_set_minter_unauthorized_caller_panics() { + let env = Env::default(); + let id = env.register(EnergyToken, ()); + let client = EnergyTokenClient::new(&env, &id); + let admin = Address::generate(&env); + let minter = Address::generate(&env); + let new_minter = Address::generate(&env); + + env.mock_auths(&[soroban_sdk::testutils::MockAuth { + address: &admin, + invoke: &soroban_sdk::testutils::MockAuthInvoke { + contract: &id, + fn_name: "initialize", + args: (&admin, &minter).into_val(&env), + sub_invokes: &[], + }, + }]); + client.initialize(&admin, &minter); + + // No auth mocked for set_minter — must panic + client.set_minter(&new_minter); + } + // ── retire tests ───────────────────────────────────────────────────────── #[test]