Skip to content

feat(contracts): yield accrue events, payment nonces, exit fee, naira checks (#992 #996 #998 #999) - #1104

Merged
ONEONUORA merged 1 commit into
Fracverse:masterfrom
that-girl-kate:fix-992-999
Sep 28, 2026
Merged

ONEONUORA merged 1 commit into
Fracverse:masterfrom
that-girl-kate:fix-992-999

Conversation

@that-girl-kate

@that-girl-kate that-girl-kate commented Sep 28, 2026 •

Copy link
Copy Markdown

Summary

Implements four smart-contract issues for Zaps:

  1. contract: CONTRACT: EMIT DETAILED YIELD ACCRUAL EVENTS WITH CALCULATED USER SHARE UPDATES #992 — Emit detailed accrue_yield events when the yield index compounds
  2. contract: CONTRACT: ADD SIGNATURE NONCE VERIFICATION TO PREVENT REPLAY IN SOCIAL PAYMENT #996 — Per-user nonce verification for off-chain signed social payments (replay protection)
  3. contract: CONTRACT: ENFORCE NAIRA TOKEN DECIMAL PRECISION CHECKS IN TRANSFER AMOUNTS #998 — Enforce Stellar 7-decimal precision and reject zero/negative Naira transfer amounts
  4. contract: CONTRACT: IMPLEMENT YIELD VAULT FEE ON WITHDRAWAL MANAGEMENT #999 — Optional 0.1% protocol exit fee on yield vault withdrawals

#992 — Detailed yield accrual events

Problem: Indexers and UIs needed a clear on-chain signal when the vault interest index compounds, including enough context to reason about depositor share value.

Changes (contracts/contracts/yield_vault/src/lib.rs):

  • checkpoint_index publishes
    env.events().publish((Symbol::new(&env, "accrue_yield"),), (old_index, new_index, total_assets))
  • Event fires only when the index actually compounds (new_index != old_index), so no-op checkpoints stay quiet
  • Payload gives indexers the pre/post index and current total_assets for share-value updates

Acceptance mapping: Soroban accrue_yield event · old_index · new_index · total_assets · uses env.events().publish()


#996 — Signature nonce verification (social payment)

Problem: Off-chain signed payment authorizations must not be replayable.

Changes (contracts/contracts/social_payment/src/lib.rs):

  • Per-user nonces stored as DataKey::Nonce(Address) in persistent storage
  • get_nonce(user) returns the current counter (default 0)
  • pay_with_signature requires auth.nonce == current_nonce, then increments to current_nonce + 1 on success
  • Mismatched / reused / future nonces return Error::NonceAlreadyUsed before signature verification
  • Strengthened unit tests covering reuse rejection, future-nonce rejection, and independent per-user counters

Acceptance mapping: Nonce(Address) in storage · increment on successful execution · reject reused nonces


#998 — Naira token decimal / amount checks

Problem: Transfer amounts must follow Stellar’s 7-decimal standard and never accept zero or negative values.

Changes (contracts/contracts/naira_token/src/lib.rs):

  • STELLAR_DECIMALS = 7; initialize asserts decimals == 7
  • Shared require_positive_amount helper (assert!(amount > 0)) used by mint, burn, transfer, transfer_from, and burn_from
  • Tests covering 7-decimal init plus ignored panic-path coverage for zero/negative transfers (Soroban v20 abort semantics)

Acceptance mapping: Reject zero/negative transfer values · amount > 0 · Stellar 7-decimal precision enforced at init


#999 — Yield vault exit fee on withdrawal

Problem: Protocol needed an optional 0.1% exit fee on vault withdrawals, routed to a treasury.

Changes (contracts/contracts/yield_vault/src/lib.rs):

  • Default exit fee 10 bps (0.1%); treasury defaults to vault owner at initialize
  • On withdraw: fee = (assets_out * fee_bps) / 10000, net sent to caller, fee to treasury
  • Admin APIs: set_treasury, set_exit_fee_bps (cap 100 bps), plus treasury / exit_fee_bps views
  • YieldWithdrawn event now carries the actual fee (was hardcoded 0)
  • Fee can be disabled with set_exit_fee_bps(0); emergency exit paths remain fee-free rescue routes
  • Tests for fee routing, zero-fee full payout, and balance updates after fee deduction

Acceptance mapping: fee = (amount * fee_bps) / 10000 · fee → treasury · remaining → caller


Test plan

  • cargo +1.85.0 test -p zaps-yield-vault --lib -- test_withdraw_exit_fee test_withdraw_zero_exit test_withdraw_returns_principal test_accrue_yield_emits_accrue
  • cargo +1.85.0 test -p zaps-social-payment --lib -- test_signed_payment_rejects_reused_nonce test_signed_payment_rejects_future_nonce test_get_nonce test_signed_payment_different_users
  • cargo +1.85.0 test -p zaps-naira-token --lib -- --skip blacklisted (decimals + positive-amount paths)
  • Manual: deposit → advance ledgers → accrue_yield → confirm accrue_yield event topics/data
  • Manual: withdraw with default 10 bps → confirm treasury receives fee and user receives net
  • Manual: pay_with_signature with stale nonce → NonceAlreadyUsed

Closes #992
Closes #996
Closes #998
Closes #999

Implements Fracverse#992, Fracverse#996, Fracverse#998, and Fracverse#999 across yield vault, social payment,
and naira token contracts.

Co-authored-by: Cursor <cursoragent@cursor.com>
@drips-wave

drips-wave Bot commented Sep 28, 2026

Copy link
Copy Markdown

@that-girl-kate 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! 🚀

Learn more about application limits

@ONEONUORA ONEONUORA left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job @that-girl-kate

@ONEONUORA
ONEONUORA merged commit 20a85b4 into Fracverse:master Sep 28, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants