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 protocolpools
: Mutable reference to the pools registrytick_spacing
: The spacing between usable ticksinitialize_price
: Initial sqrt price of the poolurl
: Optional URL for pool metadata (defaults to placeholder if empty)tick_lower/tick_upper
: Range for the initial liquidity positioncoin_a/coin_b
: Initial tokens to provide as liquiditylock_until
: Timestamp until which the position is lockedis_fixed_a
: Whether to fix the amount of coin A or coin Bclock
: Clock object for time-based operationsctx
: Transaction context
Returns:
Position
: The created liquidity positionRemaining 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:
Get string representations of both coin types
Ensure CoinTypeA is lexicographically greater than CoinTypeB
Concatenate type names and tick spacing
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
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