Pure Rust implementation of Curve Finance AMM math. Exact on-chain match — no tolerances, no approximations, wei-level precision.
Every registered pool is differentially fuzz-tested against its on-chain get_dy: our get_amount_out is called with random swap amounts and the result is compared with an on-chain call at the same block. The test requires exact wei-level match — no tolerances, no approximations. Pools that don't match are not registered.
The pool registry covers all live Curve pools (non-empty, non-paused, functional tokens) across factory and legacy deployments.
| Chain | Verified / Live pools | Last indexed |
|---|---|---|
| Ethereum | 1128 / 1128 |
2026-05-25 |
| Base | 158 / 158 |
2026-05-25 |
| Arbitrum | 203 / 203 |
2026-05-25 |
Compared against revm executing the same pool's on-chain get_dy bytecode. Both produce identical results (wei-exact).
Pure computation — revm with pre-loaded state (EVM interpretation overhead only):
| Pool type | curve-math | revm | Speedup |
|---|---|---|---|
| StableSwap 2-coin (3pool) | 1.6 µs | 13 µs | 8x |
| StableSwapNG with oracle rates (sUSDS/USDT) | 1.4 µs | 38 µs | 27x |
| TwoCryptoNG Cardano cubic (crvUSD/FXN) | 6.4 µs | 34 µs | 5x |
| TriCryptoNG 3-coin hybrid (crvUSD/WETH/CRV) | 4.5 µs | 52 µs | 12x |
Realistic simulation — revm with full EVM setup (DB, accounts, storage, bytecode):
| Pool type | curve-math | revm | Speedup |
|---|---|---|---|
| StableSwap 2-coin (3pool) | 1.6 µs | 150 µs | 94x |
| StableSwapNG with oracle rates (sUSDS/USDT) | 1.4 µs | 448 µs | 320x |
| TwoCryptoNG Cardano cubic (crvUSD/FXN) | 6.4 µs | 313 µs | 49x |
| TriCryptoNG 3-coin hybrid (crvUSD/WETH/CRV) | 4.5 µs | 358 µs | 80x |
MacBook M2, Rust 1.82, revm 36. Reproduce: cd crates/curve-math/benches/revm-comparison && cargo bench
All 12 Curve pool variants:
| Variant | Type | Solver | Example pools | Vyper source |
|---|---|---|---|---|
StableSwapV0 |
StableSwap | Newton | sUSD, Compound, USDT, y, BUSD | StableSwapSUSD.vy |
StableSwapV1 |
StableSwap | Newton | 3pool, ren, sbtc, hbtc | StableSwap3Pool.vy |
StableSwapV2 |
StableSwap | Newton | FRAX/USDC, factory plain | SwapTemplateBase.vy |
StableSwapSTETH |
StableSwap | Newton | Lido stETH/ETH | StableSwapSTETH.vy |
StableSwapALend |
StableSwap | Newton | Aave, sAAVE, IB, aETH | SwapTemplateA.vy |
StableSwapNG |
StableSwap | Newton | StableSwap-NG (plain + meta) | CurveStableSwapNG.vy |
StableSwapMeta |
StableSwap | Newton | GUSD, HUSD, factory meta | SwapTemplateMeta.vy |
TwoCryptoV1 |
CryptoSwap | Newton | CRV/ETH (legacy) | CurveCryptoSwap2ETH.vy |
TwoCryptoNG |
CryptoSwap | Cardano cubic | crvUSD/FXN (MATH v2.0.0) | TwocryptoMath.vy |
TwoCryptoStable |
StableSwap | Newton | crvUSD/WETH (MATH v0.1.0) | Etherscan |
TriCryptoV1 |
CryptoSwap | Newton | tricrypto2 (USDT/WBTC/WETH) | CurveCryptoMath3.vy |
TriCryptoNG |
CryptoSwap | Hybrid cubic+Newton | tricrypto-ng (USDC/WBTC/WETH) | CurveTricryptoOptimized.vy |
| Crate | Description |
|---|---|
curve-math |
Pure math — Newton solvers, Cardano cubic, fee formulas, Pool enum. Only depends on alloy-primitives. |
curve-adapter |
Pool discovery, variant detection, and build_pool() — adapts raw on-chain data into curve-math::Pool. |
[dependencies]
# Swap computation only (construct Pool manually)
curve-math = { git = "https://github.com/sunce86/curve-math", features = ["swap"] }
# Full pipeline: raw on-chain data → Pool (includes curve-math)
curve-adapter = { git = "https://github.com/sunce86/curve-math" }With curve-adapter (recommended — handles rates, precisions, validation):
use curve_adapter::{CurveVariant, RawPoolState, build_pool};
let state = RawPoolState {
variant: CurveVariant::StableSwapV2,
balances: vec![bal0, bal1],
token_decimals: vec![18, 6],
amp,
fee: Some(fee),
..Default::default()
};
let pool = build_pool(&state)?;
let dy = pool.get_amount_out(0, 1, dx);With curve-math directly (when you already have rates/precisions):
use curve_math::Pool;
let pool = Pool::StableSwapV2 { balances, rates, amp, fee };
let dy = pool.get_amount_out(0, 1, dx);crates/
curve-math/ # Pure math, Pool enum, fuzz tests, benchmarks
src/core/ # Stateless math ported line-by-line from Vyper
src/swap/ # get_amount_out/in, spot_price (feature "swap")
src/pool.rs # Pool enum (feature "swap")
tests/ # Differential fuzz tests (RPC-based)
registry/ # Verified pool lists per chain
curve-adapter/ # Variant detection + pool construction
src/build.rs # RawPoolState → Pool, interpolate_a()
src/detect.rs # detect_variant() from on-chain probing
src/variant.rs # CurveVariant enum (12 variants)
Licensed under the Business Source License 1.1 (see LICENSE).
Free for non-production use: research, testing, auditing, and education. Production use generating revenue requires a commercial license.
For commercial licensing, contact: dusan.stanivukovic@gmail.com