1. 初始化永续合约交易对
任务目标
在去中心化永续合约协议中,初始化一个交易对(Market),为其配置基础资产、报价资产、初始保证金率、维持保证金率等核心参数,并确保该交易对可以被查询与使用。
环境与依赖
本案例基于 Foundry 开发框架,使用 Solidity ^0.8.20。需要安装 Foundry(forge)并准备一个本地或测试网 RPC 用于部署验证。无需额外第三方库。
核心实现
以下合约实现了一个最小化的永续合约交易对初始化逻辑。合约部署时即完成交易对创建,并存储所有必要参数,提供查询接口以验证初始化结果。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/// @title 永续合约交易对初始化
/// @notice 部署即创建一个永续交易对,并记录基础资产、报价资产及保证金率参数
contract PerpMarket {
// ---- 交易对参数 ----
address public baseAsset; // 基础资产(如 WBTC)
address public quoteAsset; // 报价资产(如 USDC)
uint256 public initialMarginRate; // 初始保证金率,1e18 = 100%
uint256 public maintenanceMarginRate; // 维持保证金率,1e18 = 100%
bool public isActive; // 交易对是否启用
// ---- 事件 ----
event MarketInitialized(
address indexed baseAsset,
address indexed quoteAsset,
uint256 initialMarginRate,
uint256 maintenanceMarginRate
);
/// @notice 构造函数:初始化交易对参数
/// @param _base 基础资产地址
/// @param _quote 报价资产地址
/// @param _initialMarginRate 初始保证金率(1e18 = 100%,如 0.1e18 = 10%)
/// @param _maintenanceMarginRate 维持保证金率(1e18 = 100%,如 0.05e18 = 5%)
constructor(
address _base,
address _quote,
uint256 _initialMarginRate,
uint256 _maintenanceMarginRate
) {
require(_base != address(0), "invalid base asset");
require(_quote != address(0), "invalid quote asset");
require(_initialMarginRate > _maintenanceMarginRate, "initial must be > maintenance");
require(_maintenanceMarginRate > 0, "maintenance must be > 0");
baseAsset = _base;
quoteAsset = _quote;
initialMarginRate = _initialMarginRate;
maintenanceMarginRate = _maintenanceMarginRate;
isActive = true;
emit MarketInitialized(_base, _quote, _initialMarginRate, _maintenanceMarginRate);
}
/// @notice 查询交易对是否已初始化(isActive 即表示已初始化)
function isInitialized() external view returns (bool) {
return isActive;
}
}
部署与验证
使用 Foundry 创建一个部署脚本,将合约部署到本地测试链并验证参数是否正确写入。
// scripts/Deploy.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script} from "forge-std/Script.sol";
import {PerpMarket} from "../src/PerpMarket.sol";
contract Deploy is Script {
function run() external returns (PerpMarket market) {
// 使用虚拟代币地址作为示例(实际部署时应为真实代币地址)
address wbtc = address(0x1000);
address usdc = address(0x2000);
vm.startBroadcast();
market = new PerpMarket(wbtc, usdc, 0.1e18, 0.05e18);
vm.stopBroadcast();
}
}
在项目根目录执行以下命令完成部署与验证:
# 初始化 Foundry 项目(若尚未初始化)
forge init perp-market
cd perp-market
# 将上述 PerpMarket.sol 放入 src/,Deploy.s.sol 放入 script/
# 编译
forge build
# 在本地测试链上部署
forge script script/Deploy.s.sol --rpc-url http://127.0.0.1:8545 --broadcast
# 使用 cast 调用查询接口验证参数(替换为实际部署地址)
cast call <DEPLOYED_ADDRESS> "baseAsset()" --rpc-url http://127.0.0.1:8545
cast call <DEPLOYED_ADDRESS> "initialMarginRate()" --rpc-url http://127.0.0.1:8545
cast call <DEPLOYED_ADDRESS> "isActive()" --rpc-url http://127.0.0.1:8545
验证方法与通过条件
- 编译通过:
forge build无报错。 - 部署成功:
forge script返回合约地址,无 revert。 - 参数正确:调用
baseAsset()返回0x...1000,quoteAsset()返回0x...2000,initialMarginRate()返回100000000000000000(即 0.1e18),maintenanceMarginRate()返回50000000000000000(即 0.05e18),isActive()返回true。 - 事件日志:部署交易 receipt 中包含
MarketInitialized事件,参数与构造输入一致。
常见问题
- 保证金率精度:所有比率均以 1e18 为精度,10% 应传
0.1e18而非10。 - 构造 revert:若初始保证金率 ≤ 维持保证金率,或任一资产地址为 0,构造函数会 revert,部署失败。
- 本地测试链:若未启动本地节点,可先执行
anvil启动默认 8545 端口测试链。