流动性池

什么是流动性池

流动性池是JAMM DEX的核心组件,它是一个包含两种代币储备的智能合约。每个流动性池都是一个 JAMMPair 合约实例,负责管理特定代币对的交易和流动性。

池子的创建

通过Factory创建

所有流动性池都通过 JAMMFactory 合约创建:

// 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);
}

确定性地址生成

JAMM DEX使用CREATE2来生成确定性的池子地址,这意味着给定相同的代币对和费率,池子地址总是相同的。这个计算在 JAMMLibrary.sol 中完成:

池子的状态

储备量管理

每个池子维护两种代币的储备量:

储备量更新

储备量在每次交易或流动性变更后都会更新:

流动性代币 (LP代币)

LP代币的作用

当用户向池子提供流动性时,会收到LP代币作为凭证:

  • LP代币代表用户在池子中的份额。

  • 可以随时用LP代币赎回相应的代币对。

  • LP代币本身也是ERC-20代币,可以转让。

LP代币的铸造

LP代币的销毁

交易执行

Swap函数

池子的核心功能是执行代币交换:

安全机制

重入保护

所有关键函数都使用 lock 修饰符保护,防止重入攻击:

最小流动性锁定

为防止池子被完全清空,首次添加流动性时会永久锁定最小数量的LP代币:

溢出保护

储备量使用 uint112 类型,并在更新时检查溢出,利用了 Solidity 0.8.x 的内置安全特性:

实用函数

Skim函数

用于移除意外转入池子且未被计入储备量的多余代币:

Sync函数

用于强制同步储备量与合约的实际代币余额,在某些异常情况下可以用来恢复池子状态:

Last updated