Skip to content

Payments 1/8: Fix VaultRouter <-> tier-vault ABI mismatch and unify asset-scoped accounting #138

Closed

Description

@wumibals

Problem / Context

VaultRouter (contracts/vault_router/src/lib.rs) forwards deposit, withdraw, and early_exit to each tier vault via env.invoke_contract using a 3-argument, asset-scoped signature: (user, asset, amount) (see lines 150-207). But the tier vaults do not implement that interface:

  • VaultL3::deposit/withdraw/early_exit (contracts/vault_l3/src/lib.rs) take only (user, amount) — 2 arguments, no asset parameter, and store balances in a single global Balance(Address) key (USDC-only accounting).
  • VaultFlex::withdraw (contracts/vault_flex/src/lib.rs line 61) is worse: its second parameter is strategy_balance: i128, not an amount at all — it's the external strategy balance used for pro-rata yield math — and the function always performs a full withdrawal (there is no partial-withdrawal branch, unlike VaultL3).

This is a hard ABI mismatch: Soroban's env.invoke_contract requires the argument vector to match the target function's exported signature exactly. As currently written, VaultRouter's deposit/withdraw/early_exit calls against real (non-mock) tier vault instances will fail. This hasn't surfaced yet because vault_router's own unit tests exercise a hand-written MockVault with a compatible 3-arg signature (see contracts/vault_router/src/lib.rs test module, lines 354-369), and nothing is deployed yet — deployments/testnet.json and mainnet.json are still placeholder files.

Objective

Establish one consistent, asset-scoped payment-initiation interface across all four tier vaults (VaultFlex, VaultL3, VaultL6, VaultL12) that actually matches what VaultRouter calls, so a deposit/withdraw/early-exit transaction can succeed end-to-end against the real contracts.

Technical approach

  • Change all tier vaults' storage keys to be asset-scoped: Balance(Address, Address), Shares(Address, Address), LockUntil(Address, Address), Checkpoint(Address, Address), keyed by (user, asset).
  • Standardize deposit(user, asset, amount), withdraw(user, asset, amount) -> i128, early_exit(user, asset, amount) -> i128 across all four vaults.
  • Rewrite VaultFlex::withdraw to accept a real amount and support partial withdrawal exactly like VaultL3 already does (full-vs-partial branch, dust handling), instead of depending on an externally-supplied strategy_balance. Decide how Flex sources the strategy balance it needs for yield math (own total_balance bookkeeping vs. a callback into StrategyVault).
  • Ensure min-deposit checks, TVL caps, exit-fee math, and share-checkpoint logic (shared::checkpoint) are applied per-asset, not globally.
  • Add integration tests that exercise VaultRouter against the real vault contracts (not MockVault) for deposit/withdraw/early_exit across at least two allowlisted assets, so interface drift like this is caught by CI going forward.

Detailed scope

contracts/vault_flex, contracts/vault_l3, contracts/vault_l6, contracts/vault_l12, contracts/shared/src/checkpoint.rs (if per-asset checkpoints require changes), and new integration tests in contracts/vault_router (or a new integration-test crate) that replace/augment the mock-only test harness.

Important edge cases and failure scenarios

  • Two different assets deposited by the same user in the same tier must not cross-contaminate share/lock accounting.
  • Partial withdraw/early-exit leaving a dust balance below the tier's minimum deposit — decide whether dust is allowed to remain or must be swept on partial exit.
  • VaultL3's existing emergency-unlock flag must apply per-asset once accounting is asset-scoped, not globally freeze/unfreeze every asset in the tier.
  • Multiplier and fee math must not double-apply now that storage keys include the asset dimension.
  • VaultFlex's rewritten withdraw must preserve the audited fixed-point yield-distribution behavior it currently gets from strategy_balance — verify no precision regression versus the current single-asset math.

Dependencies

None — this is the foundation issue for the payment track; all following issues assume a working, consistent contract interface.

Acceptance criteria

  • VaultRouter.deposit / withdraw / early_exit succeed end-to-end against real (non-mock) instances of all four tier vaults, for at least two allowlisted assets, in an automated test.
  • VaultFlex supports partial withdrawal with the same semantics as VaultL3/VaultL6/VaultL12.
  • All four tier vaults expose identical function signatures for deposit/withdraw/early_exit/balance/shares/lock_until.
  • cargo test passes across the full workspace, including new cross-contract integration tests.

Definition of done

PR merged with the updated contracts, new integration tests, and a CHANGELOG.md entry; CI (cargo build / cargo test) green; no remaining 2-arg-vs-3-arg (or otherwise mismatched) signatures between VaultRouter and any tier vault.

Activity

  1. Peculiarr7 commented on Aug 18, 2026

    @Peculiarr7

    Hi! I’m a full-stack developer with a strong blockchain background, and I’m confident I can resolve this issue quickly and effectively. I’ll deliver a clean, reliable solution with immediate attention to detail, ensuring it’s completed as soon as possible. Please assign it to me—I’m ready to get started right away.

  2. DavidAkere204 commented on Aug 18, 2026

    @DavidAkere204

    I would like to work on this issue

  3. soundsng commented on Aug 19, 2026

    @soundsng
    Contributor

    Looked through this project and understood its current implementation, architecture, and overall stage of maturity.

  4. grantfox-oss commented on Aug 19, 2026

    @grantfox-oss

    🦊 GrantFox — @soundsng has been assigned to this issue as part of the Third Campaign campaign!

    Next steps:

    1. Open a Pull Request referencing this issue (e.g., Closes #138)
    2. Your PR will be reviewed by the LadderMine maintainers

    Good luck! Track your progress on GrantFox.

  5. grantfox-oss commented on Aug 21, 2026

    @grantfox-oss

    🎉 This issue has been marked as completed on GrantFox as part of the Third Campaign campaign!

    @soundsng's PR #146 was approved and merged by @wumibals.

    🏆 @soundsng: You earned 40 FoxPoints for this contribution! Your current tier: Builder (1,425 total points). Track your full progress on GrantFox.

    👏 Great work, @soundsng! Keep contributing to LadderMine.

  6. added a commit that references this issue on Aug 21, 2026
    2db672b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardThird CampaignCampaign: Third CampaigncontractenhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions