From 08e51c641ab725f99d1a9d82864e4ad6b8c99401 Mon Sep 17 00:00:00 2001 From: carrion256 Date: Mon, 18 May 2026 13:18:30 +0200 Subject: [PATCH] fix: require governance group market id (#FIND-062 Nexus e019c107-ebbe-4cbd-8446-06739d060ac0) Trace: 4fab9e08ab4f33df919c893a5bf1c475310a5ad4 --- .../vault/soroban/src/contract/entrypoints.rs | 2 +- contract/vault/soroban/src/tests.rs | 66 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/contract/vault/soroban/src/contract/entrypoints.rs b/contract/vault/soroban/src/contract/entrypoints.rs index b723111ca..cc6bfbeec 100644 --- a/contract/vault/soroban/src/contract/entrypoints.rs +++ b/contract/vault/soroban/src/contract/entrypoints.rs @@ -209,7 +209,6 @@ fn apply_group_policy( CapGroupId::try_from(raw).map_err(|_| ContractError::InvalidInput) } - let market_id = market_id.unwrap_or(0); let cap_group_raw = sdk_string_to_alloc( cap_group_id.unwrap_or_else(|| soroban_sdk::String::from_str(env, "")), )?; @@ -229,6 +228,7 @@ fn apply_group_policy( }, }, 2 => { + let market_id = market_id.ok_or(ContractError::InvalidInput)?; let group = if cap_group_raw.is_empty() { None } else { diff --git a/contract/vault/soroban/src/tests.rs b/contract/vault/soroban/src/tests.rs index e15a8b8db..2c74192f3 100644 --- a/contract/vault/soroban/src/tests.rs +++ b/contract/vault/soroban/src/tests.rs @@ -2901,6 +2901,72 @@ mod storage_tests { }); } + #[test] + fn test_execute_governance_group_membership_requires_market_id() { + let env = Env::default(); + env.mock_all_auths_allowing_non_root_auth(); + let contract_id = env.register(SorobanVaultContract, ()); + let curator = SdkAddress::generate(&env); + let governance = SdkAddress::generate(&env); + let asset = SdkAddress::generate(&env); + let share = SdkAddress::generate(&env); + let cap_group_id = CapGroupId::try_from("group-c".to_string()).unwrap(); + + env.as_contract(&contract_id, || { + SorobanVaultContract::initialize( + env.clone(), + curator, + governance.clone(), + asset, + share, + 0, + 0, + ) + .unwrap(); + + let mut storage = SorobanStorage::new(&env); + let mut policy_state = PolicyState::default(); + policy_state.set_cap_group_absolute_cap(cap_group_id.clone(), Some(100)); + policy_state + .set_market_config(0, MarketConfig::new(true, 100, None)) + .unwrap(); + Storage::save_policy_state(&mut storage, &policy_state).unwrap(); + }); + + let payload = Bytes::from_slice( + &env, + &GovernanceCommand::SetGovernancePolicy { + kind: GOVERNANCE_POLICY_KIND_GROUP, + target_ids: None, + mode: Some(2), + accounts: None, + market_id: None, + cap_group_id: Some("group-c".to_string()), + value: None, + value_b: None, + value_c: None, + } + .encode(), + ); + let result = env.as_contract(&contract_id, || { + SorobanVaultContract::execute_governance(env.clone(), governance.clone(), payload) + }); + assert_eq!(result, Err(crate::error::ContractError::InvalidInput)); + + env.as_contract(&contract_id, || { + let storage = SorobanStorage::new(&env); + let reloaded = Storage::load_policy_state(&storage) + .unwrap() + .unwrap_or_default(); + assert_eq!( + reloaded + .market_config(0) + .and_then(|config| config.cap_group_id.clone()), + None + ); + }); + } + #[test] fn test_execute_governance_remove_market_with_principal_after_timelock() { let env = Env::default();