Monitor
监视器允许您全面了解智能合约的风险和行为。您可以检测威胁,获取关于威胁和异常的警报,并自动响应和解决问题。
用例
-
监控关键事件和授权函数,如所有权转移、暂停或铸币。
-
对潜在的危险交易或运营问题发出警报。
-
将通知集成到 Slack、Telegram、Discord、电子邮件、PagerDuty、Opsgenie 或自定义 API。
-
使用预构建的模板快速轻松地设置监控。
-
与其他 Defender 模块结合使用,以使用监视器触发器执行链上交易。
监视器
监视器可以从头开始创建,也可以从模板创建,这些模板是为常见用例设计的。模板会自动预填充监视器,因此您可以轻松修改和重新调整它们。

监视器根据其监控的风险类型分为五个类别:
-
Governance
-
Access Control
-
Suspicious Activity
-
Financial
-
Technical
您还可以指定严重程度,您的团队可以使用它按严重程度对监视器进行分组或过滤。
-
High Severity
-
Medium Severity
-
Low Severity
配置监视器
监视器会监视所有链上合约交易,并在交易与参数、过滤器或事件匹配时发出通知。
目前,除了 Fantom 之外,所有 网络都支持监视器。 |
常规信息
-
Name:分配给监视器的名称。
-
Risk Category:监视器的风险类别,用于过滤或分组。
-
Contracts:要监控的智能合约。监控依赖于底层的 ABI,因此每个监视器可能只有一个 ABI。如果存在多个智能合约,则监视器必须遵守相同的 ABI/Interface。
-
Confirmation Blocks:如果您希望仅在确定交易被接受到一定程度后才收到通知,建议使用更高的确认区块级别,但如果您希望尽快收到通知并容忍重组,则使用较低的确认区块级别更好。在接受安全和最终区块标签的链中,您也可以选择它们作为确认区块级别。
匹配规则
要使交易触发通知,它必须满足*所有*以下条件:
-
交易*必须*具有与配置的地址匹配的 To、From 或 Address(来自日志)。
-
如果指定了*交易过滤器*
-
交易*必须*与*交易过滤器*匹配。
-
-
如果选择了*事件*
-
交易*必须*发出任何选定的事件并匹配*事件条件*(如果有)
-
-
如果选择了*函数*
-
交易*必须*直接调用任何选定的函数(目前未检测到合约调用)并匹配*函数条件*(如果有)
-
交易过滤器
交易过滤器允许缩小被监控的交易范围。这些作为属性表达式或 JavaScript 代码输入,提供了极大的灵活性。为了适应校验和地址和非校验和地址的比较,比较是不区分大小写的。
要接收涉及所选事件/函数的所有交易,不应指定交易条件。 |
-
条件可以使用 AND、OR、NOT 和 ()
-
条件可以使用 ==、<、>、>=、⇐ 进行比较
-
数字值可以用 Hex (0xabc123) 或 Decimal (10000000000) 表示
-
字符串值只能通过 == 进行比较
-
包括基本数学运算符:+、-、*、/、^*
如果指定了交易过滤器条件,则交易*必须*满足此条件才能触发通知。 |
交易条件可以引用以下属性
-
to 是交易的 to 地址
-
from 是交易的 from 地址
-
gasPrice 是交易中发送的 Gas 价格。在 EIP1559 交易中,它等于或低于
maxFeePerGas
。 -
maxFeePerGas 是交易愿意为交易支付的最高价格。仅存在于 EIP1559 交易中。
-
maxPriorityFeePerGas 是交易愿意为包含支付给矿工的超过
BASE_FEE
的最高 Wei 金额。仅存在于 EIP1559 交易中。 -
gasLimit 是交易中发送的 Gas 限制
-
gasUsed 是交易中使用的 Gas 量
-
value 是交易中发送的值
-
nonce 是特定交易的 nonce
-
status 是一个派生值,可以与 "success" 或 "failed" 进行比较
自定义过滤器
自定义过滤器支持用于过滤交易的自定义代码。如果指定了自定义过滤器,则将使用给定区块中找到的匹配项列表调用它。这允许监视器使用其他数据源和自定义逻辑来评估交易是否匹配。
只有符合其他条件(事件、函数、交易)的交易才会调用自定义过滤器。 |
每次调用最多可包含 25 个交易。 |
请求 Schema
请求正文将包含以下结构。来自 defender-sdk-action-client 包的 MonitorConditionRequest
类型可用于 Typescript 中的自定义过滤器。
{
"events": [
{
"hash": "0xab..123", // 交易哈希
"timestamp": "1699857792", // 交易的时间戳 (区块)
"blockNumber": 18561272, // 交易的区块号
"blockHash": "0xab..123", // 看到此交易的区块哈希
"transaction": { // eth_getTransactionReceipt 响应正文
... // 参见 https://eips.ethereum.org/EIPS/eip-1474
"cumulativeGasUsed": "0xc3614",
"effectiveGasPrice": "0x6e214d78",
"gasUsed": "0x6075",
"logs": [
{ ... }
],
"logsBloom": "0x4..0",
"status": "0x1",
"from": "0xab..123",
"to": "0xab..123",
"transactionHash": "0xab..123",
"transactionIndex": "0x9",
"type": "0x2"
},
"matchReasons": [ // 监视器触发的原因
{
"type": "event", // event, function, or transaction
"address": "0x123..abc", // 发出事件的合约地址
"signature": "...", // 你的事件/函数的签名
"condition": "value > 5", // 条件表达式(如果有)
"args": ["5"], // 按索引的参数(未命名的存在)
"params": { "value": "5" } // 按名称的参数(未命名的不存在)
}
],
"matchedAddresses": ["0xabc..123"], // 你正在监控的来自此交易的地址
"matchedChecksumAddresses": ["0xAbC..123"], // 你正在监控的来自此交易的校验和地址
"monitor": {
"id": "44a7d5...31df5", // 你的监视器的内部 ID
"name": "Monitor Name", // 你的监视器的名称
"abi": [...], // 你的地址的 abi(或未定义)
"addresses": ["0x000..000"], // 你的监视器正在监视的地址
"confirmBlocks": 0, // 监视器等待的区块数(在 PoS 客户端上可以是“safe”或“finalized”)
"network": "rinkeby" // 你的地址的网络
"chainId": 4 // 网络的链 Id
},
"metadata": "..." // 元数据(如果可用)
}
]
}
响应 Schema
自定义过滤器必须返回一个包含所有匹配项的结构。返回一个空对象表示未发生匹配。此对象的类型为 MonitorConditionResponse
。
错误将被视为不匹配。 |
{
"matches": [
{
"hash": "0xabc...123", // 交易哈希
"metadata": {
"foo": true // 要与通知共享的任何对象
}
},
{
"hash": "0xabc...123" // 没有指定元数据的示例
}
]
}
自定义过滤器示例
exports.handler = async function(payload) {
const conditionRequest = payload.request.body;
const matches = [];
const events = conditionRequest.events;
for(const evt of events) {
// 在此处添加用于匹配的自定义逻辑
// 元数据可以是任何可进行 JSON 编组的对象(或未定义)
matches.push({
hash: evt.hash,
metadata: {
"id": "customId",
"timestamp": new Date().getTime(),
"numberVal": 5,
"nested": { "example": { "here": true } }
}
});
}
return { matches }
}
事件和函数
事件和函数可以选择作为过滤器。选择多个事件充当 OR 子句(为任何选定的事件触发)。函数也是如此。
事件或函数的条件可以进一步缩小监视器的范围。这些可以通过名称(如果参数已命名)或通过索引(例如,$0,$1…)引用签名中的参数。变量必须与接口中显示的类型匹配。如果留空,则条件将被忽略。
如果未指定任何事件或函数,则到合约或来自合约的所有交易都将在范围内。 |
监视器无缝支持智能合约在所有网络上发出的事件的通知,无论它们是直接触发还是通过来自第三方合约的内部调用触发。但是,跟踪和提供合约内内部函数调用通知的功能目前仅限于 Ethereum 主网。 |
条件示例
发出 Transfer(…)
事件且值在 1 到 100 ETH 之间的交易(以十六进制表示)
// Event Signature: Transfer(address to, address from, uint256 value)
value > 0xde0b6b3a7640000 and value < 0x56bc75e2d63100000
发出 ValsEvent(…)
事件且具有第一个元素等于 5 的数组的交易
// Event Signature: ValsEvent(uint256[3] vals)
vals[0] == 5
调用具有未命名的字符串“hello”的 greet(…)
函数的交易
// Function Signature: greet(address, string)
$1 == "hello"
警报
监视器可以使用任何受支持的通知通道进行警报。也可以连接应该与监视器一起运行的 Action 或 Workflow。
为防止来自单个监视器的重复警报并控制通知率,您可以使用“警报阈值”和“连续通知之间的最短时间”字段。
-
警报阈值:定义在发送通知或触发 Action 之前,监视器必须在每个时间单位内触发的次数。时间单位由“连续通知之间的最短时间”字段定义。
-
连续通知之间的最短时间:设置发送通知之间的最短等待时间。

