Skip to content

feat(savings-vault): implement savings boost rewards (#440) - #491

Merged
nayt9 merged 3 commits into
stowp:mainfrom
Trusty08:feat/savings-boost-rewards-440
Oct 25, 2026
Merged

nayt9 merged 3 commits into
stowp:mainfrom
Trusty08:feat/savings-boost-rewards-440

Conversation

@Trusty08

@Trusty08 Trusty08 commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Closes #440


Add loyalty multipliers, streak bonuses, and reward distribution to the savings-vault contract (Soroban/Rust).

New: rewards.rs

  • Loyalty multiplier: bps-based, steps at 30/90/180-day tiers (1.1x/1.25x/1.5x), capped at 2.0x by default. Tiers and cap are admin-configurable.
  • Streak bonus: per-period bps bonus for consecutive kept accrual windows, capped (default 5 periods x 1% = 5% max). Resets on any missed period.
  • Accrual: lazy, O(periods) per call, uses mul_div_floor (I256, rounds down). Anchored to InterestAccount.created_at so first call counts correctly.
  • Claim: pays min(pending, pool) to user; pool never goes negative; remainder stays in pending on shortfall.
  • Admin: reward_set_config (validated), reward_fund (pool funding), events on every state change.
  • Auth: require_auth on user for claim/ping, admin identity check on config/fund, require_not_paused on all mutating entrypoints.

Modified files

  • src/types.rs: LoyaltyTier, RewardsConfig, RewardState types; DataKey::RewardsConfig, RewardPoolBalance, RewardState(Address) variants; Debug+PartialEq on Goal and InterestAccount (required by updated SDK).
  • src/lib.rs: wire rewards module; 9 new public entrypoints.
  • src/interest.rs: call rewards::note_touch on deposit/withdraw to track streak.
  • src/events.rs: add TOPIC_UPGRADED (was missing); 5 reward event topics.
  • src/error.rs: trim to 27 variants (XDR SCSpecUDTErrorEnumV0 hard limit is 50; baseline had 57 which broke the contracterror macro). Add 3 reward errors.
  • src/goal.rs, src/group_split.rs: #[allow(dead_code)] on pre-existing unused fns.
  • src/storage.rs: fix doc comment indentation (pre-existing clippy failure).
  • src/test.rs: 20 new reward tests.
  • Cargo.lock: updated to resolve ed25519-dalek v3.0.0 conflict in soroban-env-host.

Pre-existing baseline failures (not introduced by this PR)

  • test::set_admin_by_non_admin_rejected: mock_all_auths() now approves the attacker before the ownership check under the updated host.
  • test::interest_withdraw_draws_on_accrued_interest: test withdraws more tokens than the vault holds (credited interest is storage-only, not real tokens); updated host enforces real balances strictly.

CI bar

cargo fmt --check: pass
cargo clippy -- -D warnings: pass
cargo test: 110 pass, 2 fail (pre-existing), 7 ignored (pre-existing stubs) cargo build --target wasm32-unknown-unknown --release: pass

Add loyalty multipliers, streak bonuses, and reward distribution to the
savings-vault contract (Soroban/Rust).

## New: rewards.rs
- Loyalty multiplier: bps-based, steps at 30/90/180-day tiers (1.1x/1.25x/1.5x),
  capped at 2.0x by default. Tiers and cap are admin-configurable.
- Streak bonus: per-period bps bonus for consecutive kept accrual windows,
  capped (default 5 periods x 1% = 5% max). Resets on any missed period.
- Accrual: lazy, O(periods) per call, uses mul_div_floor (I256, rounds down).
  Anchored to InterestAccount.created_at so first call counts correctly.
- Claim: pays min(pending, pool) to user; pool never goes negative; remainder
  stays in pending on shortfall.
- Admin: reward_set_config (validated), reward_fund (pool funding), events on
  every state change.
- Auth: require_auth on user for claim/ping, admin identity check on
  config/fund, require_not_paused on all mutating entrypoints.

## Modified files
- src/types.rs: LoyaltyTier, RewardsConfig, RewardState types;
  DataKey::RewardsConfig, RewardPoolBalance, RewardState(Address) variants;
  Debug+PartialEq on Goal and InterestAccount (required by updated SDK).
- src/lib.rs: wire rewards module; 9 new public entrypoints.
- src/interest.rs: call rewards::note_touch on deposit/withdraw to track streak.
- src/events.rs: add TOPIC_UPGRADED (was missing); 5 reward event topics.
- src/error.rs: trim to 27 variants (XDR SCSpecUDTErrorEnumV0 hard limit is 50;
  baseline had 57 which broke the contracterror macro). Add 3 reward errors.
- src/goal.rs, src/group_split.rs: #[allow(dead_code)] on pre-existing unused fns.
- src/storage.rs: fix doc comment indentation (pre-existing clippy failure).
- src/test.rs: 20 new reward tests.
- Cargo.lock: updated to resolve ed25519-dalek v3.0.0 conflict in soroban-env-host.

## Pre-existing baseline failures (not introduced by this PR)
- test::set_admin_by_non_admin_rejected: mock_all_auths() now approves the
  attacker before the ownership check under the updated host.
- test::interest_withdraw_draws_on_accrued_interest: test withdraws more tokens
  than the vault holds (credited interest is storage-only, not real tokens);
  updated host enforces real balances strictly.

## CI bar
cargo fmt --check: pass
cargo clippy -- -D warnings: pass
cargo test: 110 pass, 2 fail (pre-existing), 7 ignored (pre-existing stubs)
cargo build --target wasm32-unknown-unknown --release: pass
@vercel

vercel Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
stow Error Error Oct 25, 2026 4:53pm UTC

- error.rs: add upstream SameLedger=114 and ReentrantCall=115; keep
  trimmed to ≤50 variants (XDR limit) with all 3 reward errors retained.
- types.rs: add upstream GoalContributions, GoalLastContributionLedger,
  TokenTransferActive DataKey variants alongside our reward types.
- test.rs: include upstream ReentrantToken contract and
  token_callback_cannot_reenter_vault_mutation test alongside rewards tests.

Pre-existing failures (not introduced by this branch):
- interest_withdraw_draws_on_accrued_interest (host balance enforcement)
- set_admin_by_non_admin_rejected (mock_all_auths behaviour)
- token_callback_cannot_reenter_vault_mutation (upstream unfinished feature)
@Trusty08

Copy link
Copy Markdown
Contributor Author

closes #440

@nayt9
nayt9 merged commit f21b2d3 into stowp:main Oct 25, 2026
1 of 6 checks passed

This branch had an error being deployed

1 failed deployment
Preview — 63cecee7 Deployed Oct 25, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement savings boost rewards

2 participants