本文介绍了如何使用OpenZeppelin Defender监控通过工厂模式创建的合约克隆。通过设置Monitor监控工厂合约的事件,触发Action自动将新创建的克隆合约地址添加到Defender的地址簿和另一个Monitor的监控列表中,简化了对大量克隆合约的追踪和监控。
工厂克隆模式对于最小化 gas 成本可能是有利的。然而,由于每个克隆都被部署到一个新的地址,有效地跟踪和监控这些合约可能是一个挑战。
本指南展示了如何使用 Defender 来监控工厂合约以及由它创建的克隆合约。监控自动化是通过以下 Defender 模块结构实现的:
一个 Monitor 监控由工厂合约发出的、用于创建克隆的成功事件。如果检测到,它会触发一个 Action 并 传递关于交易的信息。
该 Action 利用 defender-sdk
将新创建的合约地址添加到 地址簿 中,以便更容易地进行监控。
此外,该 Action 使用 defender-sdk
将克隆地址添加到 Monitor 监控的地址列表中。
在这种情况下,由于克隆合约将具有相同的 ABI,因此可以预先提供合约 ABI。或者,你可以使用 Etherscan 的 API 从给定地址的已验证合约中动态检索 ABI。
要以编程方式将合约添加到地址簿,sdk
需要以 API 密钥和密钥的形式提供的凭据。在 API 密钥页面 中创建并复制凭据。
现在,导航到 Defender 中的 Secrets 页面,创建一个名为 API_KEY
的新 secret,然后粘贴 API 密钥。创建另一个名为 API_SECRET
的 secret,然后粘贴 API secret。这些 secret 将被 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 现在已准备好被 Monitor 触发。
手动触发此 Action 将会引发错误,因为 Action 依赖于 Monitor 提供的数据(例如,新部署的克隆合约地址)。 |
此 Monitor 将监控由工厂合约发出的、表明已创建新克隆的事件。导航到 Monitor 创建页面,选择一个名称、风险类别,然后选择工厂合约(如果尚未添加,请添加工厂)。
保持 Transaction Filters
不变,然后继续到 Events
选项卡。在此处,选择用于克隆创建的事件名称,并将事件参数留空以捕获所有发出的事件。
最后,打开 Alerts
部分,并在 Execute an Action
下拉列表中选择在上一步中创建的 Action。随意添加任何其他设置(如通知),然后保存 Monitor。
与任何 action 一样,此 Monitor 的触发将记录在 Logs 中。
要测试设置,请导航到 Transaction Proposals 以通过工厂手动创建一个克隆。选择工厂合约,然后调用使用任何所需参数创建克隆的函数。
然后,使用你喜欢的审批流程(如 Relayer 或 EOA 钱包)执行此交易。转到 Action 的运行历史记录以验证它是否由 Monitor 触发,并将克隆合约地址添加到 Defender。
现在你有了一个克隆合约作为所有未来克隆合约的模板,现在是时候为它们创建一个 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。
要验证,请执行另一次测试运行!
- 原文链接: docs.openzeppelin.com/de...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!