2025-10-21-Uniswap-V2-工厂合约

2025-10-21-Uniswap-V2-工厂合约

十月 20, 2025

工厂合约代码及其分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
pragma solidity =0.5.16;

import './interfaces/IUniswapV2Factory.sol';
import './UniswapV2Pair.sol';

contract UniswapV2Factory is IUniswapV2Factory {
address public feeTo;
address public feeToSetter;

mapping(address => mapping(address => address)) public getPair;
address[] public allPairs;

event PairCreated(address indexed token0, address indexed token1, address pair, uint);

constructor(address _feeToSetter) public {
feeToSetter = _feeToSetter;
}

function allPairsLength() external view returns (uint) {
return allPairs.length;
}

function createPair(address tokenA, address tokenB) external returns (address pair) {
require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');
(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS');
require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient
bytes memory bytecode = type(UniswapV2Pair).creationCode;
bytes32 salt = keccak256(abi.encodePacked(token0, token1));
assembly {
pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
}
IUniswapV2Pair(pair).initialize(token0, token1);
getPair[token0][token1] = pair;
getPair[token1][token0] = pair; // populate mapping in the reverse direction
allPairs.push(pair);
emit PairCreated(token0, token1, pair, allPairs.length);
}

function setFeeTo(address _feeTo) external {
require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
feeTo = _feeTo;
}

function setFeeToSetter(address _feeToSetter) external {
require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
feeToSetter = _feeToSetter;
}
}

1. 合约基础结构

状态变量

1
2
3
4
5
6
7
address public feeTo;          // 协议费用接收地址

address public feeToSetter; // 有权设置 feeTo 的地址

mapping(address => mapping(address => address)) public getPair; // 代币对到交易对地址的映射

address[] public allPairs; // 所有已创建交易对的数组

2. 核心功能:createPair

输入验证

1
2
3
4
5
6
7
require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');

(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);

require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS');

require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS');

关键设计

  • 代币地址标准化排序(token0 < token1)
  • 防止重复创建相同交易对
  • 零地址检查

CREATE2 确定性部署

1
2
3
4
5
6
7
8
9
bytes memory bytecode = type(UniswapV2Pair).creationCode;

bytes32 salt = keccak256(abi.encodePacked(token0, token1));

assembly {

pair := create2(0, add(bytecode, 32), mload(bytecode), salt)

}

CREATE2 的优势

  • 相同代币对总是部署到相同地址
  • 便于前端预测交易对地址
  • 节省 Gas(避免重复部署)

初始化交易对

1
IUniswapV2Pair(pair).initialize(token0, token1);

更新状态

1
2
3
4
5
getPair[token0][token1] = pair;

getPair[token1][token0] = pair; // 反向映射

allPairs.push(pair);

3. 费用管理机制

设置协议费用接收地址

1
2
3
4
5
6
7
function setFeeTo(address _feeTo) external {

require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');

feeTo = _feeTo;

}

转移权限管理

1
2
3
4
5
6
7
function setFeeToSetter(address _feeToSetter) external {

require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');

feeToSetter = _feeToSetter;

}

权限模型

  • 只有 feeToSetter 可以设置 feeTo
  • feeToSetter 可以将权限转移给其他地址

4. 查询功能

获取交易对数量

1
2
3
4
5
function allPairsLength() external view returns (uint) {

return allPairs.length;

}

通过代币地址查询交易对

1
2
3
// 通过 public mapping 自动生成查询函数

getPair[token0][token1] // 返回交易对地址

5. 核心设计特点

确定性地址计算

1
2
3
4
5
// 交易对地址计算公式:

address = create2(0, bytecode, salt)

salt = keccak256(abi.encodePacked(token0, token1))

双向映射支持

1
2
3
getPair[token0][token1] = pair;

getPair[token1][token0] = pair; // 支持反向查询

最小权限原则

  • 只有工厂合约可以创建交易对
  • 只有 feeToSetter 可以修改费用设置

6. 与交易对合约的交互

当交易对合约需要查询费用设置时:

1
2
3
// 在 UniswapV2Pair 的 _mintFee 函数中

address feeTo = IUniswapV2Factory(factory).feeTo();

7. 安全性考虑

重放攻击防护:通过映射检查确保每个交易对只创建一次

1
require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS');

权限控制:严格的权限验证防止未授权操作

输入验证:全面的参数检查确保合约状态一致性

这个工厂合约是 Uniswap V2 生态系统的核心枢纽,负责管理所有交易对的创建和协议级别的费用设置。其简洁而强大的设计为整个 DEX 提供了可靠的基础设施。