工厂克隆的自动监控 - OpenZeppelin 文档

本文介绍了如何使用OpenZeppelin Defender监控通过工厂模式创建的合约克隆。通过设置Monitor监控工厂合约的事件,触发Action自动将新创建的克隆合约地址添加到Defender的地址簿和另一个Monitor的监控列表中,简化了对大量克隆合约的追踪和监控。

自动监控工厂克隆

工厂克隆模式对于最小化 gas 成本可能是有利的。然而,由于每个克隆都被部署到一个新的地址,有效地跟踪和监控这些合约可能是一个挑战。

本指南展示了如何使用 Defender 来监控工厂合约以及由它创建的克隆合约。监控自动化是通过以下 Defender 模块结构实现的:

  • 一个 Monitor 监控由工厂合约发出的、用于创建克隆的成功事件。如果检测到,它会触发一个 Action传递关于交易的信息

  • 该 Action 利用 defender-sdk 将新创建的合约地址添加到 地址簿 中,以便更容易地进行监控。

  • 此外,该 Action 使用 defender-sdk 将克隆地址添加到 Monitor 监控的地址列表中。

在这种情况下,由于克隆合约将具有相同的 ABI,因此可以预先提供合约 ABI。或者,你可以使用 Etherscan 的 API 从给定地址的已验证合约中动态检索 ABI。

生成 API 密钥

要以编程方式将合约添加到地址簿,sdk 需要以 API 密钥和密钥的形式提供的凭据。在 API 密钥页面 中创建并复制凭据。

创建 API 凭据

现在,导航到 Defender 中的 Secrets 页面,创建一个名为 API_KEY 的新 secret,然后粘贴 API 密钥。创建另一个名为 API_SECRET 的 secret,然后粘贴 API secret。这些 secret 将被 Action 安全地使用。

保存 API 凭据

创建 Action

导航到 Action 创建页面,输入一个名称,然后选择 Webhook 作为触发器。然后,粘贴以下 Action 代码并保存它:

const { Defender } = require('@openzeppelin/defender-sdk');

exports.handler = async function (event) {
  const creds = {
    apiKey: event.secrets.API_KEY,
    apiSecret: event.secrets.API_SECRET,
  }
  const client = new Defender(creds);

  const payload = event.request.body
  const matchReasons = payload.matchReasons
  const newCloneAddress = matchReasons[0].params._clone
  const newCloneAbi = `[\
    {\
      "anonymous": false,\
      "inputs": [\
        {\
          "indexed": false,\
          "internalType": "uint256",\
          "name": "value",\
          "type": "uint256"\
        }\
      ],\
      "name": "ValueChanged",\
      "type": "event"\
    },\
    {\
      "inputs": [\
        {\
          "internalType": "uint256",\
          "name": "value",\
          "type": "uint256"\
        }\
      ],\
      "name": "initialize",\
      "outputs": [],\
      "stateMutability": "nonpayable",\
      "type": "function"\
    },\
    {\\
      "inputs": [],\
      "name": "retrieve",\
      "outputs": [\
        {\
          "internalType": "uint256",\
          "name": "",\
          "type": "uint256"\
        }\
      ],\
      "stateMutability": "view",\
      "type": "function"\
    },\
    {\
      "inputs": [\
        {\
          "internalType": "uint256",\
          "name": "value",\
          "type": "uint256"\
        }\
      ],\
      "name": "store",\
      "outputs": [],\
      "stateMutability": "nonpayable",\
      "type": "function"\
    }\
  ]`
  // 添加新的克隆合约
  await client.proposal.addContract({
    network: 'sepolia',
    address: newCloneAddress,
    name: `Clone ${newCloneAddress}`,
    abi: newCloneAbi,
  })
}

创建 Action

该 Action 现在已准备好被 Monitor 触发。

手动触发此 Action 将会引发错误,因为 Action 依赖于 Monitor 提供的数据(例如,新部署的克隆合约地址)。

创建 Monitor

此 Monitor 将监控由工厂合约发出的、表明已创建新克隆的事件。导航到 Monitor 创建页面,选择一个名称、风险类别,然后选择工厂合约(如果尚未添加,请添加工厂)。

