Skip to main content

Factory Contract

The Factory contract is the central registry and management system for all trading pairs in the Oyl AMM protocol. It handles pool creation, routing, and protocol-wide operations.

Contract Overview

The Factory contract serves as:

  • Pool Registry: Maintains a list of all trading pairs
  • Pool Creator: Deploys new pool contracts
  • Router: Handles multi-hop swaps and liquidity operations
  • Fee Manager: Collects protocol fees

Core Functions

Pool Management

InitFactory

Initializes the factory with required parameters:

#[opcode(0)]
InitFactory {
pool_factory_id: u128,
beacon_id: AlkaneId,
}

CreateNewPool

Creates a new trading pair:

#[opcode(1)]
CreateNewPool {
token_a: AlkaneId,
token_b: AlkaneId,
amount_a: u128,
amount_b: u128,
}

This function:

  • Deploys a new pool contract
  • Registers the pool in the factory
  • Sets up initial pool parameters
  • Provides initial liquidity

FindExistingPoolId

Finds the pool ID for a token pair:

#[opcode(2)]
FindExistingPoolId {
alkane_a: AlkaneId, // First token
alkane_b: AlkaneId, // Second token
}

Returns the pool ID if it exists, or creates a new pool if it doesn't.

Pool Information

GetAllPools

Returns a list of all pools:

#[opcode(3)]
#[returns(Vec<u8>)]
GetAllPools

Example script to decode the output

  function parseHexData(hex) {
if (hex.startsWith("0x")) {
hex = hex.slice(2);
}

const buf = Buffer.from(hex, "hex");

// 获取 pool 数量(前 16 字节,小端,取最低字节)
const poolCount = buf.readUIntLE(0, 1);

const pools = [];
let offset = 16;

for (let i = 0; i < poolCount; i++) {
// 读取 block(16 字节,小端)
const blockLE = buf.slice(offset, offset + 16);
const blockLEBigInt = bufferToBigIntLE(blockLE);

offset += 16;

// 读取 tx(16 字节,小端)
const txLE = buf.slice(offset, offset + 16);
const txBigInt = bufferToBigIntLE(txLE);

offset += 16;

pools.push({
block: blockLEBigInt.toString(),
tx: txBigInt.toString(),
});
}

return {
poolCount,
pools,
};
}

function bufferToBigIntLE(buffer) {
let result = 0n;
for (let i = buffer.length - 1; i >= 0; i--) {
result = (result << 8n) + BigInt(buffer[i]);
}
return result;
}

GetNumPools

Returns the total number of pools:

#[opcode(4)]
#[returns(Vec<u8>)]
GetNumPools

Configuration

SetPoolFactoryId

Updates the pool factory ID:

#[opcode(7)]
SetPoolFactoryId {
pool_factory_id: u128
}

This function is restricted to authorized users only.

Liquidity Operations

AddLiquidity

Adds liquidity to a trading pair:

#[opcode(11)]
AddLiquidity {
token_a: AlkaneId, // First token
token_b: AlkaneId, // Second token
amount_a_desired: u128, // Desired amount of token A
amount_b_desired: u128, // Desired amount of token B
amount_a_min: u128, // Minimum amount of token A
amount_b_min: u128, // Minimum amount of token B
deadline: u128, // Transaction deadline in block height
}

The function:

  1. Finds or creates the pool for the token pair
  2. Calculates optimal amounts based on current reserves
  3. Transfers tokens to the pool
  4. Mints LP tokens to the user

Burn (Remove Liquidity)

Removes liquidity from a trading pair:

#[opcode(12)]
Burn {
token_a: AlkaneId, // First token
token_b: AlkaneId, // Second token
liquidity: u128, // Amount of LP tokens to burn
amount_a_min: u128, // Minimum amount of token A to receive
amount_b_min: u128, // Minimum amount of token B to receive
deadline: u128, // Transaction deadline in block height
}

Trading Operations

SwapExactTokensForTokens

Swaps an exact amount of input tokens for output tokens:

#[opcode(13)]
SwapExactTokensForTokens {
path: Vec<AlkaneId>, // Token path for the swap
amount_in: u128, // The amount of input tokens to send
amount_out_min: u128, // Minimum output amount
deadline: u128, // Transaction deadline in block height
}

SwapTokensForExactTokens

Swaps tokens to get an exact amount of output tokens:

#[opcode(14)]
SwapTokensForExactTokens {
path: Vec<AlkaneId>, // Token path for the swap
amount_out: u128, // Exact output amount desired
amount_in_max: u128, // Maximum input amount
deadline: u128, // Transaction deadline in block height
}

SwapExactTokensForTokensImplicit

Swaps an exact amount of input tokens for output tokens, where the input amount is implicitly determined by the value of the alkanes sent with the call.

#[opcode(29)]
SwapExactTokensForTokensImplicit {
path: Vec<AlkaneId>,
amount_out_min: u128,
deadline: u128, // Transaction deadline in block height
}

Fee Management

CollectFees

Collects protocol fees from a specific pool:

#[opcode(10)]
CollectFees {
pool_id: AlkaneId
}

This function:

  • Calculates accumulated protocol fees
  • Transfers fees to the protocol treasury
  • Updates pool fee tracking

Access Control

Authentication

The Factory contract implements authentication mechanisms:

  • Critical functions require proper authorization
  • Uses the Alkanes authentication system
  • Protects against unauthorized access

Permissions

Different functions have different permission levels:

  • Public: Pool queries, swaps
  • User: Liquidity operations
  • Admin: Configuration changes, fee collection

The Factory contract is the main entry point for most Oyl AMM operations, providing a unified interface for pool management, liquidity operations, and trading.