feat(factory, farming-pool): report refreshed pool IDs, add get_pool_info, verify credit-rate event (#393, #394, #395, #396) - #423
Merged
ritaifeoluwa merged 5 commits intoSep 27, 2026
Conversation
…tDropLabs#393) The sweep already guarded each bump with a storage existence check, so non-existent IDs were skipped — but the entry point returned Ok(()), and callers had no way to learn which IDs were actually kept alive versus which were skipped. A keeper reconciling a sweep against a known registry had to guess. - New RefreshPoolTtlsResponse contract type: refreshed (ascending IDs that existed and were bumped), end_id (clamped resume point) and missing (count of IDs skipped for an absent record). - refresh_pool_ttls now returns it. The existence check and the ttl_ref event payload are unchanged, so the event contract is stable. - Existing refresh tests updated to the new return value.
…rtDropLabs#394) Adds the coverage the TTL logic lacked: - test_refresh_pool_ttls_reports_only_existing_pools_and_counts_gaps: pool IDs are handed out sequentially, so a hole inside the sweep range means a record was removed from storage (TTL lapse / archival) — the same case list_pools reports as pool_gap. The test archives the middle record, ages the survivors, then asserts the sweep returns only the two surviving IDs, reports missing == 1, extends the survivors' TTLs to TTL_EXTEND_TO, and does not materialise the archived record. - test_refresh_pool_ttls_reports_empty_sweep_past_the_registry: a start_id beyond PoolCount sweeps nothing and reports an empty result with end_id clamped to the count, instead of an ambiguous unit return.
) A pool overview needed up to six separate contract calls — total_staked, credit_rate, the global multiplier, the min lock period, the min stake amount and the paused flag — each paying its own invocation cost and TTL bump, with no on-chain way to fetch the set together. - New PoolInfo contract type carrying total_staked, total_banked_credits, total_distributed_credits, credit_rate, global_multiplier, min_lock_period, min_stake_amount and is_paused. - get_pool_info() reads instance storage directly, guarded by require_initialized + bump_instance like every other getter. The issue text also names 'number of stakers', which is deliberately not a field: the pool keeps no staker-count entry (it is derived by paging get_positions), so the field would report a value nothing maintains. The two maintained credit counters are included instead so the overview is a single round trip. Tests: the aggregate agrees with every individual getter it replaces, and an uninitialized pool returns NotInitialized rather than a zeroed PoolInfo that would be indistinguishable from an empty pool.
…rate (SmartDropLabs#396) The issue asks to verify the event already includes both rates. It does: set_credit_rate publishes (old_rate, new_rate, ledger_sequence). This adds the missing verification, which is a sequence rather than a single change — each event's old_rate must equal the previous event's new_rate, which is precisely the property an indexer needs to reconstruct rate history and compute deltas without reading storage. Pins three consecutive changes (10 -> 25 -> 40 -> 5) as three rate_set events with those payloads, and asserts the final value still matches the public credit_rate getter.
|
@aurorabini 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! 🚀 |
✅ Deploy Preview for sdcontracts ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
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.
Closes #393
Closes #394
Closes #395
Closes #396
Summary
One commit per issue. Two factory TTL changes and two farming-pool
readability/coverage changes, with no behaviour change beyond the two
additive return values described below.
#393 —
refresh_pool_ttlsreports what it refreshed (ddf4646)The existence check was already in place, so IDs without a record were
skipped — but the entry point returned
Ok(()), leaving callers no way totell which IDs were actually kept alive versus skipped. A keeper
reconciling a sweep against a known registry had to guess.
RefreshPoolTtlsResponse:refreshed(ascending IDs that existed andwere bumped),
end_id(clamped resume point) andmissing(count skippedfor an absent record).
refresh_pool_ttlsnow returns it. The existence check and thettl_refevent payload are unchanged, so the event contract stays stable.
refresh_pool_ttlstests were assertingOk(Ok(()))andare updated to the new return value.
#394 — coverage for missing pool records (
52413c9)test_refresh_pool_ttls_reports_only_existing_pools_and_counts_gaps: poolIDs are handed out sequentially from
PoolCount, so a hole inside thesweep range means a record was removed from storage (TTL lapse /
archival) — the same case
list_poolsreports aspool_gap. The testarchives the middle record, ages the survivors, and asserts the sweep
returns only the survivors, reports
missing == 1, extends their TTLs toTTL_EXTEND_TO, and does not materialise the archived record.test_refresh_pool_ttls_reports_empty_sweep_past_the_registry: astart_idbeyond the count sweeps nothing and reports an empty result withend_idclamped, instead of an ambiguous unit return.#395 —
get_pool_infoaggregate query (bbcb745)A pool overview needed up to six separate calls (
total_staked,credit_rate, global multiplier, min lock period, min stake amount, pausedflag), each paying its own invocation cost and TTL bump.
PoolInfocontract type andget_pool_info(), reading instancestorage directly behind
require_initialized+bump_instancelike everyother getter.
replaces, and that an uninitialized pool returns
NotInitializedratherthan a zeroed
PoolInfothat would be indistinguishable from an empty pool.One deliberate deviation: the issue also lists "number of stakers". There
is no staker-count entry in storage — it is derived by paging
get_positions— so a field here would report a value nothing maintains. The two maintained
credit counters (
total_banked_credits,total_distributed_credits) areincluded instead, so the overview is still a single round trip. This is
noted in the code comment and the commit message.
#396 — verify the
set_credit_rateevent (dfd04ba)The issue asks to verify the event already includes both rates. It does:
set_credit_ratepublishes(old_rate, new_rate, ledger_sequence). Thisadds the missing verification, and it verifies the property that actually
matters — across a sequence, not a single change. Three consecutive
changes (10 → 25 → 40 → 5) are pinned as three
rate_setevents, where eachevent's
old_rateequals the previous event'snew_rate. That chain is whatlets an indexer reconstruct rate history and compute deltas without reading
storage. The final value is also asserted against the
credit_rategetter.Notes for maintainers
entry point and a new read-only entry point. No storage keys, no
authorization changes, and no existing call sites outside the tests.
min_lock_periodis returned in ledgers, matching the internalread_min_lock_periodand the existingmin_lock_period()getter, ratherthan the seconds variant.
performed here, per the contribution constraints) — CI should compile and
execute the suites.