Troubleshooting
Who this is for: Developers and integrators debugging quote/swap failures, SDK or RPC issues, deployment/verification problems, or rebalancing with Mento V3. For end-user issues (getting stables, swap failed in app), see User troubleshooting.
Quick reference: why did my swap or quote revert?
The pool (and Router) can revert for these reasons. Check your revert message or transaction trace first:
ReserveValueDecreased
Swap would decrease pool value at oracle after fees (value-protection check failed).
Usually means quote was stale or fee/rate changed; re-quote and retry with a fresh amount.
TradingSuspended
Circuit breaker has tripped for this feed; trading is halted.
Wait until breakers are reset; check BreakerBox / OracleAdapter for the feed’s trading mode.
NoRecentRate
Oracle report is older than the configured expiry (stale).
Wait for a new oracle update or check SortedOracles / Chainlink relay for the feed.
FXMarketClosed
FX market-hours breaker says the market is closed for this feed.
Trade during configured market hours, or use a pool that does not gate on market hours.
TradingLimitsV2 (limit exceeded)
Net flow for a token in the 5-minute or 1-day window would exceed the pool’s limit.
Use a smaller amount, wait for the rolling window to expire, or try again later.
Insufficient liquidity (Router)
Router/pool has no liquidity for the requested output.
Check pool reserves and that the pool exists for the pair.
Expired (Router)
Transaction submitted after the deadline passed.
Increase deadline (e.g. block.timestamp + 300) and resubmit.
Insufficient output (Router)
Output was less than amountOutMin (slippage).
Re-quote and raise amountOutMin slightly or accept a lower minimum.
Swap and quote
Swap reverted: value protection, limits, or oracle
Every swap is checked in this order:
Oracle rate — The pool calls
oracleAdapter.getFXRateIfValid(referenceRateFeedID). If the adapter reverts, the swap reverts withTradingSuspended,NoRecentRate, orFXMarketClosed. So: ensure the feed is recent, trading is allowed, and (if applicable) FX market is open.Value protection — After the swap, the pool’s reserve value at the oracle must not decrease (after crediting fees). If it would, the pool reverts with
ReserveValueDecreased. This can happen if the quote was computed with an older rate or different fee.TradingLimitsV2 — After the swap, per-token net flow in the 5-minute and 1-day windows must stay within the pool’s configured limits. If a limit would be exceeded, the swap reverts.
Practical steps: Re-fetch a quote immediately before sending the transaction. Use the same pool and rate feed the pool uses. If the revert is ReserveValueDecreased, your executed rate/fee differed from the one used for the quote. If the revert is from TradingLimitsV2, reduce size or wait. See TradingLimitsV2 and BreakerBox.
Quote doesn’t match execution
Quotes are valid only at the current block’s oracle rate and fee. If the user sends the tx later, the rate may have changed or the oracle may have become invalid. Always re-fetch the quote right before building the transaction, and use a small slippage tolerance (e.g. amountOutMin = quote * 99 / 100) if needed.
getAmountOut or Router getAmountsOut fails
Invalid pair or pool: Ensure the pool exists for the token pair (use FPMMFactory
getPool(token0, token1)or RouterpoolFor). Tokens must be sorted by address (token0<token1).Oracle invalid:
getAmountOutcalls the samegetFXRateIfValidas the swap. If the oracle is suspended, stale, or market closed, the call reverts. Useadapter.getRate(rateFeedID)(no revert) to inspecttradingMode,isRecent, andisFXMarketOpenbefore quoting.Wrong rate feed ID: The pool’s
referenceRateFeedIDmust match a feed that the OracleAdapter and BreakerBox know. Check OracleAdapter and Addresses for the correct adapter and feed setup per chain.
Router vs direct pool calls
Router: Use the Router for exact-input swaps and for mint/burn so it handles transfers and pool calls. Approve the Router for the input token(s). The Router reverts if the pool reverts (oracle, limits, value protection) or if output <
amountOutMinordeadlinehas passed.
Mint and burn (liquidity)
Mint reverted
Wrong ratio or approval
You must transfer both tokens to the pool in the current reserve ratio. Use pool.quoteMint(amount0, amount1) or Router quoteAddLiquidity to get the required amounts. Approve the pool (or Router) for both tokens.
Burn reverted
Wrong LP amount or approval
Transfer the LP tokens to the pool first, then call burn(to). Approve the pool (or Router) for the LP tokens. Ensure you are not burning more than the pool’s total supply.
“Insufficient liquidity” on mint
First mint must meet minimum
The first mint uses sqrt(amount0*amount1) - MINIMUM_LIQUIDITY; ensure amounts are large enough.
See FPMM — Mint and burn and Router for exact signatures.
Rebalancing (keepers / strategies)
If you are calling rebalance on a pool or a liquidity strategy:
NotLiquidityStrategy
Caller is not allowlisted on the pool.
Only addresses set via setLiquidityStrategy(addr, true) can call rebalance.
PriceDifferenceTooSmall
Reserve price deviation from oracle is below the pool’s threshold.
Check getRebalancingState(); only rebalance when priceDifference >= rebalanceThreshold.
PriceDifferenceNotImproved / PriceDifferenceMovedInWrongDirection / PriceDifferenceMovedTooFarFromThresholds
Rebalance did not meet post-rebalance checks (direction preserved, no overshoot).
Strategy must return the other token in the right amount so the new deviation is still ≥ threshold and in the same direction.
InsufficientAmount0In / InsufficientAmount1In
Strategy did not send back enough of the other token (minimum repayment / incentive cap).
Strategy must return at least the minimum required by the pool’s rebalance incentive cap.
Use pool.getRebalancingState() to decide if and how much to rebalance. See Liquidity strategies and FPMM — Rebalance.
Oracle and circuit breakers
TradingSuspended: The BreakerBox has set the feed’s trading mode to suspended (e.g. MedianDeltaBreaker or ValueDeltaBreaker tripped). No swaps or quotes using that feed succeed until the breaker is reset and the cooldown has passed.
NoRecentRate: The median report timestamp for the rate feed is older than
reportExpiry. Relayers must submit a fresh price; check SortedOracles or the Chainlink relayer for that feed.FXMarketClosed: The pool uses
getFXRateIfValid, which checks FX market hours. Use a feed without market-hours gating or wait until the market is open.
To inspect without reverting: call oracleAdapter.getRate(rateFeedID) and check tradingMode, isRecent, isFXMarketOpen. See OracleAdapter and BreakerBox.
SDK and integration
SDK returns wrong network or pairs
Using V2 Broker instead of V3 FPMM
V3 uses FPMM pools and the Router for quotes and swaps, not the legacy Broker. Point the SDK at the V3 factory, Router, and pool addresses; see Mento SDK and Deployments.
Wrong or stale quote
Caching or wrong pool
Ensure you are querying the correct pool for the token pair and re-fetch quotes before sending a transaction.
RPC or provider errors
Wrong RPC URL or chain
Use a supported chain (e.g. Celo, Monad) and a valid RPC endpoint. See Deployments and Addresses.
Contracts and deployments
Wrong pool or router address
Outdated or wrong chain
Use Deployments → Addresses for the chain you are on; verify factory, Router, and pool on a block explorer.
Pool not found for pair
Pool not deployed or wrong token order
Factory returns getPool(token0, token1) with tokens sorted by address. Ensure the pool is deployed for that pair on the correct factory.
Verification failed on explorer
Source or constructor args
Follow Verification for the correct compiler settings and constructor arguments.
More
Integration — How to integrate stables and oracles.
Smart contracts — FPMM, Router, OracleAdapter, TradingLimitsV2, BreakerBox.
Deployments — Addresses, verification, parameters.
User troubleshooting — End-user issues (getting stables, swap in app, CDP).
Last updated