From c6e64f3d6c0b1531ee54600739bec506edad3c5e Mon Sep 17 00:00:00 2001 From: leanworld7-netizen Date: Fri, 31 Jul 2026 23:54:20 +0000 Subject: [PATCH 1/2] fix(#38): add admin auth to set_government_vault and set_tax_rate set_government_vault called require_auth() on the caller-supplied vault_address, allowing anyone to self-authorize as the government vault. set_tax_rate had no auth at all with a comment saying 'Should be admin-only in production'. Both functions now require an admin: Address parameter that is: 1. Authenticated via require_auth() 2. Verified against the stored CurrentAdmin This prevents unauthenticated takeover of settlement payouts. --- contracts/utility_contracts/src/lib.rs | 28 ++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/contracts/utility_contracts/src/lib.rs b/contracts/utility_contracts/src/lib.rs index d8ebf43..93d28ba 100644 --- a/contracts/utility_contracts/src/lib.rs +++ b/contracts/utility_contracts/src/lib.rs @@ -6127,9 +6127,17 @@ impl UtilityContract { ); } - // Task #2: Tax Compliance - Set government vault address - pub fn set_government_vault(env: Env, vault_address: Address) { - vault_address.require_auth(); + // Task #2: Tax Compliance - Set government vault address (admin-only) + pub fn set_government_vault(env: Env, admin: Address, vault_address: Address) { + admin.require_auth(); + let stored_admin: Address = env + .storage() + .instance() + .get(&DataKey::CurrentAdmin) + .expect("admin not set"); + if admin != stored_admin { + panic_with_error!(&env, ContractError::Unauthorized); + } env.storage() .instance() @@ -6139,9 +6147,17 @@ impl UtilityContract { .publish((soroban_sdk::symbol_short!("GovVault"),), vault_address); } - // Task #2: Tax Compliance - Set tax rate (in basis points) - pub fn set_tax_rate(env: Env, tax_rate_bps: i128) { - // Should be admin-only in production + // Task #2: Tax Compliance - Set tax rate (in basis points, admin-only) + pub fn set_tax_rate(env: Env, admin: Address, tax_rate_bps: i128) { + admin.require_auth(); + let stored_admin: Address = env + .storage() + .instance() + .get(&DataKey::CurrentAdmin) + .expect("admin not set"); + if admin != stored_admin { + panic_with_error!(&env, ContractError::Unauthorized); + } if tax_rate_bps < 0 || tax_rate_bps > 10_000 { panic_with_error!(&env, ContractError::InvalidUsageValue); } From d99dc567b660e0c9f7cdeed6aafec6e259657e9b Mon Sep 17 00:00:00 2001 From: leanworld7-netizen Date: Fri, 31 Jul 2026 23:58:02 +0000 Subject: [PATCH 2/2] fix: add admin auth to set_legal_vault and collect_streaming_fees set_legal_vault: had vault.require_auth() on caller-supplied vault address (same self-authorizing bug as #38). Now requires admin verified against DataKey::CurrentAdmin. collect_streaming_fees: had NO auth at all. Anyone could call it to zero out accrued streaming fees for any stream, preventing the protocol fee vault from collecting. Now requires admin auth. --- contracts/utility_contracts/src/lib.rs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/contracts/utility_contracts/src/lib.rs b/contracts/utility_contracts/src/lib.rs index 93d28ba..4984ecb 100644 --- a/contracts/utility_contracts/src/lib.rs +++ b/contracts/utility_contracts/src/lib.rs @@ -6624,8 +6624,16 @@ impl UtilityContract { } /// Set legal vault address - pub fn set_legal_vault(env: Env, vault: Address) { - vault.require_auth(); + pub fn set_legal_vault(env: Env, admin: Address, vault: Address) { + admin.require_auth(); + let stored_admin: Address = env + .storage() + .instance() + .get(&DataKey::CurrentAdmin) + .expect("No admin set"); + if admin != stored_admin { + panic_with_error!(&env, ContractError::UnauthorizedAdmin); + } env.storage().instance().set(&DataKey::LegalVault, &vault); @@ -7963,7 +7971,17 @@ impl UtilityContract { /// Sweep accrued streaming fees for a stream to the Protocol Fee Vault. /// Anyone can call this; the vault address is set by the admin. - pub fn collect_streaming_fees(env: Env, stream_id: u64) -> i128 { + pub fn collect_streaming_fees(env: Env, admin: Address, stream_id: u64) -> i128 { + admin.require_auth(); + let stored_admin: Address = env + .storage() + .instance() + .get(&DataKey::CurrentAdmin) + .expect("No admin set"); + if admin != stored_admin { + panic_with_error!(&env, ContractError::UnauthorizedAdmin); + } + let vault: Address = env .storage() .instance()