Skip to content

4.12 主网上线

一句话总结:主网上线不是终点,而是起点——多签部署+Timelock+监控=安全上线。

📊 学习进度

  • 状态:⬜ 未开始
  • 预计时长:3-4 小时
  • 已完成:0/3 个模块
  • 在整体流程中的位置:预测市场实战·第 9 阶段

📍 本章定位

  • 服务方案:方案 3(核心 90%)
  • 学习方式:🔥 推荐
  • 在流程中的作用:部署主网、上线运营
  • 核心知识点:合约部署、多签、Timelock、运营策略
  • 预计时长:3-4 小时
  • 完成后能做什么:能安全完成主网上线

人机分工

环节谁做重要度说明
部署策略🧑 人⭐⭐⭐⭐⭐决定部署方案
多签设置🧑 人⭐⭐⭐⭐⭐安全核心
部署执行🤖 AI⭐⭐⭐AI 执行脚本
上线监控🤖 AI⭐⭐⭐⭐AI 实时监控

1. 上线前准备

1.1 上线检查清单

1.2 详细检查清单

序号类别检查项状态负责人
1代码合约审计报告安全团队
2代码测试覆盖率 > 90%开发团队
3代码Slither 扫描无高危安全团队
4代码代码冻结,无新提交开发团队
5基础设施RPC 节点稳定运行 7 天运维
6基础设施数据库备份策略运维
7基础设施监控告警配置运维
8基础设施CDN 和域名配置运维
9安全多签钱包创建安全团队
10安全Timelock 配置安全团队
11安全紧急暂停测试安全团队
12安全密钥安全存储安全团队
13运营初始做市资金到位运营
14运营首批事件准备运营
15运营社区公告文案运营
16运营客服响应流程运营

2. 上线流程

2.1 上线步骤

2.2 部署清单

序号任务工具验证时间
1部署 Factory 合约Hardhat合约地址确认10 分钟
2部署预言机合约Hardhat节点连接测试10 分钟
3部署做市合约Hardhat流动性测试10 分钟
4设置多签钱包Safe签名者确认30 分钟
5设置 TimelockTimelock延迟时间确认20 分钟
6前端配置Next.js功能测试30 分钟
7监控配置Grafana告警测试20 分钟
8初始做市脚本流动性确认30 分钟
9功能验证手动全流程测试60 分钟

总时间:约 4 小时


3. 安全措施

3.1 多签钱包

多签配置

typescript
// Gnosis Safe 多签配置
const safeConfig = {
  owners: [
    '0xFounder...',      // 创始人
    '0xTechLead...',     // 技术负责人
    '0xSecurityLead...', // 安全负责人
    '0xCommunity...',    // 社区代表
    '0xBackup...'        // 备用
  ],
  threshold: 3,  // 需要 3 人签名
  chainId: 8453  // Base
};

3.2 Timelock 配置

solidity
// Timelock 合约配置
contract TimelockConfig {
    uint256 public constant MIN_DELAY = 24 hours;   // 最小延迟
    uint256 public constant MAX_DELAY = 7 days;     // 最大延迟
    uint256 public constant DEFAULT_DELAY = 48 hours; // 默认延迟
    
    // 升级流程:
    // 1. 提交升级提案(需要多签)
    // 2. 等待延迟期(48 小时)
    // 3. 执行升级(需要多签)
    
    // 紧急情况:
    // 1. 紧急暂停(不需要延迟)
    // 2. 紧急升级(需要所有签名者)
}

3.3 紧急暂停机制

3.4 安全措施清单

措施说明必要性实现方式
多签钱包多人签名才能执行⭐⭐⭐⭐⭐Gnosis Safe
Timelock合约升级延迟执行⭐⭐⭐⭐⭐OpenZeppelin Timelock
升级代理可升级合约⭐⭐⭐⭐TransparentProxy
紧急暂停紧急情况下暂停合约⭐⭐⭐⭐Pausable
限额机制单笔交易限额⭐⭐⭐自定义
黑名单恶意地址限制⭐⭐AccessControl

4. 部署脚本

4.1 主网部署脚本

typescript
// scripts/deploy-mainnet.ts
import { ethers } from "hardhat";
import { LedgerSigner } from "@anders-t/ethers-ledger";

