Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions soroban/contracts/factory/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use super::*;
use soroban_sdk::{
symbol_short,
testutils::{
storage::Persistent as _, Address as _, AuthorizedFunction, AuthorizedInvocation,
Events as _, Ledger, MockAuth, MockAuthInvoke,
storage::{Instance as _, Persistent as _},
Address as _, AuthorizedFunction, AuthorizedInvocation, Events as _, Ledger, MockAuth,
MockAuthInvoke,
},
vec, Address, BytesN, Env, IntoVal, Symbol,
};
Expand Down Expand Up @@ -170,6 +171,10 @@ fn pool_record_ttl(env: &Env, factory_addr: &Address, pool_id: u32) -> u32 {
})
}

fn factory_instance_ttl(env: &Env, factory_addr: &Address) -> u32 {
env.as_contract(factory_addr, || env.storage().instance().get_ttl())
}

#[test]
fn test_initialize_sets_admin() {
let t = setup();
Expand Down Expand Up @@ -1368,6 +1373,18 @@ fn test_list_pools_bumps_pool_record_ttl() {
assert_eq!(pool_record_ttl(&t.env, &t.factory_addr, id), TTL_EXTEND_TO);
}

#[test]
fn test_list_pools_empty_page_bumps_factory_instance_ttl() {
let t = setup();

advance_ledgers(&t.env, TTL_EXTEND_TO - TTL_THRESHOLD + 1);
assert!(factory_instance_ttl(&t.env, &t.factory_addr) < TTL_THRESHOLD);

let page = t.client.list_pools(&0, &10);
assert!(page.records.is_empty());
assert_eq!(factory_instance_ttl(&t.env, &t.factory_addr), TTL_EXTEND_TO);
}

#[test]
fn test_refresh_pool_ttls_restores_ttl_for_unqueried_pool() {
let t = setup();
Expand Down
32 changes: 32 additions & 0 deletions soroban/contracts/farming-pool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2406,6 +2406,14 @@ impl FarmingPool {
Self::total_distributed_credits(env)
}

/// Return the total credits earned across users and staking systems.
///
/// Accrual is included when a user's stake or position is checkpointed;
/// uncheckpointed accrual remains available through the per-user queries.
pub fn get_total_earned(env: Env) -> Result<i128, PoolError> {
Self::total_distributed_credits(env)
}

/// Aggregate pool overview in a single invocation (Issue #395).
///
/// A pool dashboard previously needed up to six separate reads
Expand Down Expand Up @@ -2590,6 +2598,30 @@ impl FarmingPool {
Self::whitelist_count(env)
}

/// Return a zero-based page of distinct users with an active stake or locked position.
pub fn get_stakers(env: Env, start: u32, limit: u32) -> Result<Vec<Address>, PoolError> {
require_initialized(&env)?;
bump_instance(&env);

let mut all = get_staked_users_list(&env);
for user in get_locked_users_list(&env).iter() {
if !all.contains(&user) {
all.push_back(user);
}
}

let mut page = Vec::new(&env);
let mut index = start;
let mut count = 0u32;
while index < all.len() && count < limit {
page.push_back(all.get(index).unwrap());
index += 1;
count += 1;
}

Ok(page)
}

/// Return a paginated list of all users with active stakes.
///
/// `offset`: zero-based index of the first user to return.
Expand Down
33 changes: 33 additions & 0 deletions soroban/contracts/farming-pool/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,19 @@ fn test_total_distributed_credits_starts_at_zero() {
assert_eq!(t.client.total_distributed_credits(), 0);
}

#[test]
fn test_get_total_earned_counts_credits_when_checkpointed() {
let t = setup(2, 1);
t.client.stake(&t.user, &1_000);
advance_ledgers(&t.env, 10);

assert_eq!(t.client.get_credits(&t.user), 10_000);
assert_eq!(t.client.get_total_earned(), 0);

t.client.unstake(&t.user, &1_000);
assert_eq!(t.client.get_total_earned(), 10_000);
}

#[test]
fn test_total_distributed_credits_counts_banked_stake_accrual_on_checkpoint() {
let t = setup(2, 1);
Expand Down Expand Up @@ -1925,6 +1938,26 @@ fn test_get_user_position_none_after_full_unlock() {
assert!(t.client.get_user_position(&t.user).is_none());
}

#[test]
fn test_get_stakers_pages_distinct_flexible_and_locked_users() {
let t = setup(1, 1);
let locked_only_user = Address::generate(&t.env);
t.token_sac.mint(&locked_only_user, &1_000_000);

t.client.stake(&t.user, &1_000);
t.client.lock_assets(&t.user, &500);
t.client.lock_assets(&locked_only_user, &500);

let first_page = t.client.get_stakers(&0, &1);
assert_eq!(first_page.len(), 1);
assert_eq!(first_page.get(0), Some(t.user.clone()));

let second_page = t.client.get_stakers(&1, &1);
assert_eq!(second_page.len(), 1);
assert_eq!(second_page.get(0), Some(locked_only_user));
assert!(t.client.get_stakers(&2, &10).is_empty());
}

// ── pause / unpause tests ─────────────────────────────────────────────────────

#[test]
Expand Down
7 changes: 7 additions & 0 deletions soroban/contracts/vesting-wallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,13 @@ impl VestingWallet {
Ok(get_released(&env))
}

/// Return whether the beneficiary has received the entire scheduled amount.
pub fn is_fully_released(env: Env) -> Result<bool, VestingError> {
require_initialized(&env)?;
bump_instance(&env);
Ok(get_released(&env) == get_total_amount(&env))
}

/// Return the amount currently available to release (vested minus released).
pub fn releasable(env: Env) -> Result<i128, VestingError> {
require_initialized(&env)?;
Expand Down
3 changes: 3 additions & 0 deletions soroban/contracts/vesting-wallet/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,15 @@ fn test_release_nothing_before_cliff() {
#[test]
fn test_release_full_amount_after_end() {
let t = setup(0, 100, 1_000);
assert!(!t.client.is_fully_released());
advance_ledgers(&t.env, 200); // past end
assert!(!t.client.is_fully_released());

let amount = t.client.release();
assert_eq!(amount, 1_000);
assert_eq!(t.token.balance(&t.beneficiary), 1_000);
assert_eq!(t.client.releasable(), 0);
assert!(t.client.is_fully_released());
}

#[test]
Expand Down