Skip to content

fix(contracts): canonical last-price key, dust deposit rejection, bri… - #1645

Merged
Junirezz merged 2 commits into
Junirezz:mainfrom
godamongstmen897:fix/1525-1536-1538-1540-contract-issues
Oct 18, 2026
Merged

Junirezz merged 2 commits into
Junirezz:mainfrom
godamongstmen897:fix/1525-1536-1538-1540-contract-issues

Conversation

@godamongstmen897

Copy link
Copy Markdown
Contributor

🚀 Overview

This Pull Request resolves four core smart contract reliability, optimization, security, and integration issues for Junirezz/YieldVault-RWA:

  1. Deduplicated Price Storage Keys ([contract] Deduplicate DataKeyExt::Risk variant and dual last-price keys #1525): Consolidated dual last-price keys (Risk(LastPx) and LastOraclePrice) into DataKeyExt::LastOraclePrice with backward-compatible lazy migration and proper cache invalidation on oracle updates.
  2. Dust Deposit Rejection ([contract] Reject / test dust deposits minting zero shares #1536): Rejects dust deposits that round down to zero shares with MinDepositNotMet (Error Code 6) and emits diagnostic dep_dust events, preventing locked user funds across deposit, gasless_deposit, and batch entrypoints.
  3. Storage Read Caching & Gas Optimization ([contract] Cache repeated storage reads in total_assets / set_strategy #1538): Optimized total_assets and set_strategy by eliminating redundant storage reads and double-writes, verified via gas/footprint benchmark assertions.
  4. Bridge Provider Removal & Fallback Routing ([contract] Implement bridge provider removal + fallback routing + endpoint call #1540): Implemented timelocked 3-step bridge provider deregistration (queue, unregister, cancel), active contract invocation via BridgeEndpoint::send, and fallback routing over enabled secondary providers.

🔑 Linked Issues


🛠️ Summary of Changes

🔑 1. Price Storage Key Consolidation (contracts/vault/src/lib.rs) (#1525)

  • Single Canonical Key: Standardized on DataKeyExt::LastOraclePrice as the single canonical storage location for oracle price feeds.
  • Lazy State Migration: On read, if only legacy Risk(LastPx) exists, its value is automatically migrated to LastOraclePrice and the legacy key is purged.
  • Oracle Change Invalidation: Changing the vault oracle now purges both old and new keys to prevent stale price leaks (fixing a bug where only the un-written legacy key was previously cleared).
  • Storage Invariant Tests: Added unit coverage confirming single-key writes, migration execution, and full storage clearing on oracle mutations.

🛡️ 2. Zero-Share Dust Deposit Rejection (contracts/vault/src/lib.rs, contracts/share-price-math/src/rounding.rs) (#1536)

  • Zero-Share Guard: Rejects asset deposits that result in zero minted shares (e.g. 1 asset into 1,000 shares / 1,000,000 asset vault state).
  • Soroban Error Budgeting: Reused MinDepositNotMet (Code 6) to remain strictly within Soroban's 50-variant VaultError enum ceiling without breaking existing error mappings.
  • Diagnostic & Batch Events: Emits a dep_dust diagnostic event detailing input amount and vault totals. In batch entries where execution does not revert, events persist for off-chain indexing.
  • Boundary Tests: Verified zero-mint boundaries (999 assets fail, 1,000 assets mint 1 share), batch behaviors, and rounding logic.

⚡ 3. Storage Read/Write Optimization (contracts/vault/src/lib.rs) (#1538)

  • In-Memory Caching: Refactored total_assets to read token configuration once and cached intermediate storage reads across single calls. set_strategy now caches ledger timestamps.
  • Write Elimination: Replaced duplicate key writes with a single atomic price write per invocation.
  • Footprint Benchmark Test: Added footprint comparison assertions demonstrating lower CPU and memory footprint consumption for the updated read/write patterns.

🌉 4. Bridge Provider Removal & Fallback Routing (contracts/bridge-compat/src/lib.rs) (#1540)

  • Timelocked Unregister Flow: Implemented admin-governed provider removal via queue_unregister_provider, a 24-hour timelock delay, and unregister_provider. Supported cancellation via cancel_unregister_provider. Automatically clears default provider assignments if the default provider is removed.
  • Endpoint Contract Calls: Updated transfer_out to invoke BridgeEndpoint::send on the target provider contract.
  • Fallback Execution: If the primary provider call fails, transfer_out iterates through remaining enabled providers supporting the destination chain in ID order. Reverts with NoFallbackAvailable if all providers fail, ensuring sender tokens are preserved.
  • Mock Provider Test Suite: Added 16 unit tests utilizing a mock provider contract, and updated existing test fixtures to handle hashed provider identifiers.

📁 Files Touched

File / Path Change Summary
contracts/vault/src/lib.rs Storage key deduplication, migration logic, dust deposit guards, and storage read caching.
contracts/share-price-math/src/rounding.rs Added unit tests for zero-share rounding edge cases and fixed import placements.
contracts/bridge-compat/src/lib.rs Timelocked provider removal, endpoint invocations, fallback routing, and mock provider tests.
contracts/vault/src/fuzz_math.rs & tests/ Fixed minor import errors in timelock.rs, whitelist.rs, and strategy_registration.rs to allow test compilation.

🧪 Verification Logs

  • bridge-compat: 16 / 16 tests passed.
  • share-price-math: 13 / 13 tests passed.
  • vault: All 23 new and modified tests passed cleanly (including gas footprint comparison, migration, dust rejection, and single-key invariant tests).
  • Compilation: Repaired top-level test import errors across vault helper modules. Pre-existing test failures on main (auth mocking and strategy setup failures) remain unchanged.

…dge routing

- vault: use DataKeyExt::LastOraclePrice as the single last-price key,
  migrate legacy Risk(LastPx) on first read, clear both on oracle change (Junirezz#1525)
- vault: read strategy/token/oracle config once per total_assets and
  ledger timestamp once in set_strategy; single price write (Junirezz#1538)
- vault: reject zero-share deposits with MinDepositNotMet and emit
  dep_dust in deposit, gasless_deposit and batch entries (Junirezz#1536)
- bridge-compat: queue/cancel/execute provider removal behind a 24h
  timelock, invoke provider endpoint in transfer_out and fall back to the
  next eligible provider on failure (Junirezz#1540)
- fix pre-existing compile errors in rounding.rs, bridge-compat tests and
  vault lib tests so the new tests can run

Closes Junirezz#1525
Closes Junirezz#1536
Closes Junirezz#1538
Closes Junirezz#1540
Copilot AI balanced review requested due to automatic review settings October 17, 2026 10:26
@drips-wave

drips-wave Bot commented Oct 17, 2026

Copy link
Copy Markdown

@godamongstmen897 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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Junirezz
Junirezz merged commit 7eb1cb1 into Junirezz:main Oct 18, 2026
6 of 20 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

3 participants