Skip to content

Uniswap V2 implementation with extensions: TWAP oracle, configurable swap fees, flash loans and slippage protection

Notifications You must be signed in to change notification settings

Kazopl/amm-uniswap-v2-plus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Uniswap-Style AMM (V2-based + Extensions)

License: MIT Solidity

A production-grade Uniswap V2-style Automated Market Maker with extensions including TWAP oracle, adjustable fees, and sandwich protection. Built with Foundry.

Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                            AMM SYSTEM OVERVIEW                              │
└─────────────────────────────────────────────────────────────────────────────┘

                              ┌──────────────────┐
                              │   AMMRouter      │
                              │                  │
                              │ • addLiquidity   │
                              │ • removeLiquidity│
                              │ • swap*          │
                              │ • getAmounts*    │
                              └───────┬──────────┘
                                      │
                    ┌─────────────────┼─────────────────┐
                    │                 │                 │
                    ▼                 ▼                 ▼
            ┌──────────────┐  ┌──────────────┐  ┌──────────────┐
            │   AMMPair    │  │   AMMPair    │  │   AMMPair    │
            │   (A/B)      │  │   (B/C)      │  │   (A/WETH)   │
            │              │  │              │  │              │
            │ • LP tokens  │  │ • LP tokens  │  │ • LP tokens  │
            │ • TWAP oracle│  │ • TWAP oracle│  │ • TWAP oracle│
            │ • swap()     │  │ • swap()     │  │ • swap()     │
            │ • mint()     │  │ • mint()     │  │ • mint()     │
            │ • burn()     │  │ • burn()     │  │ • burn()     │
            └──────────────┘  └──────────────┘  └──────────────┘
                    │                 │                 │
                    └─────────────────┼─────────────────┘
                                      │
                              ┌───────▼───────┐
                              │  AMMFactory   │
                              │               │
                              │ • createPair  │
                              │ • getPair     │
                              │ • setFeeTo    │
                              │ • setSwapFee  │
                              └───────────────┘


┌─────────────────────────────────────────────────────────────────────────────┐
│                           SWAP FLOW                                         │
└─────────────────────────────────────────────────────────────────────────────┘

    User                Router                  Pair                 Tokens
      │                    │                      │                     │
      │  swapExact...()    │                      │                     │
      │ ──────────────────►│                      │                     │
      │                    │                      │                     │
      │                    │  transferFrom(user)  │                     │
      │                    │ ◄────────────────────┼─────────────────────│
      │                    │                      │                     │
      │                    │  transfer(pair)      │                     │
      │                    │ ─────────────────────┼────────────────────►│
      │                    │                      │                     │
      │                    │  swap(out, to)       │                     │
      │                    │ ────────────────────►│                     │
      │                    │                      │                     │
      │                    │                      │  verify K invariant │
      │                    │                      │  update reserves    │
      │                    │                      │  update TWAP        │
      │                    │                      │                     │
      │                    │                      │  transfer(user)     │
      │                    │                      │ ────────────────────►
      │  receive tokens    │                      │                     │
      │ ◄──────────────────┼──────────────────────┼─────────────────────│

AMM Mathematics

Constant Product Formula

The core invariant of the AMM:

x × y = k

where:
  x = reserve of token A
  y = reserve of token B
  k = constant (increases with fees)

Swap Calculation

For a swap of Δx tokens in:

Δy = (y × Δx × (10000 - fee)) / (x × 10000 + Δx × (10000 - fee))

where:
  Δx = input amount
  Δy = output amount
  fee = swap fee in basis points (default: 30 = 0.3%)

Price Impact

Price Impact = 1 - (output_amount / (input_amount × spot_price))

Spot Price = reserve_out / reserve_in

Liquidity Token Minting

First deposit:

LP_tokens = sqrt(amount0 × amount1) - MINIMUM_LIQUIDITY

Subsequent deposits:

LP_tokens = min(
    (amount0 × totalSupply) / reserve0,
    (amount1 × totalSupply) / reserve1
)

TWAP Oracle

Time-Weighted Average Price calculation:

price0CumulativeLast += (reserve1 / reserve0) × timeElapsed
price1CumulativeLast += (reserve0 / reserve1) × timeElapsed

TWAP = (priceCumulative_end - priceCumulative_start) / timeElapsed

Features