通知
您可以创建附加到监视器警报的*通知*,以便在多个渠道中获得有关链上事件的通知,有关如何创建和配置它们的更多信息,请参见 此部分。
预览
*监视器名称*
Monitor
*网络*
rinkeby
*区块哈希*
0x22407d00e953e5f8dabea57673b9109dad31acfc15d07126b9dc22c33521af52
*交易哈希*
0x1dc91b98249fa9f2c5c37486a2427a3a7825be240c1c84961dfb3063d9c04d50
https://rinkeby.etherscan.io/tx/0x1dc91b98249fa9f2c5c37486a2427a3a7825be240c1c84961dfb3063d9c04d50[区块浏览器]
*匹配原因 1*
_类型:_ 函数
_匹配地址_:_ 0x1bb1b73c4f0bda4f67dca266ce6ef42f520fbb98
_签名:_ greet(name)
_条件:_ name == 'test'
_参数:_
name: test
*匹配原因 2*
_类型:_ 交易
_条件:_ gasPrice > 10
*值*
0x16345785D8A0000
消息语法
自定义通知支持一组有限的 markdown 语法:
-
粗体 (**this text is bold**)
-
斜体 (*this text* and _this text_ are italic)
-
链接 (this is a [link](https://example.com))
部分支持其他 markdown 语法,但渲染行为因平台而异。电子邮件支持完整的 HTML,并且具有最丰富的功能集,但其他消息传递平台存在限制,包括对标准 markdown 功能(如标题、块引用和表格)的支持。受支持功能的组合(例如,粗体和斜体文本)也具有混合支持。如果 markdown 包含任何具有混合平台支持的语法,则警告消息将直接显示在编辑器下方。
监视器事件 Schema
使用自定义通知模板时,您可以访问以下 schema。如果您配置监视器来执行一个 Action,则此 schema 也会传递给该 Action。
{
"transaction": { // eth_getTransactionReceipt 响应正文
... // 参见 https://eips.ethereum.org/EIPS/eip-1474
"cumulativeGasUsed": "0xc3614",
"effectiveGasPrice": "0x6e214d78",
"gasUsed": "0x6075",
"logs": [
{ ... }
],
"logsBloom": "0x4..0",
"status": "0x1",
"from": "0xab..123",
"to": "0xab..123",
"transactionHash": "0xab..123",
"transactionIndex": "0x9",
"type": "0x2"
},
"blockHash": "0xab..123", // 看到此交易的区块哈希
"matchReasons": [ // 监视器触发的原因
{
"type": "event", // event, function, or transaction
"address": "0x123..abc", // 发出事件的合约地址
"signature": "...", // 事件/函数的签名
"condition": "value > 5", // 条件表达式(如果有)
"args": ["5"], // 按索引的参数(未命名的存在)
"params": { "value": "5" } // 按名称的参数(未命名的不存在)
}
],
"matchedAddresses":["0x000..000"] // 从此交易监控的地址
"monitor": {
"id": "44a7d5...31df5", // 监视器的内部 ID
"name": "Monitor Name", // 监视器的名称
"abi": [...], // 地址的 abi(或未定义)
"addresses": ["0x000..000"], // 监控的地址
"confirmBlocks": 0, // 监视器等待的区块数(在 PoS 客户端上可以是“safe”或“finalized”)
"network": "rinkeby" // 地址的网络
"chainId": 4 // 网络的链 Id
},
"value": "0x16345785D8A0000" // 交易的值
"metadata": {...} // 由 Action 条件注入的元数据(如果适用)
}
暂停和删除
在监视器页面中,您可以暂停已创建的处于活动状态的监视器。通过单击卡片上的虚线按钮,您可以删除监视器或将其另存为模板。
将监视器另存为模板会存储其配置和参数,可以通过单击模板库选项卡找到这些配置和参数。
我们提供了一个快速入门教程,用于使用 Defender 监视智能合约。在此处查看 它! |