Skip to content

fluidbase9/fluid-stable-amm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fluid Stable AMM

Production-grade USDC/USDT StableSwap pool on Base mainnet — MIT licensed, open source, forkable.

Built by Fluid Wallet · Auditable math · Deploy in one command


What is this?

A StableSwap AMM (like Curve Finance) for stablecoins on Base. It uses the Curve invariant to provide:

  • Near-zero slippage for USDC↔USDT swaps
  • 4 bps (0.04%) swap fee — among the lowest available
  • 50% admin fee → Fluid treasury
  • A=100 amplification factor — optimal for pegged assets

The Math (Curve invariant, n=2)

A·n^n·(x + y) + D = A·n^n·D + D^(n+1) / (n^n · x · y)

Simplified for n=2:

4A(x + y) + D = 4AD + D³ / (4xy)

Where:

  • x, y = token reserves (scaled to 18 decimals)
  • D = total liquidity invariant (computed via Newton-Raphson)
  • A = amplification factor (100 for stablecoins)

Key property: As A → ∞, the curve approaches a constant-sum (x+y=D) with zero slippage. As A → 0, it approaches Uniswap's constant-product (xy=k). A=100 is the sweet spot.

Newton-Raphson for D

D_{n+1} = (Ann·S/A_PREC + D_P·N) · D_n / ((Ann - A_PREC)·D_n/A_PREC + (N+1)·D_P)

Where D_P = D³ / (N^N · x₀ · x₁), iterated until |D_{n+1} - D_n| ≤ 1.


Contracts

Contract Description
StableMath.sol Pure math library: getD(), getY(), calculateWithdrawOneCoin()
StableAMM.sol Main pool: swap, addLiquidity, removeLiquidity
StableAMMFactory.sol Factory: deploy pools for any token pair
LPToken.sol ERC-20 LP token (minted/burned only by pool)
IStableAMM.sol Interface for integrators

Security features

  • nonReentrant on all state-changing functions (OpenZeppelin)
  • minOut / slippage protection on every user-facing function
  • deadline parameter on swap() prevents stale transactions
  • Admin-gated: rampA, collectAdminFees, pause, transferAdmin
  • Newton-Raphson capped at 255 iterations with convergence check
  • All math in uint256, no unsafe casting
  • Linear A-ramping with 10x max change per ramp (safe migration)

Directory Structure

fluid-stable-amm/
├── src/
│   ├── StableAMM.sol              # Main pool
│   ├── StableAMMFactory.sol       # Factory
│   ├── LPToken.sol                # ERC-20 LP token
│   ├── libraries/
│   │   └── StableMath.sol         # Pure math
│   └── interfaces/
│       └── IStableAMM.sol         # Interface
├── test/
│   ├── StableAMM.t.sol            # Fork tests (Base mainnet)
│   └── StableMath.t.sol           # Math unit tests
├── script/
│   ├── Deploy.s.sol               # Deploy pool + factory
│   └── DeployFactory.s.sol        # Deploy factory only
├── sdk/
│   └── src/
│       ├── index.ts               # Re-exports
│       ├── pool.ts                # StableAMMPool class
│       ├── math.ts                # Off-chain math (BigInt)
│       └── types.ts               # TypeScript types
├── foundry.toml
└── .env.example

Quick Start

1. Prerequisites

# Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup

# Install OpenZeppelin
forge install OpenZeppelin/openzeppelin-contracts

2. Clone and build

git clone https://github.com/fluidwallet/fluid-stable-amm
cd fluid-stable-amm
forge build

3. Run tests

# Math unit tests (no RPC needed)
forge test --match-contract StableMathTest -vvv

# Fork tests (requires BASE_RPC_URL)
cp .env.example .env
# Fill in BASE_RPC_URL
forge test --fork-url $BASE_RPC_URL -vvv

4. Deploy to Base mainnet

cp .env.example .env
# Fill in PRIVATE_KEY, BASE_RPC_URL, BASESCAN_API_KEY

forge script script/Deploy.s.sol \
  --rpc-url base \
  --broadcast \
  --verify \
  --etherscan-api-key $BASESCAN_API_KEY

Expected cost: ~$0.10–$0.50 on Base mainnet.


Integrate (TypeScript SDK)

npm install @fluid-stable-amm/sdk viem
import { StableAMMPool } from "@fluid-stable-amm/sdk";
import { createPublicClient, http } from "viem";
import { base } from "viem/chains";

const client = createPublicClient({ chain: base, transport: http() });

const pool = new StableAMMPool(
  {
    poolAddress: "0x...",   // deployed pool
    token0: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
    token1: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2", // USDT
    lpToken: "0x...",
    ampFactor: 100n,
    swapFee: 4n,
    adminFee: 5000n,
  },
  client
);

// Get pool stats
const stats = await pool.getPoolStats();
console.log("TVL:", stats.reserve0 + stats.reserve1);

// Off-chain quote (instant, no RPC)
const quote = pool.quoteSwap(1000_000000n, 0, stats.reserve0, stats.reserve1);
console.log("Get:", quote.amountOut, "USDT");
console.log("Fee:", quote.fee);
console.log("Price impact:", quote.priceImpact * 100, "%");

Fork This Pool

Want to deploy your own USDC/USDT pool or a different pair? Just:

forge script script/Deploy.s.sol \
  --rpc-url <your-rpc> \
  --broadcast \
  --verify

Or deploy via the factory for any ERC-20 pair:

StableAMMFactory factory = StableAMMFactory(FACTORY_ADDRESS);
address myPool = factory.deployPool(
    TOKEN_A,
    TOKEN_B,
    100,   // A factor
    4      // 0.04% fee
);

Token Addresses (Base Mainnet)

Token Address
USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
USDT 0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2

License

MIT — do whatever you want. Fork it, deploy it, build on it.


Built by Fluid Wallet · Report issues

About

Fluid StableSwap AMM — production-grade stablecoin AMM on Base mainnet. Solidity contracts + Foundry tests + TypeScript SDK. MIT licensed.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors