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
25 changes: 25 additions & 0 deletions soroban/contracts/factory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,31 @@ impl Factory {
record.wasm_hash = new_wasm_hash.clone();
env.storage().persistent().set(&key, &record);

let old_wasm_key = DataKey::PoolsByWasmHash(old_hash.clone());
if let Some(mut old_pool_ids) = env
.storage()
.persistent()
.get::<DataKey, Vec<u32>>(&old_wasm_key)
{
let mut new_old_ids: Vec<u32> = vec![&env];
for id in old_pool_ids.iter() {
if id != pool_id {
new_old_ids.push_back(id);
}
}
env.storage().persistent().set(&old_wasm_key, &new_old_ids);
}

let new_wasm_key = DataKey::PoolsByWasmHash(new_wasm_hash.clone());
let mut new_pool_ids: Vec<u32> = env
.storage()
.persistent()
.get(&new_wasm_key)
.unwrap_or_else(|| vec![&env]);
new_pool_ids.push_back(pool_id);
env.storage().persistent().set(&new_wasm_key, &new_pool_ids);
bump_wasm_pools(&env, &new_wasm_hash);

env.storage()
.instance()
.set(&DataKey::UpgradeCount, &read_upgrade_count(&env).saturating_add(1));
Expand Down
2 changes: 1 addition & 1 deletion soroban/contracts/factory/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use soroban_sdk::{contracterror, contracttype, Address, Vec};
use soroban_sdk::{contracterror, contracttype, Address, BytesN, Vec};

/// Storage keys used by the factory contract.
#[contracttype]
Expand Down
141 changes: 141 additions & 0 deletions soroban/contracts/farming-pool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,102 @@ fn add_total_distributed_credits(env: &Env, amount: i128) {
);
}

fn add_total_credits(env: &Env, amount: i128) {
let total = env
.storage()
.instance()
.get::<DataKey, i128>(&DataKey::TotalCredits)
.unwrap_or(0);
env.storage().instance().set(
&DataKey::TotalCredits,
&total.checked_add(amount).expect("total credits overflow"),
);
}

fn read_total_deposits(env: &Env) -> i128 {
env.storage()
.instance()
.get(&DataKey::TotalDeposits)
.unwrap_or(0)
}

fn add_total_deposits(env: &Env, amount: i128) {
let total = env
.storage()
.instance()
.get::<DataKey, i128>(&DataKey::TotalDeposits)
.unwrap_or(0);
env.storage().instance().set(
&DataKey::TotalDeposits,
&total.checked_add(amount).expect("total deposits overflow"),
);
}

fn read_total_withdrawals(env: &Env) -> i128 {
env.storage()
.instance()
.get(&DataKey::TotalWithdrawals)
.unwrap_or(0)
}

fn add_total_withdrawals(env: &Env, amount: i128) {
let total = env
.storage()
.instance()
.get::<DataKey, i128>(&DataKey::TotalWithdrawals)
.unwrap_or(0);
env.storage().instance().set(
&DataKey::TotalWithdrawals,
&total.checked_add(amount).expect("total withdrawals overflow"),
);
}

fn read_total_boost_allocations(env: &Env) -> u64 {
env.storage()
.instance()
.get(&DataKey::TotalBoostAlloc)
.unwrap_or(0)
}

fn add_total_boost_allocation(env: &Env, delta: i64) {
let total = read_total_boost_allocations(env);
if delta >= 0 {
env.storage().instance().set(
&DataKey::TotalBoostAlloc,
&total.checked_add(delta as u64).expect("total boost alloc overflow"),
);
} else {
let sub = (-delta) as u64;
env.storage().instance().set(
&DataKey::TotalBoostAlloc,
&total.checked_sub(sub).expect("total boost alloc underflow"),
);
}
}

fn read_boost_user_count(env: &Env) -> u32 {
env.storage()
.instance()
.get(&DataKey::BoostUserCount)
.unwrap_or(0)
}

fn increment_boost_user_count(env: &Env) {
let count = read_boost_user_count(env);
env.storage()
.instance()
.set(&DataKey::BoostUserCount, &(count + 1));
}

