Skip to content

[Feature] Automatic protocol-yield routing via migrate_adapter keeper #469

Description

@collinsezedike

Summary

The vault's active adapter is static, changed only manually via set_adapter/migrate_adapter. Existing routing logic (selectBestVault in packages/stellar-sdk-helpers/src/routing.ts, recommendedVaultId in packages/api-core/src/vaults.ts) only steers new deposits toward the best available option at deposit time; it never moves capital already deposited. migrate_adapter (packages/contracts/vault/src/lib.rs, shipped in #464/#507) already exists and atomically moves the vault's entire position to a new adapter in one transaction, with a slippage-bounded value-preservation check, but nothing calls it automatically. Today an admin has to notice a rate change and trigger it by hand.

Motivation

Automatic routing to the best available yield, without requiring a human to notice a rate change and manually trigger a migration, is the core value proposition of a yield aggregator. Without it, Meridian's yield allocation is manual, capital doesn't actually move to wherever yield is best unless someone is watching and acting.

Proposed Solution

An off-chain keeper (same shape as the existing Blend accrue keeper in #466/PR #484: a scheduled cron endpoint with retry handling and structured failure reporting) that periodically compares live rates across the protocols this vault's adapters can target (Blend, DeFindex), and calls migrate_adapter when the improvement clears a configured threshold, avoiding needless churn from chasing tiny, fee-losing differences.

This does not need any new authorization mechanism. migrate_adapter already exists, is already admin-gated, and, critically, already never touches any individual depositor's mUSDC balance, it operates on the vault's aggregate position, denominated in shares that are priced against total vault value, not reissued per protocol. So triggering it automatically benefits every depositor simultaneously with a single admin/keeper-signed call, no per-user consent, delegation, or signature is needed, because no individual user's tokens are ever moved.

(An earlier version of this issue proposed a MeridianRouter contract with per-user delegated authorization, letting a keeper move an individual depositor's position between separate vault deployments on their behalf. That approach ran into a hard constraint: Stellar's token contracts require the token holder's own signature for any transfer or burn, with no allowance/delegation primitive, so a keeper could never actually act without the depositor present, defeating the point. It also assumed multiple vault deployments would exist per protocol, which was never the intended design. That work was reverted; MeridianRouter no longer exists in the codebase.)

Scope

Field Value
Area API
Protocol affected Both
Network testnet
Breaking change? No (additive: a new scheduled job, no contract changes needed)

Alternatives Considered

Manual admin-triggered migrate_adapter (today's state): works, but depends on a human noticing a rate change and acting, which is exactly the dependency this issue exists to remove.

Acceptance Criteria

  • Scheduled job compares live rates across the vault's supported protocols (Blend, DeFindex) on a regular interval
  • Triggers migrate_adapter only when the improvement clears a configured minimum threshold, to avoid fee-losing churn from marginal differences
  • Uses a sane, explicit max_slippage_bps on every migrate_adapter call, never 10_000 (unlimited) in automated operation
  • Retry handling and structured failure reporting on migration failure, matching the accrue keeper's existing pattern
  • Documents the operational trust model: this keeper needs the vault admin's signing capability (or an equivalent trusted key), same as any other admin action, no new trust surface beyond what migrate_adapter already documents
  • Tests cover: triggering on a genuine rate improvement, not triggering below threshold, and failure/retry handling when migrate_adapter itself reverts (e.g. slippage exceeded)

Metadata

Metadata

Assignees

No one assigned

    Labels

    GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardThird CampaignCampaign: Third CampaigncontractsInvolves writing or testing Rust/Soroban contracts in packages/contractsenhancementNew feature or requesthardComplex implementation spanning multiple packages or involving Soroban contractssecuritySecurity hardening, vulnerability fixes, or audit-related worksorobanInvolves Soroban smart contract invocations or Soroban RPC calls

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions