Summary
The YieldBasis WETH market (Curve pool 0x656341Ef90b622c6634e0573772FfB7f3669b9f3, live since 21 May 2026 at A = 5) has been losing value since mid-June. That happened even though the pool charges 1.36% to 2.82% per swap and receives about 5% of its value a year in donations. Replaying the market with the same settings in our simulator shows the same decline.
We built a new pool policy, YBOraclizedPolicy, to fix this. It verifies signed Pyth ETH/USD price reports on chain and uses that external reference price in two places. First, a swap that moves the pool toward a fresh reported price pays 0.5% plus 67.5% of its edge above 0.5%, capped at 1.75%, and the discount fades over 5 minutes as the report ages. Other swaps pay 1.75%. Second, the pool re-centers price_scale toward the reported price, guided by 80-minute and 160-minute moving averages that hold near the fast average in a range and step toward the report in a trend. The update also includes a fix for a route where depositing into and withdrawing from the leveraged position could move value out of the pool without paying proper fees.
The backtest replays every 12-second Ethereum slot.
| Current settings | New policy | |
|---|---|---|
| YieldBasis position, value in ETH, 24 March 2025 to 1 October 2026 | +3.6% a year | +8.5% a year |
| The same, live pool period from 10 June to 1 October 2026 | −3.0% a year | +3.6% a year |
| On chain, one yb-WETH share in ETH, 10 June to 30 September | −2.4% a year |
The governance votes will link here. We start with WETH at A = 5, follow with the Bitcoin pools, and then move to a higher A, over roughly a month.
1. The live WETH pool
A YieldBasis market keeps a 2x leveraged position in a Curve pool of crvUSD and the underlying asset through its leveraged AMM (the LevAMM), and issues liquidity tokens (LT, here yb-WETH) to depositors. Pool liquidity concentrates around price_scale. Whenever the market moves, arbitrageurs trade against the pool while their edge exceeds fees and execution costs, and the pool earns the swap fee. Once the market drifts away from price_scale, the pool has to re-center (re-peg) it. A re-peg usually costs the pool part of its accumulated profit, so the pool only steps price_scale while its value stays above a protected level, set by the reserved profit fraction (RPF), and the rest of the profit may pay for re-pegs. YieldBasis also donates borrowing interest back into the pool as “refuel”, which funds more re-pegs.
So the pool loses value when it undercharges for the edge arbitrageurs take, or when it spends too much re-pegging toward the wrong price. It can also lose when price_scale lags far behind the market and the pool sits lopsided while prices move. Earlier posts (Tweak WETH pool parameters and Analysis and improvements of YB pools) tuned the native fee curve, the 0.5% re-peg step cap and the profit fraction around those trade-offs, and this note changes the reference price the pool steers by.
We compare from 10 June, because TVL was turbulent in the first three weeks after launch, with the market growing more than fivefold in ETH as deposits came in. From 10 June to 30 September, one yb-WETH share in ETH (the LT price per share, the accounting value of an unstaked share) fell 0.73%, or 2.4% a year, and by 19 October it was 0.91% down.
The market’s LT accounting value grew from 385 WETH just after launch to 3,235 WETH on 10 June, reached a highest sampled value of 13,726 WETH on 22 August and stood at 6,462 WETH on 21 October. From 10 June to 30 September, 5,390 swaps (4,829 of at least $1) traded $126M through the pool at a 1.51% average fee. The LevAMM borrowed at 10% a year, and the pool received 569k crvUSD in donations over the period, about 5% a year of its average value (it held about $32M on 21 October).
Why did growth stall? The WETH pool has no policy today. It relies on the native Twocrypto fee curve (1.36% to 2.82%) and re-pegs toward an exponential moving average of its own trade prices (ma_time 600 s, step at most 0.5%). The fee only looks at how far the pool’s balances sit from 50/50, so a trade that pushes the pool back toward the market price still pays at least 1.36%. Arbitrageurs wait until the market has moved past that fee. Until then the pool price drifts, and organic flow pays the same high rate. Meanwhile the internal average lags the market and gets pushed by the pool’s own trades, and the pool needs roughly 5% of its value a year in refuel to keep up.
We replayed those live settings (A = 5, fee 1.36% to 2.82%, RPF 45%, donations 5% a year, LevAMM fee 1.3%) from a fresh pool on 22 May 2026. From 10 June the simulated position loses 0.94% in ETH by 1 October, or 3.0% a year, close to what the chain shows. The simulated pool also behaves like the real one. Over the same dates its price_scale sat on average 0.88% from the Binance price, against 0.94% on chain, and both pools stayed close to 50/50 (between 46% and 52% crvUSD on chain).
The two value series still measure different things, though. The on-chain share price carries the split between staked and unstaked shares, real organic and liquidation volume, and user deposits and withdrawals, none of which the simulation models. Over the full 18 months the live settings return +3.6% a year in ETH, with long periods of large lag (in May and June 2025 price_scale sat up to about 20% under the market, and at least 10% under it for about 27 days in total) and a flat-to-falling value since July 2026.
2. The new policy
YBOraclizedPolicy plugs into the existing Twocrypto policy hooks. The pool asks it for the swap fee (get_fee) and the price_scale target (get_price_scale), and reports its state after every operation (update_pool_state). The pool contract stays untouched.
For its reference price, the policy reads signed Pyth Pro (Lazer) ETH/USD reports and has Pyth’s verifier contract check them on chain. Anyone can deliver a report. The policy admits it when the signature checks out, the report comes from the one-second channel, it was observed at most 12 seconds before the block, it is newer than the stored report, and its price falls between $100 and $100,000. Arbitrageurs bundle a fresh report with their swap because it cuts their fee. A keeper is planned to deliver a report with a dust swap when the stored report or the last pool operation is an hour old, or when Pyth has moved by more than the fallback fee.
Picking the one-second channel was deliberate. Faster channels at 50 ms or 200 ms hand an arbitrageur dozens of candidate prices inside the admission window to pick from. One report a second shrinks that menu a lot. We also ran the same backtest over 1 to 19 October 2026 with Pyth against Chainlink Data Streams, saw no clear winner, and stayed with Pyth.
Fees separate corrective swaps from everything else. When a swap moves the pool’s price toward the reported price without crossing it, the policy measures the swap’s edge at the report as edge = 1 − input value / output value, with both legs valued at the reported price. With a fresh report it charges
fee = min(1.75%, 0.50% + 67.5% × max(0, edge − 0.50%)).
A small correction therefore costs 0.5%, where the native curve charges at least 1.36% whatever the market does. Up to an edge of about 2.35% the arbitrageur keeps about a third of the edge above 0.5% and the pool takes the other two thirds, and above that the fee stays at 1.75% and the arbitrageur keeps what is left. The discount fades with the square root of the report’s age, so a small corrective swap that pays 0.5% with a fresh report pays about 1.1% after 75 seconds. After 5 minutes it pays the full 1.75%. Swaps away from the report, past it, or without a fresh report pay the 1.75% fallback, and deposits and withdrawals keep the pool’s own liquidity-fee rules.
For price_scale, the policy tracks two exponential moving averages of the observed price, with half-lives of 80 minutes (fast) and 160 minutes (slow). While the stored report is younger than 90 minutes, the observed price is that report. After that, the policy falls back to the pool’s spot price at the end of the previous operation (the current trade’s own price is never used), and every observation is clamped to between half and twice price_scale. With the trend defined as |fast / slow − 1|, the target is
target = fast + w × (observed − fast), with w = min(1, trend / 0.7%).
In a sideways market (w near 0) the target hugs the fast average and ignores the chop. Once the averages diverge by 0.7% or more, w reaches 1 and the target is the observed price itself, which is the Pyth report whenever one is fresh. At most once a block, the policy asks the pool to move half the distance to that target, capped at 0.5% of price_scale. The pool’s own cap and profit gate still apply, so price_scale moves only in blocks where the pool can pay for it.
On the Bitcoin pools (WBTC, cbBTC and tBTC), our earlier YBTwocryptoPolicy pioneered dual-EMA trend detection, and because it used only the pool’s own prices it had to extrapolate a target (slow + κ × (fast − slow) with κ = 1.3). Signed reports remove the need to extrapolate. The report now gives the pool a price to step toward, and the 80-minute and 160-minute averages stay on duty to detect the trend and set how far to step.
One more piece of the update covers the deposit-and-withdraw route from the summary. Arbitrageurs could use it to take value from the pool without paying proper fees, which was not healthy for the pool. We will publish the details once all markets have the fix.
| Parameter | Value | Why |
|---|---|---|
| Base fee | 0.50% | The cost of a small corrective swap with a fresh report. It lets arbitrageurs correct small moves and covers the noise between the report and the block. |
| Capture | 67.5% | The pool’s share of the edge above the base fee. Higher capture earns more per swap but leaves arbitrageurs less reason to correct the pool. |
| Fallback fee | 1.75% | Every swap that is not a fresh corrective swap. Protects the pool when there is no report. |
| Relax time | 5 min | The discount fades with the square root of the report’s age and is gone after 5 minutes. |
| Fast / slow half-life | 80 / 160 min | Filters minute noise and short spikes while following a trend within hours. |
| Trend gate | 0.70% | The averages’ gap at which the target is the observed price itself. |
| Step cap | 0.50% | The largest re-peg the policy requests at once, the same as the pool’s own 0.5% cap. |
| Report lifetime | 90 min | How long a report steers the averages. The keeper is planned to deliver a new one once the stored report is an hour old. |
| Reserved profit fraction | 42.9% (today 45%) | The share of profit protected from re-pegs. The rest may pay for them. |
| Donation rate | about 1.2% of pool value a year (today about 5%) | Set together with the profit fraction, near the top of the high-growth band (see the map below). |
| LevAMM fee | 1.5% (today 1.3%) | The fee on the LevAMM’s re-leverage trades. |
We searched the moving-average half-lives, the trend gate, the fee parameters and the step cap together on our cluster, then mapped the donation rate and profit fraction on 128 × 128 grids for the 100 best policy variants. Within that map we chose a point in the high-growth band.
3. Backtest
Our simulator replays Binance ETHUSDT trades on a uniform 12-second clock (one step per Ethereum slot) from 24 March 2025 to 1 October 2026, which is 556 days. Each slot settles against the market price one second into the slot, and crvUSD counts as one USDT. Alongside the market tape we feed the historical Pyth ETH/USD one-second channel. In each slot the simulated arbitrageur may use any report from 12 seconds before the slot to 3 seconds after it, and picks whichever report gives it the most profit, or none. The pool runs in a floating-point C++ model of the Twocrypto math, with YBOraclizedPolicy.vy ported line by line. After the contract audit we updated the port and re-ran the 1.6-million-cell grid of the 100 best variants, chosen setting included, and every result matched.
In each slot the arbitrageur trades the pool toward the Binance price when the marginal edge exceeds 0.015% and the sized swap is profitable after fees. The LevAMM’s 2x re-leverage trades, at the LevAMM fee, and the liquidity operations they need run in the same loop. In a slot without other trades, a simulated keeper delivers a newer report with a dust swap when the stored report or the last pool operation is an hour old, or when Pyth has moved by the fallback fee. The model has no organic retail flow and no lending liquidations. Real pools have both, so live results will differ. We measure each run by the ETH value of a YieldBasis position (its LP collateral at the market price, less its debt). In the grids, a run stops early if the seven-day average gap between price_scale and the market exceeds 30%. Over the past three months we spent weeks of time on our Curve research cluster on repeated multi-dimensional parameter searches, Nevergrad among them, on the order of hundreds of millions of simulated pool variations in total.
| 24 March 2025 to 1 October 2026 | Current settings | New policy |
|---|---|---|
| YieldBasis position, value in ETH | +3.6% a year | +8.5% a year |
| price_scale off the market: average / worst week | 2.1% / 15.7% | 1.2% / 8.2% |
| Time with the pool beyond 40/60 | 6% | about 1% |
| Swap volume | $1.8B | $5.1B |
| Average fee paid | 1.69% | 0.55% |
| Donations, % of pool value a year | 4.9% | 1.2% |
The detail view follows the chosen settings through the same 18 months in five panels. From the top come price_scale against the Binance price, then the pool’s own LP growth before leverage with its rolling 60-day rate, and the YieldBasis position’s growth with its rolling 7, 30 and 60-day rates. Below them sit the LevAMM’s balance sheet (cash, debt and LP collateral) and the pool’s balance skew with a sampled fee quote. These panels use the simulator’s internal accounting. Their rates differ slightly from the ETH-valued growth in the table.
In August 2026 ETH rose about 30% within days (see the live-period price chart in section 1). With the chosen donation and profit fraction, the new policy’s price_scale fell behind this jump and re-latched over the following weeks in the backtest, as each re-peg step still had to pass the pool’s profit gate. In our 40-minute trace samples it lagged the market by up to 12.4% on 21 August and spent about 11 days of August at least 5% below it. The current settings lagged by up to 6.3%, on 19 August. They spent about 5 hours at least 3% below the market. The new position’s market value fell 2.5 points from its 13 August peak to the 21 August low, was back above that peak on 2 September, and still finished the window ahead.
The map plots the chosen policy over 128 × 128 donation rates and profit fractions, and high growth forms a diagonal band where higher donations fund a higher protected profit. Above the band the pool keeps too much profit to pay for re-pegs and the run stops, while below it the pool overspends on re-pegs. Five of the 49 cells in the 7 × 7 box around the chosen point (the star) stop. The other 44 complete the 18-month backtest at 7.4% to 9.9% a year (median 8.5%), and the nearest stopped cell is two grid steps away, counting a diagonal step as one. The pair of 2.2% donation and a 46.9% profit fraction tracked this August episode more closely, within 2.3% of the market, but returned less in these backtests: 8.0% against 8.2% a year over 18 months on the cluster, and 0.7% against 3.6% a year in the live pool period. We prefer the lower donation and let price_scale detach and re-latch. The chosen cell gives 8.2% a year in the grid run on our cluster and 8.5% in the replay behind the charts. We suspect floating-point differences between machines, but have not isolated the cause. We also re-ran the map on four conversions of the Binance tape from USDT to USD. On the two built from Coinbase USDT/USD quotes, the chosen cell earns 9.0% a year and all 49 cells in the box complete. Two deliberately crude conversions (a 5-minute smoothed rate, and a rate taken only from Binance USDC/USDT) stop the chosen cell in the February 2026 crash, and under them 37 and 46 of the 49 box cells stop, the chosen cell included.
We chose the parameters on the same 18 months we report, and there is no separate test period yet. The simulator models only arbitrage flow, with fixed rules for which report an arbitrageur delivers and when the keeper acts. The chosen point sits two grid steps from a stopped cell near the upper edge of the band, so the donation rate and profit fraction have to be set as a pair, and set again whenever A changes. In this August replay price_scale stayed detached for several weeks before it re-latched.
4. Roadmap and code
Rollout starts with the WETH market at A = 5. A Curve DAO vote to attach YBOraclizedPolicy and set the reserved profit fraction goes up in the coming days, followed by a YieldBasis vote for the LevAMM fee and the donation rate. We will then watch the arbitrage flow and the keeper on chain. About a week later we plan to bring the same policy to the WBTC, cbBTC and tBTC pools.
Preliminary scans up to A = 15 point to higher returns at higher A, and a region around A = 8 looks like a good balance between earnings and stable tracking that we will study further. A higher A needs its own donation and profit-fraction settings, and ramping A on a live pool is technically demanding because both the pool math and the policy must stay safe while A moves. We will prove the policy at A = 5 first and publish a separate note before any A ramp, all within about a month. In parallel, we are researching ways to recognize non-toxic organic flow together with block builders, solvers and aggregators, so that such flow could pay much lower fees without opening a route for arbitrageurs.
The policy is in pull request curvefi/twocrypto-ng#139, with YBOraclizedPolicy.vy on the oraclized-policy branch. The contract the vote will attach is deployed and verified at 0xaea9…8a7d, with exactly the parameters in the table above. Before that, a small crvUSD/WETH test pool on mainnet, 0x8462…C030, ran an earlier version of the policy on live Pyth reports. The simulator is open too. It is the backtest harness curvefi/fx-arb-harness, the C++ pool and policy port curvefi/twocrypto-cpp, and the parameter search tooling curvefi/fx-optimization.