async function main() {
  // 使用硬件钱包签名(更安全)
  const signer = new LedgerSigner(ethers.provider);
  
  console.log("Deploying with account:", await signer.getAddress());
  console.log("Balance:", ethers.formatEther(await ethers.provider.getBalance(await signer.getAddress())));
  
  // 1. 部署 EventPod 实现
  console.log("\n1. Deploying EventPod implementation...");
  const EventPod = await ethers.getContractFactory("EventPod", signer);
  const eventPod = await EventPod.deploy();
  await eventPod.waitForDeployment();
  console.log("EventPod:", await eventPod.getAddress());
  
  // 2. 部署 EventFactory
  console.log("\n2. Deploying EventFactory...");
  const EventFactory = await ethers.getContractFactory("EventFactory", signer);
  const eventFactory = await EventFactory.deploy(await eventPod.getAddress());
  await eventFactory.waitForDeployment();
  console.log("EventFactory:", await eventFactory.getAddress());
  
  // 3. 部署 OrderBook 实现
  console.log("\n3. Deploying OrderBook implementation...");
  const OrderBook = await ethers.getContractFactory("OrderBook", signer);
  const orderBook = await OrderBook.deploy();
  await orderBook.waitForDeployment();
  console.log("OrderBook:", await orderBook.getAddress());
  
  // 4. 部署 OrderBookFactory
  console.log("\n4. Deploying OrderBookFactory...");
  const OrderBookFactory = await ethers.getContractFactory("OrderBookFactory", signer);
  const orderBookFactory = await OrderBookFactory.deploy(await orderBook.getAddress());
  await orderBookFactory.waitForDeployment();
  console.log("OrderBookFactory:", await orderBookFactory.getAddress());
  
  // 5. 部署 OracleManager
  console.log("\n5. Deploying OracleManager...");
  const OracleManager = await ethers.getContractFactory("OracleManager", signer);
  const oracleManager = await OracleManager.deploy();
  await oracleManager.waitForDeployment();
  console.log("OracleManager:", await oracleManager.getAddress());
  
  // 6. 部署 Timelock
  console.log("\n6. Deploying Timelock...");
  const Timelock = await ethers.getContractFactory("TimelockController", signer);
  const timelock = await Timelock.deploy(
    48 * 60 * 60, // 48 小时延迟
    [await signer.getAddress()], // 提案者
    [await signer.getAddress()], // 执行者
    ethers.ZeroAddress // 管理员
  );
  await timelock.waitForDeployment();
  console.log("Timelock:", await timelock.getAddress());
  
  // 7. 转移所有权到 Timelock
  console.log("\n7. Transferring ownership to Timelock...");
  await eventFactory.transferOwnership(await timelock.getAddress());
  await orderBookFactory.transferOwnership(await timelock.getAddress());
  await oracleManager.transferOwnership(await timelock.getAddress());
  console.log("Ownership transferred");
  
  // 8. 保存部署信息
  const deployment = {
    network: "base",
    chainId: "8453",
    deployer: await signer.getAddress(),
    timestamp: new Date().toISOString(),
    contracts: {
      eventPod: await eventPod.getAddress(),
      eventFactory: await eventFactory.getAddress(),
      orderBook: await orderBook.getAddress(),
      orderBookFactory: await orderBookFactory.getAddress(),
      oracleManager: await oracleManager.getAddress(),
      timelock: await timelock.getAddress()
    }
  };
  
  const fs = require('fs');
  fs.writeFileSync(
    'deployments/base-mainnet.json',
    JSON.stringify(deployment, null, 2)
  );
  
  console.log("\n✅ Deployment complete!");
  console.log("Deployment saved to: deployments/base-mainnet.json");
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

4.2 部署验证脚本

typescript
// scripts/verify-deployment.ts
import { ethers } from "hardhat";
import deployment from '../deployments/base-mainnet.json';

async function main() {
  console.log("Verifying deployment...\n");
  
  // 1. 验证合约代码
  console.log("1. Verifying contract code...");
  const contracts = Object.entries(deployment.contracts);
  
  for (const [name, address] of contracts) {
    const code = await ethers.provider.getCode(address);
    const status = code !== '0x' ? '✅' : '❌';
    console.log(`  ${status} ${name}: ${address}`);
  }
  
  // 2. 验证权限
  console.log("\n2. Verifying permissions...");
  const eventFactory = await ethers.getContractAt("EventFactory", deployment.contracts.eventFactory);
  const owner = await eventFactory.owner();
  console.log(`  EventFactory owner: ${owner}`);
  console.log(`  Expected: ${deployment.contracts.timelock}`);
  console.log(`  Status: ${owner === deployment.contracts.timelock ? '✅' : '❌'}`);
  
  // 3. 验证功能
  console.log("\n3. Verifying functionality...");
  try {
    // 尝试创建事件(应该失败,因为没有 operator 权限)
    await eventFactory.createEvent("Test", "Test", "test", "test", Math.floor(Date.now() / 1000) + 86400);
    console.log("  ❌ Should have reverted");
  } catch (error) {
    console.log("  ✅ Access control working");
  }
  
  console.log("\n✅ Verification complete!");
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

5. 上线后运营

5.1 首日运营清单

5.2 首日监控指标

指标目标告警阈值说明
系统可用性99.9%<99%服务稳定性
API 响应时间<500ms>2s性能
交易成功率>99%<95%交易功能
撮合延迟<100ms>500ms撮合引擎
Gas 消耗正常异常高成本控制
用户投诉<10>50用户体验

5.3 首周运营计划

天数重点工作目标
D1系统监控+用户反馈系统稳定
D2做市参数优化价差 < 2%
D3首批事件结算结算正常
D4用户增长推广DAU > 100
D5数据分析优化方向明确
D6功能迭代修复问题
D7周报总结经验沉淀

6. 应急预案

6.1 应急响应流程

6.2 应急场景处理

场景严重程度响应时间处理方式
合约漏洞P0立即紧急暂停+修复
资金异常P0立即紧急暂停+调查
系统宕机P130 分钟切换备份+修复
预言机异常P11 小时暂停结算+人工介入
做市异常P22 小时调整参数+观察
性能下降P324 小时优化+部署

6.3 应急联系人

角色职责联系方式
技术负责人技术决策Telegram/电话
安全负责人安全评估Telegram/电话
运营负责人用户沟通Telegram/电话
法律顾问合规咨询邮件/电话

7. OPC 上线策略

7.1 轻量上线方案

作为 OPC,不需要复杂的上线流程。推荐轻量方案:

阶段时间资金目标
测试网1 周0功能验证
主网测试3 天$100真实环境验证
小额运营1 周$1,000流程验证
正式运营持续$5,000+正式上线

7.2 OPC 上线清单

  • [ ] 测试网运行 7 天无问题
  • [ ] 主网小额测试成功
  • [ ] 监控系统就绪
  • [ ] 多签钱包创建
  • [ ] 初始做市资金到位
  • [ ] 首批事件准备
  • [ ] 社区公告准备
  • [ ] 应急联系人确认

8. 应急预案详解

8.1 安全事件响应 SOP

当检测到安全事件时,必须按照以下标准流程执行:

应急联系人矩阵

优先级角色响应时间联系方式备份
P0安全负责人5 分钟Telegram + 电话技术负责人
P0技术负责人10 分钟Telegram + 电话合约开发者
P1运营负责人30 分钟Telegram社区经理
P1法律顾问2 小时邮件 + 电话合规团队

8.2 资金异常处理

异常类型检测方式响应动作恢复方案
合约余额突降余额监控立即暂停审计+修复
异常大额提现交易监控暂停+人工审核多签确认
做市资金耗尽风控监控暂停做市补充资金
Gas 费异常高Gas 监控暂停链上操作等待回落

资金监控脚本

typescript
class FundMonitor {
  private alertThreshold = 0.1; // 10% 变动告警
  
  async checkBalance(contractAddress: string): Promise<void> {
    const currentBalance = await this.getBalance(contractAddress);
    const previousBalance = await this.getPreviousBalance(contractAddress);
    
    const changeRate = Math.abs(currentBalance - previousBalance) / previousBalance;
    
    if (changeRate > this.alertThreshold) {
      await this.sendAlert({
        type: 'balance_anomaly',
        severity: changeRate > 0.5 ? 'critical' : 'warning',
        message: `合约余额变动 ${(changeRate * 100).toFixed(1)}%`,
        currentBalance,
        previousBalance,
        contractAddress
      });
      
      // 严重情况自动暂停
      if (changeRate > 0.5) {
        await this.emergencyPause(contractAddress);
      }
    }
  }
}

8.3 灾难恢复计划

灾难场景RTORPO恢复步骤
服务器全挂4 小时1 小时切换备用区域 + 数据恢复
数据库损坏2 小时5 分钟从备份恢复 + 链上重放
合约漏洞1 小时0暂停 + 代理升级
DNS 劫持30 分钟0切换 DNS + Cloudflare
密钥泄露15 分钟0多签暂停 + 更换密钥

9. 常见问题

问题原因解决方案
部署失败Gas 不足预留足够 Gas
合约不兼容版本问题使用兼容版本
多签丢失签名者签名者不足预留备用签名者
用户投诉体验问题快速响应+修复
资金异常合约漏洞紧急暂停+修复
性能问题流量超预期扩容+优化

9. 下一步

完成主网上线后,进入 阶段 10:数据驱动

8.4 上线后安全监控

上线后需要持续监控合约安全状态。以下是关键监控指标和响应流程:

合约安全监控指标

监控项检测方式告警阈值响应动作
异常大额交易链上事件监听单笔 >$50k人工审核
合约余额变动定时查询变动 >10%立即告警
权限变更事件监听任何变更立即告警
Gas 异常交易监控Gas >5x 正常暂停操作
预言机延迟心跳检测>1 小时无更新人工介入

安全监控脚本

typescript
class SecurityMonitor {
  private provider: ethers.Provider;
  private alertBot: AlertBot;
  
  /**
   * 监控合约余额异常
   */
  async monitorBalanceAnomaly(): Promise<void> {
    const contracts = [
      { name: 'OrderBookFactory', address: '0x...' },
      { name: 'FeeVault', address: '0x...' },
      { name: 'FundingFactory', address: '0x...' }
    ];
    
    for (const contract of contracts) {
      const currentBalance = await this.provider.getBalance(contract.address);
      const previousBalance = await this.getPreviousBalance(contract.address);
      
      const changeRate = Number(
        (currentBalance - previousBalance) * 100n / previousBalance
      );
      
      if (Math.abs(changeRate) > 10) {
        await this.alertBot.sendAlert({
          severity: 'critical',
          title: `Balance Anomaly: ${contract.name}`,
          description: `Balance changed ${changeRate.toFixed(1)}%`,
          contract: contract.address,
          currentBalance: ethers.formatEther(currentBalance),
          previousBalance: ethers.formatEther(previousBalance)
        });
      }
    }
  }
  
  /**
   * 监控权限变更事件
   */
  async monitorPermissionChanges(): Promise<void> {
    const roleGrantedABI = ['event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender)'];
    const iface = new ethers.Interface(roleGrantedABI);
    
    // 订阅所有合约的 RoleGranted 事件
    this.provider.on({
      topics: [iface.getEvent('RoleGranted').topicHash]
    }, async (log) => {
      const parsed = iface.parseLog(log);
      
      await this.alertBot.sendAlert({
        severity: 'warning',
        title: 'Permission Change Detected',
        description: `Role ${parsed.args.role} granted to ${parsed.args.account}`,
        txHash: log.transactionHash
      });
    });
  }
  
  /**
   * 监控预言机心跳
   */
  async monitorOracleHeartbeat(): Promise<void> {
    const lastUpdate = await this.getLastOracleUpdate();
    const hoursSinceUpdate = (Date.now() - lastUpdate) / (1000 * 60 * 60);
    
    if (hoursSinceUpdate > 1) {
      await this.alertBot.sendAlert({
        severity: 'warning',
        title: 'Oracle Heartbeat Missing',
        description: `No oracle update for ${hoursSinceUpdate.toFixed(1)} hours`
      });
    }
  }
}

8.5 合约升级实战指南

当发现合约漏洞或需要新功能时,需要执行合约升级。以下是安全的升级流程:

升级前检查清单

检查项验证方式通过标准
存储布局兼容forge inspect storage-layout新旧布局一致
函数选择器无冲突forge inspect abi无重复选择器
初始化函数保护代码审查initializer 修饰符
测试覆盖率forge coverage>95%
Fork 测试--fork-url 测试所有测试通过
审计报告第三方审计无高危问题

升级执行脚本

typescript
// scripts/upgrade.ts
async function upgradeContract(
  proxyAddress: string,
  newImplementation: string,
  timelockAddress: string
): Promise<void> {
  // 1. 提交升级提案
  const timelock = await ethers.getContractAt('TimelockController', timelockAddress);
  
  const upgradeCall = ethers.Interface.encodeFunctionData(
    'upgradeTo',
    [newImplementation]
  );
  
  const tx = await timelock.schedule(
    proxyAddress,           // target
    0,                      // value
    upgradeCall,            // data
    ethers.ZeroHash,        // predecessor
    ethers.ZeroHash,        // salt
    48 * 60 * 60           // delay: 48 hours
  );
  
  console.log('Upgrade proposal submitted:', tx.hash);
  console.log('Waiting 48 hours for timelock...');
  
  // 2. 等待延迟期
  await tx.wait();
  
  // 3. 执行升级(48 小时后)
  // const executeTx = await timelock.execute(
  //   proxyAddress, 0, upgradeCall,
  //   ethers.ZeroHash, ethers.ZeroHash
  // );
  // console.log('Upgrade executed:', executeTx.hash);
}

8.6 上线后常见问题处理

问题症状响应时间处理方案
合约暂停交易失败立即检查暂停原因+修复
Gas 飙升交易卡住30 分钟暂停链上操作+等待
预言机延迟结算延迟1 小时人工介入+手动结算
流动性不足价差过大2 小时补充做市资金
用户投诉社区反馈4 小时快速响应+修复

上线后监控 Prompt(用于 AI 生成监控报告):

text
请根据以下监控数据生成一份上线后首日运营报告:
- 系统可用性:99.95%
- API 响应时间:P95 = 180ms
- 交易成功率:99.8%
- 活跃用户:150
- 交易量:$12,000
- 做市价差:1.8%
- 用户投诉:3 个

请分析数据,指出需要关注的问题,并给出改进建议。

上线后运营 SOP

typescript
// 上线后每日运营 SOP
const dailyOperationsSOP = [
  { time: '09:00', task: '检查系统状态和监控告警', priority: 'P0' },
  { time: '09:30', task: '查看昨日交易数据和用户反馈', priority: 'P0' },
  { time: '10:00', task: '检查做市库存和价差', priority: 'P1' },
  { time: '11:00', task: '处理用户工单和社区反馈', priority: 'P1' },
  { time: '14:00', task: '分析数据趋势,调整策略', priority: 'P2' },
  { time: '17:00', task: '生成每日运营报告', priority: 'P2' },
  { time: '18:00', task: '备份数据和日志', priority: 'P1' },
];

8.7 合约验证与开源最佳实践

合约上线后,必须进行验证和开源,以建立用户信任:

typescript
// 合约验证脚本
async function verifyContracts(deployment: DeploymentInfo): Promise<void> {
  const contracts = [
    { name: 'EventFactory', address: deployment.contracts.eventFactory },
    { name: 'OrderBookFactory', address: deployment.contracts.orderBookFactory },
    { name: 'OracleManager', address: deployment.contracts.oracleManager },
    { name: 'FeeVault', address: deployment.contracts.feeVault }
  ];
  
  for (const contract of contracts) {
    try {
      await hre.run('verify:verify', {
        address: contract.address,
        constructorArguments: contract.constructorArgs
      });
      console.log(`✅ ${contract.name} verified`);
    } catch (error) {
      console.log(`❌ ${contract.name} verification failed:`, error);
    }
  }
}

开源策略

阶段动作原因
测试网私有仓库快速迭代
审计提交审计第三方验证
主网开源合约建立信任
运营开源 SDK生态建设

开源 Checklist

  • [ ] 合约代码开源到 GitHub
  • [ ] 编写详细的 README 文档
  • [ ] 添加 LICENSE 文件(MIT 或 Apache 2.0)
  • [ ] 提交合约验证到区块浏览器
  • [ ] 发布安全审计报告
  • [ ] 建立漏洞赏金计划

漏洞赏金计划

漏洞级别赏金说明
Critical$10,000-50,000资金被盗风险
High$5,000-10,000功能异常
Medium$1,000-5,000性能问题
Low$500-1,000代码质量

参考与延伸

[11] Sourcify(2025)— 合约验证平台

[12] Code4rena(2025)— Web3 审计竞赛平台

[1] Gnosis Safe(2025)— 多签钱包

[2] OpenZeppelin Timelock(2025)— 时间锁合约

[3] Base Network(2025)— L2 网络

[4] Tenderly(2025)— 合约监控

[5] Blocknative(2025)— 交易监控

[6] Incident Response Guide(2025)— SANS 应急响应手册

[7] Disaster Recovery Planning(2010)— NIST 灾难恢复标准

[8] Ethereum Security(2025)— 以太坊安全最佳实践

[9] Immunefi(2025)— Web3 漏洞赏金平台

[10] Chainalysis(2025)— 链上监控和合规工具

OPC 超级个体实战指南