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 超级个体实战指南