Factory Module

The Factory module is responsible for creating and managing pools. It maintains a registry of all pools and ensures proper initialization.

Overview

The Ferra CLMM (Concentrated Liquidity Market Maker) Factory module is responsible for creating and managing liquidity pools in the Ferra protocol. It implements a singleton pattern to maintain a registry of all pools and provides functionality for pool creation, management, and querying.

Key Features

  • Singleton Pool Registry: Maintains a centralized registry of all created pools

  • Deterministic Pool Keys: Generates unique pool identifiers based on coin types and tick spacing

  • Access Control: Supports whitelisting and role-based pool creation

  • Initial Liquidity: Automatically creates initial liquidity positions when creating pools

  • Event Emission: Emits events for factory initialization and pool creation

Core Structures

Pools

struct Pools has key, store {
    id: UID,
    list: LinkedTable<ID, PoolSimpleInfo>,
    index: u64,
}

The Pools struct is a singleton object that manages all pools in the system:

  • id: Unique identifier for the pools registry

  • list: Linked table containing pool information indexed by pool keys

  • index: Sequential counter for pool creation order

PoolSimpleInfo

struct PoolSimpleInfo has copy, drop, store {
    pool_id: ID,
    pool_key: ID,
    coin_type_a: TypeName,
    coin_type_b: TypeName,
    tick_spacing: u32,
}

Contains essential information about each pool:

  • pool_id: Unique identifier of the actual pool object

  • pool_key: Deterministic key generated from coin types and tick spacing

  • coin_type_a/coin_type_b: The two token types in the pool (ordered lexicographically)

  • tick_spacing: The spacing between usable ticks in the pool

Main Functions

create_pool

public fun create_pool<CoinTypeA, CoinTypeB>(
    global_config: &GlobalConfig,
    pools: &mut Pools,
    tick_spacing: u32,
    initialize_price: u128,
    url: String,
    tick_lower: u32,
    tick_upper: u32,
    coin_a: Coin<CoinTypeA>,
    coin_b: Coin<CoinTypeB>,
    lock_until: u64,
    is_fixed_a: bool,
    clock: &Clock,
    ctx: &mut TxContext,
) -> (Position, Coin<CoinTypeA>, Coin<CoinTypeB>)

Creates a new liquidity pool with initial liquidity provision.

Parameters:

  • global_config: Global configuration object for the protocol

  • pools: Mutable reference to the pools registry

  • tick_spacing: The spacing between usable ticks

  • initialize_price: Initial sqrt price of the pool

  • url: Optional URL for pool metadata (defaults to placeholder if empty)

  • tick_lower/tick_upper: Range for the initial liquidity position

  • coin_a/coin_b: Initial tokens to provide as liquidity

  • lock_until: Timestamp until which the position is locked

  • is_fixed_a: Whether to fix the amount of coin A or coin B

  • clock: Clock object for time-based operations

  • ctx: Transaction context

Returns:

  • Position: The created liquidity position

  • Remaining coins after liquidity provision

Access Control:

  • Checks if pair creation is globally allowed

  • Validates creator permissions if pair creation is restricted

  • Requires at least one coin type to be whitelisted

new_pool_key

public fun new_pool_key<CoinTypeA, CoinTypeB>(tick_spacing: u32): ID

Generates a deterministic pool key based on coin types and tick spacing.

Algorithm:

  1. Get string representations of both coin types

  2. Ensure CoinTypeA is lexicographically greater than CoinTypeB

  3. Concatenate type names and tick spacing

  4. Generate ID using Blake2b256 hash

Important: The function enforces that CoinTypeA must be the "bigger" type in string order, ensuring consistent pool keys regardless of the order types are provided.

fetch_pools

public fun fetch_pools(pools: &Pools, start: vector<ID>, limit: u64): vector<PoolSimpleInfo>

Retrieves a paginated list of pools from the registry.

Parameters:

  • start: Optional starting point for pagination (empty vector starts from beginning)

  • limit: Maximum number of pools to return

Returns: Vector of PoolSimpleInfo objects

Events

InitFactoryEvent

struct InitFactoryEvent has copy, drop {
    pools_id: ID,
}

Emitted when the factory is initialized, providing the ID of the pools registry.

CreatePoolEvent

struct CreatePoolEvent has copy, drop {
    pool_id: ID,
    coin_type_a: String,
    coin_type_b: String,
    tick_spacing: u32,
    initialize_price: u128,
}

Emitted when a new pool is created, containing all essential pool information.

Error Codes

Code
Description

1

Pool already exists or pair creation not allowed

2

Initialize price out of valid range

3

Coin types are identical

4

Insufficient coin B when fixing coin A amount

5

Insufficient coin A when fixing coin B amount

6

Coin type order violation (CoinTypeA must be lexicographically greater)

16

Zero liquidity or required amounts

Last updated