Architecture Overview
Last modified:
Contract Architecture
CenturionDEX v3 is composed of core contracts (immutable protocol logic) and periphery contracts (convenience wrappers that most integrators use).
┌─────────────────────────────────────────────────────────┐
│ Periphery │
│ │
│ ┌──────────────┐ ┌─────────────────────────────────┐ │
│ │ SwapRouter02 │ │ NonfungiblePositionManager │ │
│ │ │ │ (mint/increase/decrease/collect) │ │
│ └──────┬───────┘ └──────────────┬──────────────────┘ │
│ │ │ │
│ ┌──────┴───────┐ ┌──────────────┴──────────────────┐ │
│ │ QuoterV2 │ │ V3Migrator │ │
│ │ (simulate) │ │ (v2 → v3) │ │
│ └──────────────┘ └────────────────────────────────-┘ │
└─────────────────────────┬───────────────────────────────┘
│ calls
┌─────────────────────────▼───────────────────────────────┐
│ Core │
│ │
│ ┌──────────────┐ ┌────────────────────────────┐ │
│ │ Factory │──────►│ Pool (one per pair+fee) │ │
│ │ createPool │ │ swap() / mint() / burn() │ │
│ │ getPool │ │ observe() (oracle) │ │
│ └──────────────┘ └────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘Core Contracts
Factory
The single entry point for pool creation. Calling createPool(tokenA, tokenB, fee) deploys a new Pool contract via CREATE2 (deterministic address). The factory also stores the mapping from (token0, token1, fee) → pool address.
Pool
Each pool is an independent contract holding reserves of two ERC-20 tokens at a specific fee tier. The pool implements:
swap()— executes a token swap against the pool's liquiditymint()/burn()— low-level functions to add/remove liquidity at specific tick rangesobserve()— returns oracle observations for TWAP calculations
Pools are immutable and permissionless — anyone can swap or provide liquidity.
Periphery Contracts
SwapRouter02
The recommended entry point for swaps. Wraps the pool's low-level swap() with safety features:
- Deadline enforcement
- Minimum output amount checks
- Multi-hop routing (swap through multiple pools in one transaction)
- Exact input and exact output modes
NonfungiblePositionManager
Manages liquidity positions as ERC-721 NFTs. Each NFT represents a unique position (pool + tick range + liquidity amount). Provides:
mint()— create a new positionincreaseLiquidity()— add more capital to an existing positiondecreaseLiquidity()— withdraw capitalcollect()— claim earned fees
QuoterV2
Simulates swaps off-chain without executing them. Returns the expected output amount, price impact, and gas estimate. Used by frontends to display quotes before the user confirms.
V3Migrator
Converts v2 LP positions into v3 positions in a single transaction.
How a Swap Flows
- User calls
SwapRouter02.exactInputSingle(params) - Router validates the deadline and resolves the pool address via the factory
- Router calls
Pool.swap()with the user's parameters - Pool iterates through active ticks, exchanging tokens according to the constant product formula within each tick range
- Pool transfers output tokens to the recipient
- Router verifies the output meets
amountOutMinimum, reverts if not
How Providing Liquidity Works
- User calls
NonfungiblePositionManager.mint(params)specifying token pair, fee tier, tick range, and amounts - PositionManager calls
Pool.mint()at the specified tick range - Pool records the liquidity and transfers tokens from the user
- PositionManager mints an ERC-721 NFT representing the position
- As swaps occur within the position's range, fees accrue to the position
- User calls
collect()to claim fees, ordecreaseLiquidity()+collect()to withdraw
Further Reading
- Quick Reference — function signatures and constants
- Deployment Addresses — contract addresses by network
- v3 Overview — introduction to CenturionDEX v3