Monitor 常规信息

保持 Transaction Filters 不变,然后继续到 Events 选项卡。在此处,选择用于克隆创建的事件名称,并将事件参数留空以捕获所有发出的事件。

Monitor 事件

最后,打开 Alerts 部分,并在 Execute an Action 下拉列表中选择在上一步中创建的 Action。随意添加任何其他设置(如通知),然后保存 Monitor。

Monitor 警报

与任何 action 一样,此 Monitor 的触发将记录在 Logs 中。

测试运行

要测试设置,请导航到 Transaction Proposals 以通过工厂手动创建一个克隆。选择工厂合约,然后调用使用任何所需参数创建克隆的函数。

创建克隆的交易提案

然后,使用你喜欢的审批流程(如 Relayer 或 EOA 钱包)执行此交易。转到 Action 的运行历史记录以验证它是否由 Monitor 触发,并将克隆合约地址添加到 Defender。

Action 运行历史记录

为克隆创建 Monitor

现在你有了一个克隆合约作为所有未来克隆合约的模板,现在是时候为它们创建一个 Monitor 了。导航到 Monitor 创建页面,选择一个名称、风险类别,然后选择克隆合约。

此外,你可以随意添加任何其他交易、事件和函数或通知的过滤器。保存 Monitor 并观察日志/通知以验证 Monitor 是否按预期工作。

Monitor 克隆

自动将克隆添加到 Monitor

使用最后一个 Monitor,你可以更新 Action 以将任何新创建的合约添加到 Monitor 正在监控的地址列表中。使用以下代码更新 Action 代码,将 monitorId 替换为在上一步中创建的 Monitor 的 ID:

const { Defender } = require('@openzeppelin/defender-sdk');

exports.handler = async function (event) {
  const creds = {
    apiKey: event.secrets.API_KEY,
    apiSecret: event.secrets.API_SECRET,
  }
  const client = new Defender(creds);

  const payload = event.request.body
  const matchReasons = payload.matchReasons
  const newCloneAddress = matchReasons[0].params._clone
  const newCloneAbi = `[\
    {\
      "anonymous": false,\
      "inputs": [\
        {\
          "indexed": false,\
          "internalType": "uint256",\
          "name": "value",\
          "type": "uint256"\
        }\
      ],\
      "name": "ValueChanged",\
      "type": "event"\
    },\
    {\
      "inputs": [\
        {\
          "internalType": "uint256",\
          "name": "value",\
          "type": "uint256"\
        }\
      ],\
      "name": "initialize",\
      "outputs": [],\
      "stateMutability": "nonpayable",\
      "type": "function"\
    },\
    {\
      "inputs": [],\
      "name": "retrieve",\
      "outputs": [\
        {\
          "internalType": "uint256",\
          "name": "",\
          "type": "uint256"\
        }\
      ],\
      "stateMutability": "view",\
      "type": "function"\
    },\
    {\
      "inputs": [\
        {\
          "internalType": "uint256",\
          "name": "value",\
          "type": "uint256"\
        }\
      ],\
      "name": "store",\
      "outputs": [],\
      "stateMutability": "nonpayable",\
      "type": "function"\
    }\
  ]`
  // 添加新的克隆合约
  await client.proposal.addContract({
    network: 'sepolia',
    address: newCloneAddress,
    name: `Clone ${newCloneAddress}`,
    abi: newCloneAbi,
  })

  // 将克隆合约添加至 Monitor
  const monitorId = 'REPLACE'
  const monitor = await client.monitor.get(monitorId)
  const subscribedAddresses = monitor.addressRules[0].addresses
  subscribedAddresses.push(newCloneAddress)
  await client.action.update(monitorId, { addresses: subscribedAddresses })
}

现在,当 Action 运行时,它不仅会将合约添加到 Defender,还会将其添加到 Monitor。

要验证,请执行另一次测试运行!

参考

← 中继无 Gas 的 Meta 交易

管理 TimelockController 的角色 →

  • 原文链接: docs.openzeppelin.com/de...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
OpenZeppelin
OpenZeppelin
江湖只有他的大名,没有他的介绍。