MorphoERC4626SwapConnectors: gate redeem quotes on servicable liquidity (v0 production line) - #177
Merged
Merged
Conversation
…ty (#175) * gate Morpho ERC4626 redeem quotes on servicable liquidity previewRedeem/previewWithdraw quote full NAV regardless of the vault's available liquidity, so the redeem leg always won MultiSwapper quote comparisons and then reverted at execution when the vault could not pay out, instead of routing to an AMM leg. Morpho Vault V2 hardcodes maxRedeem/maxWithdraw to 0, so servicability is derived from VaultV2.exit semantics instead: when the vault provably has no liquidity adapter (liquidityAdapter() == 0), redemptions are served from idle assets only and quotes return 0.0 - the graceful failure MultiSwapper routes around - unless the redemption fits in the vault's idle balance. Vaults without liquidityAdapter() (MetaMorpho V1, plain ERC4626) or with an adapter set keep legacy ungated behavior. * support VaultV2Lens as authoritative liquidity oracle, non-breaking A configured VaultV2Lens reports maxWithdraw = idle assets + liquidity adapter availability for any Vault V2 vault, covering adapter-backed vaults that the liquidityAdapter/idle heuristic cannot measure. The lens address lives in the contract account's storage (not contract state) because in-place contract updates reject new contract fields and a new Swapper.init parameter would break existing callers. Set or clear it with transactions/evm/morpho/set_vault_v2_lens.cdc signed by the contract account; unset or failing lens calls fall back to the heuristic. Off by default. Fork test height bumped to 163054070 (the lens postdates the previously pinned height); the new lens test uses the fork's local key for the contract account to write config and includes a negative control (vault-as-lens, whose hardcoded maxWithdraw = 0 zeroes the quote). * keep fork height CI-compatible; make lens test height-independent CI pins flow-cli v2.15.3, whose Cadence cannot type-check current mainnet bridge contracts (Serialize uses StringBuilder), so any fork height past that deployment fails CI at dependency load. Revert to the previously pinned height and verify the lens branch with the height-independent negative control (vault-as-lens: maxWithdraw is hardcoded to 0). The real-lens integration is verified against live mainnet state; verified locally with both v2.15.3 and v2.17.4. * swap back actual share balance in testSwap instead of magic 0.99 Depositing 1.0 PYUSD0 yields a height-dependent share amount (exchange rate, previewDeposit floor-rounding, and Cadence<->EVM decimal truncation), so the hardcoded 0.99 swapBack and its 'investigate losses' TODO are replaced by reading the received share balance and swapping it back in full.
Kay-Zee
marked this pull request as ready for review
August 31, 2026 23:33
Gornutz
approved these changes
Aug 31, 2026
peterargue
approved these changes
Sep 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
The #175 changeset (liquidity-aware Morpho ERC4626 redeem quotes + VaultV2Lens support) cherry-picked onto
v0, the branch production actually tracks. Clean cherry-pick of the squash commit b8d5cb6; no conflicts.See #175 for the full problem statement, design, and verification. This PR exists because deployed mainnet contracts track
v0, notmain— deploying the fix requires the change to exist on thev0lineage.Verification (specific to this base)
MorphoERC4626SwapConnectors.cdcis strictly additive over the deployed mainnet contract: zero lines removed or changed relative to the code at0x251032a66e9700ef(verified by diffing deployed code, import lines normalized). The rounding fix from fix morpho swap rounding #164 (deployed, previously missing frommain) is preserved by construction.ERC4626Utils.cdcdelta vs deployed is exactly the three new view functions (idleAssets,liquidityAdapter,maxWithdrawViaLens).flow test cadence/tests/MorphoERC4626SwapConnectors_test.cdcpasses under flow-cli v2.13.4 (v0 CI pin), v2.15.3 (main CI pin), and v2.17.4 — each run performs the in-place contract update against the real forked mainnet state, which is the production update path.Related
main(main-line hygiene; not a deploy blocker once this lands).