[Bug] Input-side MGEN quotes miss the allowlisted v4 pool when buys require EXACT_OUTPUT
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 5.5k
- Forks
- 5.4k
- PR merge metrics
- No merged PRs in 30d
Description
Interface affected
- Web (app.uniswap.org)
- Wallet Extension
- Wallet Mobile App
App version
- Version: Current production deployment at the time of reproduction
- Production build
- Development build
System / environment
- Browser: Desktop browser; the exact version was not recorded
- OS / platform: macOS
- Wallet: A connected wallet is not required to reproduce the quote discrepancy
- Network: Robinhood Chain (
4663) - Input token: native ETH / WETH (
0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73) - Output token: MGEN (
0x822850e3d25A19258eE160F8Bb33FB1345B70372)
Summary
The production interface can return materially different economic results for the same ETH-to-MGEN buy intent depending on which field the user edits:
- Entering an ETH budget on the pay side creates an
EXACT_INPUTrequest. The canonical allowlisted MGEN/WETH pool is not compatible with exact-input MGEN buys, so the quote can fall back to a much shallower compatible pool. - Entering the desired MGEN amount on the receive side creates an
EXACT_OUTPUTrequest. That request can discover and execute through the canonical pool at a materially better result.
The canonical Morphogen contracts and exact-output path are operating as designed. The issue is that the ordinary user intent “I have X ETH; maximize the MGEN I receive” is represented only as exact input, without comparing a separately formulated exact-output result or explaining that the canonical pool was excluded by trade-type compatibility.
Steps to reproduce
- Open the production Uniswap web interface on Robinhood Chain.
- Select native ETH as the input and MGEN (
0x822850e3d25A19258eE160F8Bb33FB1345B70372) as the output. - Enter an ETH amount in the pay field and record the quoted MGEN output and selected route.
- Clear the pay field and enter the MGEN output available from the canonical pool in the receive field.
- Observe that the receive-side entry produces an exact-output quote through the canonical pool at a materially lower ETH cost per MGEN than the exact-input result.
One captured same-session reproduction showed:
| User entry | Request type | Result |
|---|---|---|
0.01 ETH in the pay field |
EXACT_INPUT |
1,865.43 MGEN, with a displayed 5.36% large-price-difference warning |
| Desired MGEN in the receive field | EXACT_OUTPUT |
The canonical hooked pool becomes available near the expected 0.01 ETH cost |
0.01 ETH budget in the Morphogen interface |
Bounded search over canonical exact-output quotes | Approximately 2,062.30124278 MGEN at the same observed state |
The numerical quote changes with pool state. The reproducible invariant is that field choice changes the trade type and therefore whether the canonical pool participates in the search.
Expected behavior
For the user intent “spend at most X ETH and maximize MGEN received,” the interface or routing layer should do one of the following:
- consider compatible exact-output-only hooked pools through an explicit, bounded intent-translation mechanism and compare the result with ordinary exact-input routes; or
- clearly disclose that the submitted exact-input search excludes an allowlisted canonical pool that supports the direction only as exact output, and guide the user to enter a desired output amount.
Any inverse exact-output search must be hook-aware. It is appropriate only where required input is monotonic with requested output over a known range for a fixed state, and execution must revalidate the quote and enforce a maximum input.
At minimum, the interface should not present a materially worse shallow-pool result as the complete “best price” answer without explaining that the result is scoped to exact-input-compatible routes.
Actual behavior
- Editing the pay field fixes the request as
EXACT_INPUT. - The canonical pool rejects exact-input MGEN buys with
BuyRequiresExactOutput. - The router can select a shallow secondary pool that accepts exact input and return materially less MGEN.
- Editing the receive field fixes the request as
EXACT_OUTPUT, after which the canonical pool can be selected. - The UI does not explain that the discrepancy is caused by trade-type compatibility or that a better separately formulated exact-output route exists.
The captured interface comparison did not include the raw quote payload or selected fallback Pool ID. It establishes the trade-type-dependent quote discrepancy, but it does not by itself identify the precise secondary route. Internal request logging or a fresh reproduction that records the route payload should identify that route directly.
Why this is an interoperability issue
Morphogen intentionally requires:
- MGEN buys as exact output; and
- MGEN sells as exact input.
These requirements apply in both formation and permanent phases. Exact output is a first-class v4 quote and execution mode. The reference router accepts a maximum ETH input, spends only the required amount, and refunds the remainder.
Uniswap's public Interface source derives tradeType from the edited field and preserves it in the quote request. The public UniRoute source likewise preserves the submitted trade type through quote processing, ranking, route selection, and trade construction. It does not automatically reinterpret an exact-input request as an inverse search over exact-output quotes.
The hook is source-verified, marked vanillaSwap: false, approved through the hooklist process, and present in UniRoute's Robinhood allowlist. The current hooklist schema does not expose direction-specific exact-input/exact-output capabilities, so allowlisting alone cannot communicate this constraint to generic routing.
This report does not allege a Uniswap v4 core-contract failure. Both the Uniswap and Morphogen contracts execute the trade type they receive. The requested fix concerns user-intent translation, routing capability discovery, and route disclosure.
Canonical production identifiers
- Chain: Robinhood Chain (
4663) - MGEN:
0x822850e3d25A19258eE160F8Bb33FB1345B70372 - Hook:
0xD27596adD474e5f645Cc1D2141e8Ff2A3FD33AEC - Pool ID:
0xae0acc3836678141dc58ac679d2ab66619afedf32095fde8f773aead524847ca - Reference router:
0xFCB9b9dC8DDCaA1a71869Bf0003d6da493C8BABb - Reference quoter:
0x5f586aBcED4982a88426034CD1c0Fa72F59b5756
Primary evidence
Integration and routing
- Approved hooklist submission
- Pinned hook registry entry
- Current UniRoute hook definition and Robinhood inclusion
- Interface trade-type derivation
- Interface quote-request construction
- Public UniRoute request parsing, quote processing, route selection, and trade construction
- Hooklist schema without directional trade-type capability fields
Morphogen contracts and production execution
- Formation trade-type validation
- Permanent trade-type validation
- Exact-output quoter
- Maximum-input and refund implementation
- Successful exact-output production transaction
- Canonical market
Related documentation and reproductions
- Uniswap docs PR #1152: document trade-type constraints for hooked pools
- Part 1: When “best route” depends on how you ask
- Part 2: What Uniswap's open-source router confirms after allowlisting
Requested ownership and next step
Please confirm whether this behavior should be addressed in the Interface intent layer, the Trading API / UniRoute routing layer, or through hook capability metadata. The production Interface repository is developed privately, so this issue is intended to provide a complete public reproduction that the appropriate internal team can route and act on.
No transaction is required to reproduce the discrepancy; comparing the two quote directions at the same pool state is sufficient.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with packages/uniswap/src/features/transactions/swap/stores/swapFormStore/hooks/useDerivedSwapInfo.ts and packages/uniswap/src/features/transactions/swap/services/tradeService/transformations/buildQuoteRequest.ts to trace how edited fields determine trade type. Then compare the linked UniRouteBL.ts request, quote-processing, route-selection, and trade-construction paths with the allowlist entry. Done requires an agreed owner and scoped behavior for comparing or disclosing exact-output-only routes, backed by a reproducible regression test or documented limitation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, blockchain, frontend
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100