FXSwap Mechanism and Parameter Design
FXSwap concentrates passive, full-range liquidity around a moving price_scale. It is designed for two-asset markets whose primary price discovery happens outside the pool and whose liquidity can be recentered through arbitrage, trading profit, and a finite refuel budget.
This page is for protocol teams evaluating or operating a market. Route aggregators can start with the integration guide; contract researchers should use the FXSwap Pool.
When FXSwap fits
Volatility alone does not determine whether a pair fits FXSwap. The important inputs are external price discovery, market depth, arbitrage access, desired concentration, and the cost of recentering.
| Market property | FXSwap implication |
|---|---|
| Reliable external reference market | Gives arbitrageurs a price against which to trade the pool |
| Sufficient external depth | Makes it more likely that arbitrage remains economical at useful trade sizes |
| Passive liquidity is preferred | Avoids requiring LPs to choose and manage active ranges |
| Sustainable recentering budget | Supports the desired concentration as the external price moves |
| Primary price discovery occurs in this Curve pool | Usually favors CryptoSwap rather than FXSwap |
Fiat FX pairs are a natural use case, but externally priced volatile pairs such as BTC/USD can also fit. They generally require more careful parameter selection and stress testing because larger or faster moves can increase recentering demand.
Price tracking and recentering
The pool maintains three related prices:
| Getter | Precision | Role |
|---|---|---|
last_prices() | 1e18 | Most recently observed normalized trade price |
price_oracle() | 1e18 | Exponential moving-average target derived from recent prices |
price_scale() | 1e18 | Current center of the pool's concentrated liquidity |
Each expresses the price of coins(1) in coins(0) units. A state-changing pool operation can update the oracle and, when the contract's conditions are satisfied, move price_scale toward price_oracle.
The deployed implementation evaluates tweak_price after swaps, liquidity additions, fixed-out withdrawals, and one-coin withdrawals. A call does not guarantee a recenter. The contract first updates price and profit state, then checks the oracle distance, configured step, profit threshold, and available refuel support before accepting a new price_scale.
The invariant concentrates liquidity around price_scale with amplification A. Unlike ordinary Twocrypto, the reviewed FXSwap invariant does not use gamma to shape a CryptoSwap curve; gamma() remains in the ABI for compatibility. Higher concentration can improve execution near the center but raises sensitivity to movement away from it and can increase the budget required to recenter.
The deployed source makes the state transition boundary explicit:
def tweak_price(
A_gamma: uint256[2],
_xp: uint256[N_COINS],
D: uint256,
) -> uint256:
"""
Updates price_oracle, last_price and conditionally adjusts
price_scale. This is called whenever there is an unbalanced
liquidity operation.
"""
Refuels do not set an external price and do not force a rebalance. They help pay the cost when the pool's normal recentering logic moves concentrated liquidity. Read Refuels for unlocking, protection, burn priority, and depletion.
Read FXSwap Oracles for the complete price direction, update cadence, EMA calculation, and safe integration boundary.
The recentering budget
Moving concentrated liquidity can reduce the pool's measured profit. FXSwap can fund that movement from:
- unlocked refuel shares that have passed the protection rules; and
- the pool's normal profit buffer when more funding is required.
This makes refuels a spendable market-liquidity budget, not recoverable principal. A protocol can observe the outstanding shares and public unlock parameters, but the deployed v2.1.0d interface does not expose separate getters for the exact locked, unlocked, protected, and immediately burnable amounts.
Dynamic fees
The swap fee moves between mid_fee() and out_fee() according to the pool's normalized balance. fee_gamma() controls the transition. A more balanced pool receives a fee nearer mid_fee; increasing imbalance moves the fee toward out_fee.
The deployed calculation uses the normalized xp balances, not raw token balances:
# balance indicator: 1e18 when balanced, toward 0 when imbalanced
B = PRECISION * N_COINS**N_COINS * xp[0] // B * xp[1] // B
# fee_gamma shapes the transition between the bounds
B = fee_gamma * B // (fee_gamma * B // 10**18 + 10**18 - B)
return (mid_fee * B + out_fee * (10**18 - B)) // 10**18
This excerpt names unpacked values for readability; the deployed contract stores the three fee parameters in packed_fee_params. Applications should call fee() or fee_calc(xp) rather than reimplementing the packed-state logic unless exact reproduction is required and versioned.
Parameter interactions
Parameters must be selected together. Raising concentration without providing enough room, fees, or recentering budget can improve quotes near the center while making the pool more fragile when the external price moves.
| Parameter | Unit / precision | Primary effect | Interaction to test |
|---|---|---|---|
A() | Contract amplification precision | Controls StableSwap-style concentration around price_scale | Higher concentration can improve near-center depth and increase recentering cost |
mid_fee() | 1e10 | Lower dynamic-fee bound | Affects routine execution and fee income |
out_fee() | 1e10 | Upper dynamic-fee bound | Must remain low enough for useful rebalancing flow while charging adverse imbalance |
fee_gamma() | 1e18 | Shapes the transition between fee bounds | Changes how quickly fees rise with imbalance |
ma_time() | approximate half-life, seconds | Controls oracle smoothing | Too slow can lag the external market; too fast can follow short-lived moves |
allowed_extra_profit() | 1e18 | Profit buffer before recentering | Interacts with how readily the pool moves price_scale |
adjustment_step() | 1e18 | Minimum recentering step | Affects the size and frequency of adjustments |
| Refuel schedule | Token amounts and seconds | Supplies the finite external budget | Must be evaluated against volatility, concentration, fees, and expected flow |
gamma() remains in the ABI for compatibility but is unused by the reviewed FXSwap invariant.
Mutable parameters
The factory admin can:
- ramp
Athroughramp_A_gammaand stop a ramp; - update
mid_fee,out_fee,fee_gamma,allowed_extra_profit,adjustment_step, and the internal EMA exponent parameter together throughapply_new_parameters; - update refuel duration and protection parameters;
- update
admin_fee,VIEW(), andMATH().
After a parameter event, applications should invalidate cached fee and recentering configuration, re-read the target pool, and reassess quotes, monitoring thresholds, withdrawal assumptions, and refuel demand. Index NewParameters, RampAgamma, StopRampA, SetDonationDuration, SetDonationProtection, SetAdminFee, and SetPeriphery.
Separate facts from model inputs
| Category | Examples | Interpretation |
|---|---|---|
| Onchain getters | A, fees, ma_time, price_oracle, price_scale, refuel state | Current deployed pool state at a specific block |
| Simulation inputs | Assumed refuel or boost rate, parameter search ranges, historical replay window | Choices made by the model; not necessarily onchain getters or future settings |
| Offchain market assumptions | External depth, reference prices, arbitrage costs, organic flow, gas | Inputs outside the pool that must be sourced and stress-tested |
Do not present a simulation input as a deployed default or an offchain assumption as a contract guarantee.
Parameters that work for one pair, time period, or external market can fail for another. Read the target pool's current values and treat historical configurations as dated evidence, not defaults.
Simulation-driven design
The Curve simulation workflow described in FXSwap Simulations: Behind the Scenes replays historical price data against many parameter combinations. It models whether arbitrage would be economical after external market depth and trading costs, then measures outcomes such as price tracking, imbalance, execution, pool profitability, and refuel demand.
A practical design workflow is:
- Define the external reference market, coin order, token behavior, and usable historical data.
- Model external liquidity depth and arbitrage costs instead of assuming unlimited rebalancing.
- Search combinations of
A, dynamic-fee settings, oracle smoothing, recentering parameters, and a proposed refuel schedule. - Evaluate several outcomes together; do not optimize only for the best near-center quote.
- Stress periods with fast moves, thin external liquidity, and prolonged one-directional flow.
- Deploy conservatively, monitor observed behavior, and re-simulate before changing parameters.
In simulation discussions, refuel rate or boost rate describes an assumed funding schedule. It is not a deployed pool getter.
The published simulation methodology models arbitrage flow and relies on assumptions about external depth and costs. Organic flow is uncertain, historical volatility may not repeat, and parameter optimization does not eliminate market or LP risk.
Dated performance evidence
An independent analysis summarized in the January 9, 2026 FXSwap article compared a YieldBasis WBTC route with a Uniswap V3 WBTC/USDC pool over November 1–December 17. For a $10 million quoted trade, the article reports better FXSwap execution in approximately 80% of observed blocks, with about 2% average improvement. Quotes included swap fees and excluded gas.
This is evidence for those pools, trade sizes, market conditions, and dates. It is not a general promise about another FXSwap deployment or smaller trades. Integrators should quote the live pool, and protocol teams should reproduce relevant simulations for their own market.
Operating checklist
- Monitor
price_oracle()relative toprice_scale()and the external reference market. - Track pool balances, realized fees, refuel shares, and refuel depletion.
- Measure live execution across representative trade sizes, not only spot price.
- Revisit assumptions when external market depth, token redemption paths, volatility, or flow changes.
- Simulate and govern parameter changes as a coordinated set.