Liquidity Pools
What is a Liquidity Pool?
A liquidity pool is a core component of JAMM DEX, consisting of a smart contract that holds reserves of two tokens. Each liquidity pool is an instance of the JAMMPair contract, responsible for managing the trading and liquidity of a specific token pair.
Pool Creation
Creation via Factory
All liquidity pools are created through the JAMMFactory contract:
// from JAMMFactory.sol
function createPair(
address tokenA,
address tokenB,
uint24 fee
) external override returns (address pair) {
require(tokenA != tokenB, "JAMMFactory: IDENTICAL_ADDRESSES");
(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), "JAMMFactory: ZERO_ADDRESS");
require(
fee == FEE_0_5_PERCENT ||
fee == FEE_1_PERCENT ||
fee == FEE_2_PERCENT ||
fee == FEE_3_PERCENT,
"JAMMFactory: INVALID_FEE"
);
require(getPair[token0][token1][fee] == address(0), "JAMMFactory: PAIR_EXISTS");
// deploy the pair using CREATE2
bytes memory bytecode = type(JAMMPair).creationCode;
bytes32 salt = keccak256(abi.encodePacked(token0, token1, fee));
assembly {
pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
}
// initialize the pair
JAMMPair(pair).initialize(token0, token1, fee);
getPair[token0][token1][fee] = pair;
getPair[token1][token0][fee] = pair;
allPairs.push(pair);
emit PairCreated(token0, token1, fee, pair, allPairs.length);
}Deterministic Address Generation
JAMM DEX uses CREATE2 to generate deterministic pool addresses. This means that for the same token pair and fee, the pool address will always be the same. This calculation is performed in JAMMLibrary.sol:
Pool State
Reserve Management
Each pool maintains reserves of two tokens:
Reserve Updates
Reserves are updated after every trade or liquidity change:
Liquidity Tokens (LP Tokens)
The Role of LP Tokens
When a user provides liquidity to a pool, they receive LP tokens as a receipt:
LP tokens represent the user's share in the pool.
They can be redeemed at any time for the corresponding token pair.
LP tokens are themselves ERC-20 tokens and can be transferred.
Minting LP Tokens
Burning LP Tokens
Trade Execution
The swap Function
swap FunctionThe core function of the pool is to execute token swaps:
Security Mechanisms
Re-entrancy Guard
All critical functions are protected with the lock modifier to prevent re-entrancy attacks:
Minimum Liquidity Lock
To prevent the pool from being completely drained, a minimum amount of LP tokens is permanently locked on the first liquidity provision:
Overflow Protection
Reserves use the uint112 type, and updates are checked for overflow, leveraging the built-in security features of Solidity 0.8.x:
Utility Functions
skim Function
skim FunctionUsed to remove any excess tokens that were accidentally sent to the pool and not accounted for in the reserves:
sync Function
sync FunctionUsed to forcibly synchronize the reserves with the contract's actual token balances. This can be used to recover the pool state in certain edge cases:
Summary
Liquidity pools are the core components of JAMM DEX, and they:
Are created and managed centrally by the Factory contract.
Use deterministic address generation for easy calculation and lookup.
Implement full AMM functionality, including liquidity management and token swaps.
Have built-in security mechanisms and fee distribution logic.
Provide price oracle functionality.
Understanding how liquidity pools work is essential for effectively using JAMM DEX.