Skip to content

docs: add TIB for Vault V2 public-allocator shared liquidity - #912

Open
Foulks-Plb wants to merge 5 commits into
mainfrom
vault-v2-public-allocator-tib
Open

docs: add TIB for Vault V2 public-allocator shared liquidity#912
Foulks-Plb wants to merge 5 commits into
mainfrom
vault-v2-public-allocator-tib

Conversation

@Foulks-Plb

@Foulks-Plb Foulks-Plb commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Motivation

The SDK can answer "how much more can be borrowed on this Blue market, counting liquidity a public allocator could pull in?" for MetaMorpho Vault V1 onlyReallocationDatacomputeReallocationsVaultReallocation[]. morpho-org/vault-v2 has since shipped BluePublicAllocator (last touched b417825, 2026-07-29), for which the SDK has no ABI, address key, entity, or compute — so as Vault V2 TVL grows, the V1-only engine silently under-reports a market's reallocatable liquidity and quotes borrows as impossible when they would succeed.

Solution

This PR is documentation only — one new TIB, no package source touched, no changeset (root AGENTS.md §7 excludes non-API documentation-only changes). It freezes the design of a Vault V2 mirror that is strictly additive: the V1 surface is untouched (no renames, no deprecations, no breaking change), the new symbols mirror V1 names with a VaultV2 suffix (computeReallocationsVaultV2, ReallocationDataVaultV2, …), and the engine is deliberately not wired into any transaction flow — no action, no bundler encoder, and MorphoBlue.getReallocationData() keeps its exact current behavior, with the v1/v2 dispatch deferred to the blue bundles migration.

The load-bearing part is a contract-level finding verified line-by-line against VaultV2.sol and MorphoMarketV1AdapterV2.sol: the vault rebases allocation[id] to expectedSupplyAssets rather than incrementing it by assets, which means shared allocation ids (adapterId, collateralId) do not net to zero across a reallocation and allocation[id] never bounds the deallocate leg. The intuitive port of the V1 algorithm is therefore wrong in the unsafe direction, and the TIB records it as rejected Alternative 4 with an invariant test per trap.

Review notes

Six locked decisions worth a second opinion, all argued in Considered Alternatives: the sibling-class-over-parameterized-ReallocationData split, the vault-grouped result shape, full-parity cap simulation, the shared-id correction above, deferring the encoder, and dropping V1's four deprecated utilization options. Two Open Questions are left for reviewers: whether BluePublicAllocator gets a deterministic cross-chain address, and whether the liquidity metric should count vault idle by default.

@Foulks-Plb Foulks-Plb added the documentation Improvements or additions to documentation label Jul 29, 2026
@Foulks-Plb Foulks-Plb self-assigned this Jul 29, 2026
- Should `getPublicReallocationLiquidityVaultV2` count idle by default? It is included here, on the
grounds that idle is genuinely reallocatable and excluding it under-reports — but a dashboard
showing "shared liquidity" may prefer to attribute idle separately.
- Should reallocation candidates be favored by penalty cost? Unlike PAV1's single per-vault fee,

@Foulks-Plb Foulks-Plb Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Open question before start (Should reallocation candidates be favored by penalty cost?)
(https://morpholabs.slack.com/archives/C0AJMKR8VB9/p1785398315187139)

@Rubilmax
Rubilmax marked this pull request as ready for review August 6, 2026 11:56
@Rubilmax
Rubilmax requested a review from a team as a code owner August 6, 2026 11:56

@devin-ai-integration devin-ai-integration Bot 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.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

@Rubilmax
Rubilmax force-pushed the vault-v2-public-allocator-tib branch from 29f6a32 to b2d0b3d Compare August 6, 2026 11:58

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 29f6a3248b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +104 to +105
`BluePublicAllocator` is a singleton — no constructor, no immutables, no `MORPHO` reference. Every
entry point is gated on `IVaultV2(vault).isAllocator(msg.sender)`; there is no `admin` mapping.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Describe allocator calls as permissionless

In the pinned allocator, reallocate and allocateFromIdle are the public, penalty-paid entry points; they check msg.value, active adapters, and deallocation/idle flags, not IVaultV2(vault).isAllocator(msg.sender) (that guard is on the curator setters). Describing every entry point as allocator-gated can lead the SDK surface/JSDoc to treat public reallocations as curator-only and hide a permissionless flow.

Useful? React with 👍 / 👎.

- `absoluteCap[t] > 0` for every target id (`ZeroAbsoluteCap`), `allocation[s] > 0` for every source
id (`ZeroAllocation`).
- For each id **shared** between source and target:
`allocation[id] + untracked_src + untracked_tgt ≤ min(absoluteCap[id], mulDivDown(A, relativeCap[id], WAD))`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bypass the relative-cap bound at WAD

When relativeCap is WAD, the on-chain cap check skips the relative-cap bound (relativeCap == WAD || ...), but this shared-id formula still takes min(..., A) and therefore caps the id at firstTotalAssets. For vaults where firstTotalAssets is below a valid absolute-capped allocation, the planner would reject or undercount reallocations that the contract accepts; use the absolute cap alone in the WAD case.

Useful? React with 👍 / 👎.

| `allocations[vault][t]`, all 3 target ids | `+= change_tgt = assets + untracked_tgt` | same |
| `markets[srcId]`, `srcAdapter.supplyShares` | `withdraw(assets)` | — |
| `markets[tgtId]`, `tgtAdapter.supplyShares` | `supply(assets)` | same |
| `vault.assetBalance` | `+= assets + untracked_src`, then `−= assets` | `−= assets` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep untracked interest out of idle balance

In a market→market leg, the pinned VaultV2 receives exactly assets from the deallocate adapter and then sends exactly assets to the allocate adapter, while untracked_src only changes the returned cap allocation. Adding untracked_src to vault.assetBalance creates fake idle liquidity in the simulated state, so a later idle→market withdrawal in the same greedy plan can be emitted even though the vault never received those tokens and will revert.

Useful? React with 👍 / 👎.

Comment thread docs/tibs/TIB-2026-07-29-vault-v2-public-allocator-shared-liquidity.md Outdated
Comment thread docs/tibs/TIB-2026-07-29-vault-v2-public-allocator-shared-liquidity.md Outdated
Comment thread docs/tibs/TIB-2026-07-29-vault-v2-public-allocator-shared-liquidity.md Outdated
Comment thread docs/tibs/TIB-2026-07-29-vault-v2-public-allocator-shared-liquidity.md Outdated
Foulks-Plb and others added 4 commits August 18, 2026 09:26
Freezes the design of a Vault V2 mirror of the V1 PublicAllocator
shared-liquidity engine, based on the new BluePublicAllocator periphery
contract in morpho-org/vault-v2.

Additive only: the V1 surface is untouched, the new symbols mirror V1
names with a VaultV2 suffix, and the engine is deliberately not wired
into any transaction flow (deferred to the blue bundles migration).

Records the contract-level finding that VaultV2 rebases allocation[id]
to expectedSupplyAssets rather than incrementing it, so shared allocation
ids do not net to zero across a reallocation and allocation[id] never
bounds the deallocate leg.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Rubilmax
Rubilmax force-pushed the vault-v2-public-allocator-tib branch from b2d0b3d to 7d4a219 Compare August 18, 2026 07:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants