From a45b140d034aa121baa5af47437a86fda68cb198 Mon Sep 17 00:00:00 2001 From: WISDOM-WOKE22 Date: Sun, 27 Sep 2026 21:15:17 +0100 Subject: [PATCH] fix(farming-pool, vesting-wallet): boost config multiplier, pause guard, and cliff release test - Return the user's checkpointed multiplier from get_boost_config instead of the live global multiplier, consistent with credit accrual (#413) - Confirm set_boost is already guarded by require_staking_not_paused which checks the general pause flag (#411) - Add test_release_immediately_after_cliff covering release at the exact cliff boundary (#412) - Verify pool_wasm_hash query already works correctly with proper guards and documentation (#414) Closes #413, Closes #412, Closes #411, Closes #414 --- soroban/contracts/farming-pool/src/lib.rs | 6 ++++- soroban/contracts/vesting-wallet/src/test.rs | 25 ++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/soroban/contracts/farming-pool/src/lib.rs b/soroban/contracts/farming-pool/src/lib.rs index cbd9e04..4a06d0e 100644 --- a/soroban/contracts/farming-pool/src/lib.rs +++ b/soroban/contracts/farming-pool/src/lib.rs @@ -2091,8 +2091,12 @@ impl FarmingPool { pub fn get_boost_config(env: Env, user: Address) -> Result, PoolError> { require_initialized(&env)?; bump_instance(&env); + let multiplier = match get_user_stake(&env, &user) { + Some(stake) => stake.multiplier, + None => read_global_multiplier(&env), + }; Ok(Some(BoostConfig { - multiplier: read_global_multiplier(&env), + multiplier, allocation_pct: get_user_boost(&env, &user).unwrap_or(0), })) } diff --git a/soroban/contracts/vesting-wallet/src/test.rs b/soroban/contracts/vesting-wallet/src/test.rs index ae0907f..9fae3ea 100644 --- a/soroban/contracts/vesting-wallet/src/test.rs +++ b/soroban/contracts/vesting-wallet/src/test.rs @@ -461,6 +461,31 @@ fn test_release_with_nothing_releasable_emits_no_event() { assert_eq!(released_events.count(), 0); } +#[test] +fn test_release_immediately_after_cliff() { + // Cliff at +100 ledgers, period 200 (end = start + 300), total = 1000. + // Advance exactly to the cliff boundary and verify release works. + let t = setup(100, 200, 1_000); + + // Before cliff: nothing releasable. + advance_ledgers(&t.env, 99); + assert_eq!(t.client.releasable(), 0); + assert_eq!(t.client.release(), 0); + + // Advance to exactly cliff (start + 100). + advance_ledgers(&t.env, 1); + // Vested = 1000 * 100 / 300 = 333 + let vested_at_cliff = t.client.vested_amount(); + assert!(vested_at_cliff > 0, "tokens must be vested at cliff"); + assert_eq!(vested_at_cliff, 333); + + let released = t.client.release(); + assert_eq!(released, 333); + assert_eq!(t.token.balance(&t.beneficiary), 333); + assert_eq!(t.client.released_amount(), 333); + assert_eq!(t.client.releasable(), 0); +} + // ── revoke tests ────────────────────────────────────────────────────────────── #[test]