AMMPair

  • Constant Product AMM: x × y = k invariant
  • LP Tokens: ERC-20 liquidity provider tokens
  • TWAP Oracle: Cumulative price tracking for external use
  • Flash Loans: Borrow tokens within a single transaction
  • Skim/Sync: Balance recovery utilities

AMMFactory

  • Pair Creation: CREATE2 for deterministic addresses
  • Adjustable Fees: Configurable swap fee (max 1%)
  • Protocol Fees: Optional fee recipient for protocol revenue

AMMRouter

  • Liquidity Management: Add/remove with slippage protection
  • Token Swaps: Single and multi-hop swaps
  • ETH Support: Native ETH via WETH wrapper
  • Deadline Protection: Transaction expiration

Installation

# Clone the repository
git clone https://github.com/Kazopl/amm-uniswap-v2-plus.git
cd amm-uniswap-v2-plus

# Install dependencies
forge install OpenZeppelin/[email protected]
forge install foundry-rs/forge-std

# Build
forge build

# Run tests
forge test

Environment Setup

Create a .env file:

PRIVATE_KEY=your_private_key_here
ARBITRUM_SEPOLIA_RPC_URL=https://sepolia-rollup.arbitrum.io/rpc
ARBISCAN_API_KEY=your_arbiscan_api_key
WETH_ADDRESS=0x... # WETH on Arbitrum Sepolia

Testing

# Run all tests
forge test

# Run with verbosity
forge test -vvv

# Run unit tests
forge test --match-path "test/unit/*"

# Run fuzz tests
forge test --match-path "test/fuzz/*"

# Run invariant tests
forge test --match-path "test/invariant/*"

# Gas report
forge test --gas-report

Deployment

source .env

WETH_ADDRESS=0x... forge script script/DeployAll.s.sol:DeployAll \
  --rpc-url $ARBITRUM_SEPOLIA_RPC_URL \
  --private-key $PRIVATE_KEY \
  --broadcast \
  --verify \
  --etherscan-api-key $ARBISCAN_API_KEY

Security

Threat Model

Threat Mitigation
Reentrancy ReentrancyGuard on all state-changing functions
Price Manipulation TWAP oracle, not spot price for external use
Sandwich Attacks Slippage protection via amountMin parameters
Flash Loan Attacks K invariant check after callback
Integer Overflow Solidity 0.8.24 built-in checks
Front-Running Deadline parameter, user-set slippage
LP Drain Minimum liquidity permanently locked

Attack Surfaces

  1. MEV/Sandwich: Mitigated by slippage parameters
  2. Oracle Manipulation: TWAP smooths price over time
  3. Liquidity Removal: Proportional burning ensures fairness
  4. Flash Loans: K invariant must hold after callback

Invariants Verified

  1. reserve0 × reserve1 never decreases (K invariant)
  2. LP total supply ≥ MINIMUM_LIQUIDITY
  3. Token balances ≥ reserves
  4. Swap fee ≤ MAX_SWAP_FEE_BPS

Gas Optimization

Function Gas (approx)
createPair() ~2,500,000
addLiquidity() ~150,000
removeLiquidity() ~120,000
swapExactTokensForTokens() ~100,000
mint() ~120,000
swap() ~80,000

Project Structure

amm-uniswap-v2-plus/
├── src/
│   ├── AMMPair.sol          # Pair with LP tokens + TWAP
│   ├── AMMFactory.sol       # Pair factory
│   ├── AMMRouter.sol        # User-facing router
│   ├── interfaces/
│   │   ├── IAMMPair.sol
│   │   ├── IAMMFactory.sol
│   │   ├── IAMMRouter.sol
│   │   └── IWETH.sol
│   ├── libraries/
│   │   └── AMMLibrary.sol   # Math helpers
│   └── mocks/
│       ├── MockERC20.sol
│       └── WETH.sol
├── test/
│   ├── BaseTest.sol
│   ├── unit/
│   │   ├── AMMFactory.t.sol
│   │   ├── AMMPair.t.sol
│   │   └── AMMRouter.t.sol
│   ├── fuzz/
│   │   └── AMMFuzz.t.sol
│   └── invariant/
│       └── AMMInvariant.t.sol
├── script/
│   ├── DeployAll.s.sol
│   └── Interactions.s.sol
├── foundry.toml
└── README.md

License

MIT License - see LICENSE for details.

Acknowledgments

About

Uniswap V2 implementation with extensions: TWAP oracle, configurable swap fees, flash loans and slippage protection

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published