Architecture

Rapiddex v3 is a binary smart contract system split into two layers (Core and Periphery), each with distinct responsibilities and security boundaries.

Understanding this separation is important before integrating with the protocol. Core contracts define the invariants and hold funds. Periphery contracts add convenience and safety for callers, but they hold no special privileges over Core.

Core vs Periphery

The protocol is deliberately divided into two layers:

  • Core: minimal, gas-optimised contracts that enforce the AMM invariants and store all funds. They are designed to be as simple as possible: correctness is prioritised over code clarity.
  • Periphery: higher-level contracts that wrap Core to provide a safer, more ergonomic interface for end-users and integrators. Periphery contracts never hold protocol funds on a permanent basis.

Because periphery contracts have no elevated access to core contracts, you can always interact with Core directly if needed: the periphery is purely optional convenience.

Core Contracts

Factory

The RapiddexV3Factory is the registry for all pools. It deploys new pool contracts and tracks their addresses. Key points:

  • Multiple pools can exist for the same token pair: one per fee tier (0.05%, 0.30%, 1.00%).
  • Pool addresses are deterministic: given token0, token1, and fee, the factory's getPool() function always returns the same address.
  • Anyone can create a pool for a new token pair by calling createPool() on the factory.
solidity// Look up an existing pool address
address pool = IRapiddexV3Factory(factory).getPool(token0, token1, fee);

Pools

Each RapiddexV3Pool is an independent AMM contract for a specific token pair and fee tier. Pools are the heart of the protocol, where they:

  • Hold all liquidity funds (token0 and token1 balances).
  • Execute swaps and update the concentrated liquidity curve.
  • Accumulate fee growth per unit of liquidity.

Pool state is primarily packed into slot0 to minimise storage reads: it holds the current sqrtPriceX96, the current tick, and protocol fee settings.

Pool Deployer

The RapiddexV3PoolDeployer is a small helper the factory delegates to when creating new pools. It exists to sidestep Solidity constructor argument limitations and enable the deterministic CREATE2 deployment scheme the factory relies on for address prediction.

Periphery Contracts

SwapRouter

The SwapRouter is the standard entry point for executing token swaps. It supports single-hop swaps routed through one pool (using exactInputSingle or exactOutputSingle).

The router pulls tokens from the caller, sends them to the pool, and enforces slippage limits before returning output tokens. It does not hold funds between calls.

NonfungiblePositionManager

Liquidity positions in Rapiddex v3 are represented as ERC-721 NFTs. The NonfungiblePositionManager wraps the core pool's low-level mint/burn/collect functions and issues an NFT to track each position. Through this contract you can:

  • Mint new positions (mint())
  • Increase liquidity in an existing position (increaseLiquidity())
  • Decrease liquidity and withdraw tokens (decreaseLiquidity())
  • Collect accrued fees (collect())
  • Burn a fully-withdrawn position NFT (burn())

Periphery Libraries

The periphery ships a set of helper libraries used internally and available for integrators:

  • PoolAddress: computes the deterministic pool address from factory, token pair, and fee tier without an on-chain call.
  • CallbackValidation: verifies that callbacks (swap, mint) originate from a legitimate pool, preventing spoofing attacks.
  • TransferHelper: safe ERC-20 transfer wrappers that revert on non-standard return values.
  • LowGasSafeMath: overflow-checked arithmetic optimised for low gas usage.
  • TickMath: converts between tick indices and sqrtPriceX96 values.

Design Philosophy

The strict Core/Periphery boundary means:

  • Core contracts are immutable and cannot be upgraded: their correctness must be guaranteed at deployment.
  • Periphery contracts can be upgraded or replaced without touching Core, allowing the user-facing interface to evolve safely.
  • External integrators should always interact via periphery contracts unless they have a specific reason to call Core directly (e.g. custom swap callback handling).
  • Core contracts use a callback pattern: rather than pulling tokens directly, they call back into the caller's contract at key points (e.g. uniswapV3SwapCallback or uniswapV3MintCallback). This gives integrators full control while Core enforces the final balance invariants.
Callback Validation Always use CallbackValidation.verifyCallback() in any contract that implements a Core callback. Without it, an attacker can spoof a callback from an arbitrary address and drain your contract.