AMM

什么是自动做市商 (AMM)

自动做市商(Automated Market Maker,AMM)是一种去中心化交易机制,它使用数学公式来定价资产,而不是传统的订单簿模式。JAMM DEX 采用恒定乘积公式(Constant Product Formula)作为其核心定价机制。

恒定乘积公式

基本原理

JAMM DEX 使用恒定乘积公式:x × y = k

其中:

  • x = 代币A的储备量

  • y = 代币B的储备量

  • k = 恒定值(乘积)

这个公式确保了流动性池中两种代币的乘积始终保持恒定(除了交易费用和流动性变化的影响)。

代码实现

JAMMPair.sol 合约的 swap 函数中,这个原理通过以下方式得到验证:

// balance{0,1}Adjusted are the balances after the swap, accounting for the fee
uint balance0Adjusted = (balance0 * 10000 - (amount0In * fee * 4) / 5);
uint balance1Adjusted = (balance1 * 10000 - (amount1In * fee * 4) / 5);

// check that the product of the new balances is not less than the product of the old reserves
require(
    balance0Adjusted * balance1Adjusted >= 
    uint(_reserve0) * uint(_reserve1) * (10000 ** 2),
    "JAMM: K"
);

价格发现机制

价格计算

在AMM系统中,代币的价格由储备量比例决定:

代币A的价格 = 储备量B / 储备量A

价格影响

当用户进行交易时,会改变储备量比例,从而影响价格。交易量越大,价格影响越明显。

JAMMLibrary.sol 中的价格计算函数:

function getAmountOut(
    uint amountIn,
    uint reserveIn,
    uint reserveOut,
    uint24 fee
) internal pure returns (uint amountOut) {
    require(amountIn > 0, "JAMMLibrary: INSUFFICIENT_INPUT_AMOUNT");
    require(reserveIn > 0 && reserveOut > 0, "JAMMLibrary: INSUFFICIENT_LIQUIDITY");
    
    // calculate output amount with fee
    uint amountInWithFee = amountIn * (10000 - fee);
    uint numerator = amountInWithFee * reserveOut;
    uint denominator = reserveIn * 10000 + amountInWithFee;
    amountOut = numerator / denominator;
}

滑点概念

什么是滑点

滑点是指预期价格与实际执行价格之间的差异。在AMM系统中,滑点主要由以下因素造成:

  1. 价格影响: 大额交易改变了储备量比例。

  2. 市场波动: 在交易确认期间,池中价格可能因其他交易而发生变化。

滑点保护

JAMM DEX 通过在 JAMMRouter 合约中检查用户可接受的最小输出来提供滑点保护:

// check that the received amount is not less than the minimum amount specified by the user
require(
    amounts[amounts.length - 1] >= amountOutMin,
    "JAMMRouter: INSUFFICIENT_OUTPUT_AMOUNT"
);

套利机制

套利的作用

套利者通过在不同市场之间进行交易来获利,同时帮助:

  1. 保持JAMM DEX的价格与外部市场一致。

  2. 为交易者提供更准确的价格。

  3. 增加交易量,从而为流动性提供者创造更多费用收入。

套利示例

如果JAMM DEX上的JU/USDC价格低于其他交易所:

  1. 套利者在JAMM DEX上买入JU。

  2. 在其他交易所卖出JU。

  3. 这个过程会推高JAMM DEX上的JU价格,直到价格与外部市场趋于一致。

流动性提供

流动性的重要性

流动性是AMM系统的核心:

  • 高流动性: 较小的价格影响,更好的交易体验。

  • 低流动性: 较大的价格影响,可能导致高滑点。

流动性提供者的角色

流动性提供者(LP)通过向池子中存入等值的代币对来提供流动性,并获得LP代币作为回报。JAMMPair.sol 中的 mint 函数处理此逻辑:

function mint(address to) external lock returns (uint liquidity) {
    (uint112 _reserve0, uint112 _reserve1, ) = getReserves();
    uint balance0 = IERC20(token0).balanceOf(address(this));
    uint balance1 = IERC20(token1).balanceOf(address(this));
    uint amount0 = balance0 - _reserve0;
    uint amount1 = balance1 - _reserve1;

    bool feeOn = _mintFee(_reserve0, _reserve1);
    uint _totalSupply = totalSupply;
    
    // calculate liquidity to mint
    if (_totalSupply == 0) {
        liquidity = Math.sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY;
        _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
    } else {
        liquidity = Math.min(
            (amount0 * _totalSupply) / _reserve0,
            (amount1 * _totalSupply) / _reserve1
        );
    }
    
    require(liquidity > 0, "JAMM: INSUFFICIENT_LIQUIDITY_MINTED");
    _mint(to, liquidity);

    _update(balance0, balance1, _reserve0, _reserve1);
    if (feeOn) kLast = uint(reserve0) * uint(reserve1);
    emit Mint(msg.sender, amount0, amount1);
}

无常损失

定义

无常损失(Impermanent Loss)是指当池内代币价格发生变化时,流动性提供者(LP)撤出资金时所持资产的价值低于简单持有原始代币(HODL)的价值。价格偏离越大,无常损失越大。

计算原理

当代币价格发生变化时:

  1. AMM会自动重新平衡储备量以维持 x*y=k 的关系。

  2. LP在池子中的份额保持不变,但其份额所代表的两种代币的数量会发生变化。

缓解措施

JAMM DEX通过以下方式帮助缓解无常损失:

  1. 交易费用收入: LP获得交易费用作为补偿,这可能抵消甚至超过无常损失。

  2. 多级费率: 为高波动性资产设置更高的费率,以提供更多费用收入。

价格预言机

累积价格机制

JAMM DEX实现了时间加权平均价格(TWAP)预言机。JAMMPair.sol 合约在每个区块的第一次交易中累积价格:

function _update(
    uint balance0,
    uint balance1,
    uint112 _reserve0,
    uint112 _reserve1
) private {
    // ...
    uint32 timeElapsed = blockTimestamp - blockTimestampLast;
    if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
        // accumulate prices
        price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
        price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
    }
    // ...
}

预言机的用途

  1. 外部合约集成: 其他DeFi协议可以查询历史平均价格,用于借贷、衍生品等。

  2. 套利检测: 帮助识别价格偏差机会。

  3. 风险管理: 评估资产的价格波动风险。

最小流动性锁定

永久锁定机制

为了防止流动性池被完全移除而导致无法计算价格,JAMM DEX在第一次添加流动性时会永久锁定最小数量的LP代币到零地址。

// From JAMMPair.sol
uint public constant MINIMUM_LIQUIDITY = 10**3;

// Inside the mint function
if (_totalSupply == 0) {
    liquidity = Math.sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY;
    _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first tokens
}

这确保了:

  1. 池子永远不会完全清空。

  2. 价格计算始终有效。

  3. 防止某些类型的恶意操纵。

Last updated