Add beneficiary / whitelist_count getters, total_tvl aggregate, and old-value multiplier event (#247–#250) - #273
Merged
ritaifeoluwa merged 11 commits intoAug 31, 2026
Conversation
`get_beneficiary` was an internal helper only. Expose a `beneficiary()` entry point (guarded by `require_initialized`) so frontends can read the recipient address without unpacking `get_vesting_schedule` or probing a failing call. Refs SmartDropLabs#247
Asserts the getter returns the configured address, follows `transfer_beneficiary`, and returns `NotInitialized` before init. Refs SmartDropLabs#247
Adds `whitelist_count()` / `get_whitelist_count()` returning the number of addresses currently whitelisted. The value is derived from the canonical `WhitelistedUsers` list that every add/remove/batch path already maintains and dedupes, so it cannot drift the way a parallel counter could. Refs SmartDropLabs#248
Checks the count across single adds/removes (including duplicate adds and no-op removes), agrees with `get_whitelisted_users().total`, and returns `NotInitialized` before init. Refs SmartDropLabs#248
…ier event The `mult_set` event only carried the new value. Capture the old multiplier before the write and publish `(old_multiplier, multiplier)` so off-chain indexers have both terms for audit trails and rollback scenarios. Refs SmartDropLabs#250
…d new Verifies the emitted tuple is `(old, new)` and that a subsequent change reports the just-superseded value as the old one. Refs SmartDropLabs#250
Introduces `DataKey::TotalTvl` (aggregate) and `DataKey::PoolTvl(id)` (per-pool snapshot), plus `total_tvl()` and `pool_tvl_synced(id)` read-only getters and a `PoolQueryFailed` error code. `total_tvl` is an O(1) read of an incrementally-maintained accumulator rather than an unbounded cross-contract fan-out. Also re-exports `FactoryError` from the crate root. Refs SmartDropLabs#249
… create_pool Adds `query_pool_tvl` (one cross-contract call to the pool's `total_staked`, which already includes locked balances) and the `pool_tvl(id)` live read-through getter. `create_pool` now records a zero TVL baseline for the new pool so the first sync is a clean delta. Refs SmartDropLabs#249
…alls Permissionless calls that re-read a pool's live TVL and fold the change into the `total_tvl` accumulator (`total_tvl += live - previous_snapshot`), emitting a `tvl_sync` event on change. `sync_all_pool_tvls` walks a bounded window of pool IDs, mirroring `refresh_pool_ttls`. Refs SmartDropLabs#249
Drives factory-deployed pools through stake/lock/unstake and asserts `total_tvl`, `pool_tvl`, `pool_tvl_synced`, `sync_pool_tvl`, and `sync_all_pool_tvls` behave, including the unknown-pool error path. Refs SmartDropLabs#249
✅ Deploy Preview for sdcontracts ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
@bade22brazy Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the four getter/event issues below across the vesting-wallet, farming-pool, and factory contracts. 10 commits, one logical unit each (feature + its tests paired).
#247 — public
beneficiarygetter (vesting-wallet)get_beneficiarywas internal only. Addsbeneficiary() -> Result<Address, VestingError>(guarded byrequire_initialized, bumps instance TTL) plusadmin-style aliasing conventions already used elsewhere in the crate are not needed here.#248 —
whitelist_countgetter (farming-pool)Adds
whitelist_count()/get_whitelist_count()returning the number of currently whitelisted addresses. Design note: rather than a parallelDataKey::WhitelistCountcounter incremented/decremented on every path (the issue's sketch), the value is read from the canonicalWhitelistedUsersinstance list thatadd_to_whitelist,remove_from_whitelist, and both batch variants already maintain and de-duplicate. That list is the single source of truth forget_whitelisted_users().total, so the count can never drift out of step with it.Vec::len()on an instance entry is O(1) from the caller's perspective.#249 —
total_tvlaggregate (factory) — hardA factory receives no callback when users stake/unstake in a deployed pool, and a live sum over every pool would need an unbounded cross-contract fan-out that does not fit Soroban's per-invocation footprint limit. So this uses the incremental-accumulator approach the issue suggests:
DataKey::TotalTvl— aggregate, instance storage;DataKey::PoolTvl(id)— per-pool last-synced snapshot, persistent.create_poolseeds a new pool's snapshot at0(a fresh pool holds nothing).sync_pool_tvl(id)/sync_all_pool_tvls(start_id, limit)— permissionless maintenance calls that read a pool's live TVL (one cross-contract call tototal_staked, which already includes locked balances) and fold the delta versus the stored snapshot intoTotalTvl.sync_all_pool_tvlswalks a bounded window, mirroringrefresh_pool_ttls. Emits atvl_sync = (pool_id, old_snapshot, new_tvl)event on change.total_tvl() -> i128— O(1) read of the accumulator. Reflects the last sync; dashboards that need a fresh figure callsync_all_pool_tvlsfirst.pool_tvl(id)— live per-pool read-through;pool_tvl_synced(id)— the currently-folded snapshot.FactoryError::PoolQueryFailedfor a pool that doesn't answertotal_staked;FactoryErroris now re-exported from the crate root.#250 —
set_global_multiplierevent includes old value (farming-pool)Captures
old_multiplierbefore the write and publishes(old_multiplier, multiplier)on theboost/mult_settopic.Tests
Unit tests added for #247/#248/#250; integration tests for #249 in
factory/tests/factory_pool_integration.rs(drives factory-deployed pools through stake/lock/unstake). New integration tests will generate fresh files underfactory/test_snapshots/on first run — not included here.Not built or run in this environment. Highest-risk review spots: the
try_invoke_contract::<i128, soroban_sdk::Error>decode inquery_pool_tvl(mirrorsupgrade_pool's existingadmincross-contract call), and the assumption thatFarmingPool::total_stakedis the correct single TVL term (verified:lock_assetscredits bothTotalStakedandTotalLocked, sototal_lockedis a subset).Closes #247, Closes #248, Closes #249, Closes #250