JAMM 系统架构

架构概述

JAMM DEX 采用分层、模块化架构,确保可扩展性、安全性和可维护性。系统由核心合约层、库层和接口层组成。

核心合约

JAMMFactory

职责:创建和管理交易对

  • 维护所有交易对的注册表

  • 使用 CREATE2 确定性部署交易对合约

  • 管理协议费用设置

  • 处理推荐系统的注册

关键函数

// 为 tokenA 和 tokenB 创建具有特定费用的新交易对
function createPair(address tokenA, address tokenB, uint24 fee) external returns (address pair);

// 获取现有交易对的地址
function getPair(address tokenA, address tokenB, uint24 fee) external view returns (address pair);

// 为消息发送者设置推荐人
function setReferrer(address _referrer) external;

JAMMPair

职责:实现特定的流动性池

  • 维护两种代币的储备

  • 执行代币交换逻辑

  • 管理流动性的添加和移除

  • 计算和分配交易费用

关键函数

// 铸造 LP 代币
function mint(address to) external returns (uint liquidity);

// 销毁 LP 代币
function burn(address to) external returns (uint amount0, uint amount1);

// 交换代币
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data, address _referrer) external;

// 返回代币储备和最后区块时间戳
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);

JAMMRouter

职责:提供用户友好的交易接口

  • 为交易提供高级函数

  • 处理多跳交换路径

  • 管理截止时间检查

  • 支持 ETH/WJU 的自动转换

关键函数

// 用精确数量的输入代币交换尽可能多的输出代币
function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, uint24[] calldata fees, address to, address referrer, uint deadline) external returns (uint[] memory amounts);

// 向交易对添加流动性
function addLiquidity(address tokenA, address tokenB, uint24 fee, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline) external returns (uint amountA, uint amountB, uint liquidity);

// 从交易对移除流动性
function removeLiquidity(address tokenA, address tokenB, uint24 fee, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline) external returns (uint amountA, uint amountB);

JAMMERC20

职责:LP 代币的标准实现

  • 实现 ERC-20 标准

  • 支持 EIP-2612 permit 功能

  • 管理 LP 代币的铸造和销毁

关键函数

// 通过签名批准代币使用
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

WJU

职责:包装 JU 代币的实现

  • 提供 JU 代币的包装和解包装

  • 完全兼容 ERC-20 标准

  • 支持直接接收 ETH

关键函数

// 将 JU 包装为 WJU
function deposit() public payable;

// 将 WJU 解包装回 JU
function withdraw(uint amount) public;

库合约

JAMMLibrary

提供核心数学计算和工具函数:

  • sortTokens():排序代币地址

  • pairFor():计算交易对地址

  • getReserves():获取储备量

  • getAmountOut(), getAmountIn():计算交换数量

  • getAmountsOut(), getAmountsIn():计算多跳交换数量

Math

提供安全的数学运算:

  • sqrt():平方根计算(使用巴比伦方法)

  • min():找到两个数的最小值

  • 使用 Solidity >=0.8.0 的内置溢出/下溢保护

TransferHelper

提供安全的代币转账函数:

  • safeTransfer():安全代币转账

  • safeTransferFrom():从另一个地址安全转账代币

  • safeTransferETH():安全 ETH 转账

  • safeApprove():安全代币授权

UQ112x112

提供定点数算术支持:

  • 用于价格累积

  • 启用高精度数学运算

数据流架构

交易流程

用户 → JAMMRouter → JAMMPair → 代币合约
  ↓        ↓         ↓
检查参数 → 计算路径 → 执行交换 → 更新储备

流动性管理流程

用户 → JAMMRouter → JAMMPair → JAMMERC20
  ↓        ↓         ↓         ↓
添加流动性 → 转移代币 → 铸造 LP → 发行 LP 代币

安全架构

重入保护

所有关键函数都受到重入锁保护:

modifier lock() {
    require(unlocked == 1, "JAMM: LOCKED");
    unlocked = 0;
    _;
    unlocked = 1;
}

数学安全

  • 使用 Solidity ^0.8.21 的内置溢出和下溢保护

  • Math 库提供安全的 sqrt 函数

  • JAMMLibrary 包含零储备和数量的检查

访问控制

  • JAMMFactory 中的关键函数只能由 feeToSetter 调用

  • JAMMPair 中的 initialize 函数只能由工厂调用

  • 每个用户只能设置一次推荐人

费用架构

费用层级

uint24 public constant FEE_0_5_PERCENT = 50;   // 0.5%
uint24 public constant FEE_1_PERCENT = 100;    // 1%
uint24 public constant FEE_2_PERCENT = 200;    // 2%
uint24 public constant FEE_3_PERCENT = 300;    // 3%

费用分配

  • 交易费用:交换费用的一部分(fee/50000fee/100000)发送到指定的 feeTo 地址。如果推荐人处于活跃状态,费用在协议和推荐人之间分配

  • 协议费用:流动性提供者费用的一部分可以作为新的 LP 代币铸造并发送到 mintTo 地址,基于 k 值的增长计算

地址生成

CREATE2 确定性部署

使用 CREATE2 生成交易对地址,确保可预测性:

// salt 从排序的代币地址和费用计算
bytes32 salt = keccak256(abi.encodePacked(token0, token1, fee));
// 使用 create2 操作码部署交易对
pair := create2(0, add(bytecode, 32), mload(bytecode), salt)

初始化代码哈希

// JAMMPair 创建代码的哈希,用于 pairFor 计算
bytes32 public constant INIT_CODE_PAIR_HASH = keccak256(type(JAMMPair).creationCode);

当前值:0x2e599419feff8382bdfc47abf847537b06e96b0525db3802b2a9fb0bfe068ed8

事件系统

核心事件

  • PairCreated(address indexed token0, address indexed token1, uint24 fee, address pair, uint)

  • Swap(address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to)

  • Mint(address indexed sender, uint amount0, uint amount1)

  • Burn(address indexed sender, uint amount0, uint amount1, address indexed to)

  • Sync(uint112 reserve0, uint112 reserve1)

  • Fee(address indexed sender, address indexed referrer, address token, uint amount)

  • Referrer(address indexed sender, address indexed referrer)

这些事件为前端应用程序和分析工具提供了完整的链上数据轨迹。

Last updated