fn decrement_boost_user_count(env: &Env) {
let count = read_boost_user_count(env);
if count > 0 {
env.storage()
.instance()
.set(&DataKey::BoostUserCount, &(count - 1));
}
}

fn get_position(env: &Env, user: &Address) -> Option<Position> {
let key = DataKey::UserPosition(user.clone());
let value: Option<Position> = env.storage().persistent().get(&key);
Expand Down Expand Up @@ -621,6 +717,12 @@ impl FarmingPool {
env.storage()
.instance()
.set(&DataKey::TotalCredits, &0i128);
env.storage()
.instance()
.set(&DataKey::TotalDeposits, &0i128);
env.storage()
.instance()
.set(&DataKey::TotalWithdrawals, &0i128);
env.storage()
.instance()
.set(&DataKey::SchemaVersion, &SCHEMA_VERSION);
Expand Down Expand Up @@ -1098,6 +1200,8 @@ impl FarmingPool {
return Err(PoolError::NoActiveStake);
}

add_total_withdrawals(&env, total_returned);

// Bank the position and stake credits as separate totals so each staking
// system's accrual history survives even when a user held both (#145).
if position_credits > 0 || stake_credits > 0 {
Expand Down Expand Up @@ -1372,6 +1476,7 @@ impl FarmingPool {
increment_staked_user_count(&env);
}
add_total_staked(&env, amount);
add_total_deposits(&env, amount);

// Pull tokens from caller into the contract.
let stake_token = get_stake_token(&env)?;
Expand Down Expand Up @@ -1425,6 +1530,7 @@ impl FarmingPool {
}
increment_unstake_count(&env);
subtract_total_staked(&env, stake.amount);
add_total_withdrawals(&env, stake.amount);
Ok(total_credits)
}

Expand All @@ -1443,6 +1549,17 @@ impl FarmingPool {
set_user_stake(&env, &user, &stake);
}

let old_alloc: u32 = get_user_boost(&env, &user).unwrap_or(0);
if old_alloc == 0 {
increment_boost_user_count(&env);
add_total_boost_allocation(&env, allocation_pct as i64);
} else {
let delta = allocation_pct as i64 - old_alloc as i64;
if delta != 0 {
add_total_boost_allocation(&env, delta);
}
}

let key = DataKey::UserBoost(user.clone());
if !env.storage().persistent().has(&key) {
increment_boost_count(&env);
Expand Down Expand Up @@ -1718,6 +1835,30 @@ impl FarmingPool {
.unwrap_or(0))
}

/// Return the running total of all tokens deposited into the pool.
///
/// Incremented by `stake` and `lock_assets` with the amount transferred in.
/// Tracks cumulative inflow for protocol flow analytics; compare with
/// `total_withdrawals` to derive net flow and with `total_staked` to
/// reconcile current TVL against historical turnover.
pub fn total_deposits(env: Env) -> Result<i128, PoolError> {
require_initialized(&env)?;
bump_instance(&env);
Ok(read_total_deposits(&env))
}

/// Return the running total of all tokens withdrawn from the pool.
///
/// Incremented by `unstake`, `unlock_assets`, and `emergency_withdraw`
/// with the amount transferred out. Tracks cumulative outflow for
/// protocol flow analytics; compare with `total_deposits` to derive
/// net flow.
pub fn total_withdrawals(env: Env) -> Result<i128, PoolError> {
require_initialized(&env)?;
bump_instance(&env);
Ok(read_total_withdrawals(&env))
}

/// Return the count of currently staked unique users in the pool.
pub fn staked_user_count(env: Env) -> Result<u32, PoolError> {
require_initialized(&env)?;
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 @@ -337,6 +337,13 @@ impl VestingWallet {
Ok(compute_vested(&env)? - get_released(&env))
}

/// Return whether the vesting schedule is revocable by admin.
pub fn revocable(env: Env) -> Result<bool, VestingError> {
require_initialized(&env)?;
bump_instance(&env);
Ok(is_revocable(&env))
}

/// Return the full vesting schedule parameters in a single call.
///
/// Frontends need `beneficiary`, `token`, `total_amount`, `start_ledger`,
Expand Down