关于 solidity-audit
面向 Solidity 合约审计与代码审查的安全检查清单 Skill,覆盖常见合约漏洞及代理、信任边界等风险。可用于按类别检查实现与安全控制。
主要功能
- 01检查重入与访问控制
- 02检查输入、预言机与数值风险
- 03检查签名、ERC20 与抢跑问题
- 04检查代理升级及跨合约信任
- 05检查状态顺序与地址限制绕过
适用场景
- 01审查 Solidity 合约的漏洞
- 02检查代理合约升级权限
- 03分析跨合约调用与状态依赖
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ 0xlayerghost/ solidity-agent-kit --skill solidity-audit安装后在 Claude Code 中输入/solidity-audit确认已加载。
详细介绍
Solidity 安全审计清单
语言规则
- 始终使用用户所用的语言回复。 如果用户用中文提问,就用中文回复。如果用户用英语提问,就用英语回复。
用法:此技能用于安全审计和代码审查。它不会自动调用——审查合约漏洞时,请调用
/solidity-audit。
合约级漏洞
1. 重入
| 类型 | 说明 | 检查项 |
|---|---|---|
| 同函数 | 攻击者通过 fallback/receive 重新进入同一函数 | 所有外部调用是否都发生在状态更新之后(CEI 模式)? |
| 跨函数 | 攻击者重新进入共享状态的其他函数 | 所有操作共享状态的函数是否都受 nonReentrant 保护? |
| 跨合约 | 攻击者通过读取过时状态的其他合约重新进入 | 外部合约是否无法读取中间状态? |
| 只读 | View 函数在执行中途返回过时数据 | 状态转换期间,是否未将关键 View 函数用作预言机? |
案例:GMX v1(2025 年 7 月,4,200 万美元)——Arbitrum 上的 GLP 池发生重入,攻击者循环执行提款以耗尽流动性。
2. 访问控制
| 检查项 | 详情 |
|---|---|
| 缺少修饰符 | 每个修改状态的函数是否都有明确的访问控制? |
| 修饰符逻辑 | 修饰符是否会在检查失败时实际回滚(而不只是进行空检查)? |
| 状态标志 | 一次性访问模式是否会在每位用户操作后正确更新存储? |
| 管理员权限范围 | 所有者权限是否最小化且有时间限制? |
案例:Bybit(2025 年 2 月,14 亿美元)——Safe{Wallet} UI 被注入恶意 JS,签名流程遭到劫持。这并非合约缺陷,而是基础设施层的访问控制问题。
3. 输入验证
| 检查项 | 详情 |
|---|---|
| 零地址 | 所有地址参数是否都拒绝 address(0)? |
| 零金额 | 资金转账是否拒绝零金额? |
| 数组边界 | 成对数组是否经过验证,确保长度相同? |
| 任意调用 | 是否不存在攻击者可控 data 的未验证 address.call(data)? |
| 数值边界 | 输入是否设定了边界,以防止尘埃攻击或 Gas 消耗攻击? |
4. 闪电贷攻击
| 类型 | 机制 | 防御措施 |
|---|---|---|
| 价格操纵 | 闪电贷借款 → 兑换以推动价格变动 → 利用依赖价格的逻辑 → 偿还 | 设有最低流动性检查的 TWAP 预言机 |
| 治理 | 闪电贷借入治理代币 → 投票 → 在同一区块内偿还 | 快照投票 + 最低持有期 + ≥ 48h 的时间锁 |
| 清算 | 闪电贷借款 → 操纵抵押品价值 → 触发清算 | 多预言机价格验证 + 熔断器 |
| 组合(舍入) | 闪电贷借款 → 操纵池 → 利用舍入误差进行微量提款 → 偿还 | 最低提款金额 + 虚拟份额 |
案例:
- Cream Finance(2021 年 10 月,1.3 亿美元)——闪电贷 + yUSD 预言机操纵 + 缺少重入保护
- Abracadabra(2025 年 3 月,1,300 万美元)——cauldron 中的状态追踪错误,导致自我清算 + 坏账
- Bunni(2025 年 9 月,840 万美元)——闪电贷 + 池价格操纵 + 利用舍入误差进行微量提款
5. 预言机与价格
| 检查项 | 详情 |
|---|---|
| 单一预言机依赖 | 是否使用多个独立的价格来源? |
| 价格过期 | 是否检查 updatedAt 时间戳并拒绝旧数据? |
| 使用现货价格 | 是否从不使用原始 AMM 储备量进行定价? |
| 最低流动性 | 池储备量低于阈值时,预言机是否会回滚? |
| 价格偏差 | 价格相较上次已知价格变动超过阈值时,是否会触发熔断? |
| Chainlink 轮次完整性 | 是否检查 answeredInRound >= roundId? |
案例:Cream Finance(2021 年 10 月,$130M) — 攻击者通过减少供应量操纵 yUSD 金库价格,随后利用虚高的抵押品掏空所有借贷池。
6. 数值问题
| 类型 | 描述 | 防护措施 |
|---|---|---|
| 基本类型溢出 | uint256 a = uint8(b) + 1 — 在 Solidity ≥0.8 中,当 b=255 时会回滚 | 使用一致的类型,避免隐式缩窄 |
| 截断 | int8(int256Value) — 即使在 ≥0.8 中也会静默溢出 | 所有类型缩窄都使用 SafeCast 库 |
| 舍入/精度损失 | 对较小数值,usdcAmount / 1e12 总是舍入为 0 | 先乘后除;检查结果是否为零 |
| 先除后乘 | (a / b) * c 会损失精度 | 始终使用 (a * c) / b |
案例:Bunni(2025 年 9 月,$8.4M) — 微额提现中的舍入错误遭到利用,攻击者使用了闪电贷。
7. 签名问题
| 类型 | 描述 | 防护措施 |
|---|---|---|
| ecrecover 返回 address(0) | 无效签名会返回 address(0),而不会回滚 | 始终检查 recovered != address(0) |
| 重放攻击 | 同一签名在多个交易/链上重复使用 | 在签名数据中包含 chainId、nonce 和 deadline |
| 签名可塑性 | 每个 ECDSA 签名都有两组有效的 (s, v) | 使用 OpenZeppelin ECDSA.recover(会强制使用 low-s) |
| 空循环绕过 | 在 for 循环中验证签名,攻击者发送空数组 | 循环前检查 signatures.length >= requiredCount |
| 缺少对 msg.sender 的绑定 | 证明/签名未绑定到调用者 | 始终在签名/证明数据中包含 msg.sender |
8. ERC20 兼容性
| 问题 | 描述 | 防护措施 |
|---|---|---|
| 转账收费 | transfer(100) 实际到账的代币可能少于 100 | 检查转账前后的余额,并使用实际收到的数量 |
| Rebase 代币 | 代币余额会在没有转账的情况下发生变化 | 切勿缓存外部余额;始终读取实时余额 |
| 不返回 bool | 某些代币(USDT)在转账时不返回 bool | 使用 SafeERC20.safeTransfer |
| ERC777 钩子 | 转账钩子可能触发重入 | 所有接收代币的函数都使用 ReentrancyGuard |
| 零金额转账 | transferFrom(A, B, 0) — 地址投毒 | 拒绝零金额转账 |
| 授权竞态 | 将授权额度从 N 改为 M 会导致可支出 N+M | 使用 safeIncreaseAllowance/safeDecreaseAllowance |
9. MEV/抢跑
| 类型 | 描述 | 防护措施 |
|---|---|---|
| 三明治攻击 | 攻击者在受害者交易前抢跑买入,并在其后跟跑卖出 | 滑点保护 + 截止时间参数 |
| ERC4626 通胀攻击 | 首个存款人通过捐赠抬高份额价格,导致后续存款人的份额向下取整 | 设置首笔存款最低金额,或使用虚拟份额(带偏移量的 ERC4626) |
| 抢跑授权 | 新授权交易确认前,攻击者先使用旧授权额度支出 | 使用 increaseAllowance 而非 approve |
| 无限制提现 | 攻击者监控提现交易的内存池,并抢先发起自己的交易 | 要求使用提交-揭示机制或绑定身份验证 |
10. 存储与底层
| 问题 | 描述 |
|---|---|
| 存储指针 | Foo storage foo = arr[0]; foo = arr[1]; — 不会更新 arr[0] |
| 嵌套删除 | delete structWithMapping — 内部 mapping 数据仍然存在 |
| 私有变量 | 所有合约存储都可通过 eth_getStorageAt 公开读取 |
| 不安全的 delegatecall | 对不受信任的合约执行 delegatecall,可能导致调用方 selfdestruct |
| 代理存储冲突 | 升级后父合约顺序发生变化 → 变量会相互覆盖(使用存储间隙) |
| 循环中的 msg.value | msg.value 在循环中不会递减 — 可能导致双重花费 |
11. 合约检测绕过
| 方法 | 工作原理 |
|---|---|
| 构造函数调用 | 在构造函数中发起攻击 — 部署期间 extcodesize == 0 |
| 预计算 CREATE2 地址 | 预先计算合约地址,在部署前将其用作 EOA |
12. 代理与升级漏洞
| 检查项 | 详情 |
|---|---|
_authorizeUpgrade 访问控制 | UUPS 的 _authorizeUpgrade 必须具有 onlyOwner 修饰符吗? |
| 无权限工厂/注册表 | 攻击者能否使用无权限工厂(例如 Aquifer boreWell)满足升级检查? |
upgradeTo 修饰符 | 重写后的 upgradeTo/upgradeToAndCall 是否保留了 onlyProxy 修饰符? |
| 初始化器保护 | initializer 修饰符能否防止重新初始化?实现合约是否调用了 _disableInitializers()? |
| 存储布局兼容性 | 存储布局是否支持安全升级(存储间隙或 ERC-7201 命名空间)? |
案例:Code4rena 2024-07-basin H-01(引自 EVMbench 论文图 12,第 19 页)— _authorizeUpgrade 只检查了 delegatecall 和 Aquifer 注册,但缺少 onlyOwner,因此任何人都能将 Well 代理升级为恶意实现并提取资金。Oracle 补丁:添加一个 onlyOwner 修饰符。
13. 信任边界与协议可组合性
来源:EVMbench 论文 §4.2.1,图 6 / Code4rena 2024-04-noya H-08、2024-07-benddao
| 检查项 | 详情 |
|---|---|
| 跨金库信任隔离 | 注册表/路由器转发调用时是否验证了金库级授权? |
| 滥用受信任发送方 | sendTokensToTrustedAddress 等函数是否验证来源金库,而不仅仅是路由器身份? |
| 闪电贷与路由组合 | 攻击者能否利用闪电贷回调让路由器冒充任意金库? |
| 抵押品所有权验证 | 清算/质押操作是否验证了实际 NFT/抵押品所有者? |
| 跨合约状态依赖 | 多合约交互是否不依赖中间状态? |
案例:
- Code4rena 2024-04-noya H-08(引自 EVMbench 论文 §4.2.1,图 6,第 8-9 页)— PositionRegistry + BalancerFlashLoan 流程缺少金库级授权;keeper 利用闪电贷让路由器冒充任意金库,通过
sendTokensToTrustedAddress提取其他金库的资金 - Code4rena 2024-07-benddao(引自 EVMbench 论文图 13,第 19 页)—
isolateLiquidate未验证 NFT 所有权,攻击者因此可以传入他人的 tokenIds 进行清算
14. 状态排序与计数器操纵
| 检查项 | 详情 |
|---|---|
| 计数器/ID 递增顺序 | credIdCounter++ 或类似的 ID 递增是否发生在外部调用之前? |
| 创建时自动购买 | 带有自动 buy() 调用的 create() 函数是否仅在 ID/状态完全初始化后执行? |
| 退款时机 | ETH 退款(超额部分)是否在所有状态更新完成后进行? |
| 联合曲线元数据覆盖 | 攻击者能否通过重入修改联合曲线/定价参数——先以低价买入,再切换到高价曲线,然后高价卖出? |
案例:Code4rena 2024-08-phi H-06(参见 EVMbench 论文附录 H.1,第 25-28 页)——_createCredInternal 在递增 credIdCounter 之前调用了 buyShareCred;_handleTrade 在更新 lastTradeTimestamp 之前退还了超额 ETH。攻击者通过重入在低价曲线上累积份额,将元数据覆盖为高价曲线,再卖出并耗尽合约中的全部 ETH。修复方法:为 buyShareCred/sellShareCred 添加 nonReentrant。
15. 按地址状态绕过
任何基于
mapping(address => ...)的限制,都可能通过拆分到多个地址或经由中间地址转账来绕过。
| 限制类型 | 绕过方法 | 防御措施 |
|---|---|---|
冷却时间(_lastTxTime[addr]) | A 买入 → 转给 B → B 立即卖出 | 转账时继承发送方的冷却状态:_lastTxTime[to] = _lastTxTime[from] |
单笔交易最大金额(maxTxAmount) | 拆分到 N 个地址,每个地址都不超限 | 也按每个区块的 tx.origin 限制,或接受这是已知的权衡 |
钱包余额上限(maxWalletBalance) | 将代币分发到同一实体控制的多个钱包 | 本质上很难在链上强制执行;应在链下监控 |
同区块保护(_lastTxBlock[addr]) | 在同一区块中使用不同地址 | 继承发送方的区块状态:_lastTxBlock[to] = _lastTxBlock[from] |
| 交易次数限制 | 轮换地址,每个地址各进行一次交易 | 与冷却时间相同——转账时传播状态 |
审计方法(3 个步骤):
- 找出所有按地址存储的状态:搜索
mapping(address =>——对于每个映射,询问:“切换地址能否绕过此限制?” - 追踪所有代币流转路径:梳理代币可能移动的所有路径(买入、卖出、转账、铸造)。检查每条路径是否都会更新限制状态。钱包到钱包的转账路径最容易被忽略。
- 检查状态传递性:如果 A 有限制状态并将代币转给 B,B 是否会继承该状态?如果没有,这就是可绕过的漏洞。
防御原则:限制状态应随代币流转——代币流向何处,相关的按地址状态就必须随之传递。
两个常见陷阱:
- 通过
block.timestamp进行骚扰攻击:使用_lastTxTime[to] = block.timestamp会让任何人都能通过发送少量代币来骚扰目标,重置冷却时间。应使用发送方的状态。 - 直接赋值导致状态被覆盖:使用
_lastTxTime[to] = _lastTxTime[from]会让冷却时间即将结束的发送方缩短接收方已有的冷却时间。应使用max:if (_lastTxTime[from] > _lastTxTime[to]) _lastTxTime[to] = _lastTxTime[from]——只延长,不缩短。
基础设施层漏洞
16. 前端 / UI 注入
攻击者向 dApp 前端或签名界面注入恶意代码。
防御措施:签名前,确认交易 calldata 与预期的函数选择器和参数相符。使用可在设备上预览交易的硬件钱包。定期审计所有前端依赖。
案例:Bybit(2025 年 2 月,14 亿美元)——恶意 JavaScript 被注入 Safe{Wallet} UI,并在签名过程中篡改交易数据。
17. 私钥与社会工程
密钥泄露仍是 2025-2026 年损失的首要来源。
防御措施:将密钥存储在 HSM 或硬件钱包中。所有资金库和管理操作均使用多重签名(≥ 3/5)。绝不向任何“支持”人员透露助记词。定期开展社会工程意识培训。
案例:Step Finance(2026 年 1 月,3,000 万美元) — 设备遭入侵,导致资金库钱包私钥泄露。
18. 跨链桥
| 检查项 | 详情 |
|---|---|
| 继承的代码 | 审计从第三方框架继承的所有跨链桥逻辑 |
| 消息验证 | 跨链消息是否通过正确的签名和重放保护进行验证? |
| 流动性隔离 | 跨链桥资金是否与协议资金库分离? |
案例:SagaEVM(2026 年 1 月,700 万美元) — 从 Ethermint 继承了存在漏洞的 EVM 预编译跨链桥逻辑。
19. 旧版/已弃用合约
存在已知漏洞的旧合约仍可在链上被调用,且永远如此。
防御措施:永久 pause 已弃用的合约,或将资金迁出。监控旧合约地址,留意异常活动。在弃用前移除铸币/管理功能。
案例:Truebit(2026 年 1 月,2,640 万美元) — Solidity 0.6.10 合约缺少溢出保护,攻击者以近乎零成本铸造代币。
使用 Slither MCP 进行自动化分析(如可用)
配置了 slither MCP 后,请在下方的手动检查清单之前运行自动化分析:
推荐的审计流程
Step 1: slither MCP automated scan
→ get_detector_results(path, impact="High")
→ get_detector_results(path, impact="Medium")
Step 2: Review Slither findings — triage true positives vs false positives
Step 3: Manual checklist below — catch what Slither misses (business logic, economic attacks)
Step 4: Cross-reference — Slither + manual findings combined into final report
Slither MCP 工具
| 工具 | 用途 | 补充内容 |
|---|---|---|
get_contract_metadata | 提取函数、继承关系和标志 | 手动访问控制审查 |
get_function_source | 获取带行号的精确源代码 | 比 grep 更快地定位代码 |
find_implementations | 查找函数签名的所有实现 | 跨合约重入分析 |
get_detector_results | 运行 90 多项安全检测器,并按影响/置信度筛选 | 手动检查清单的自动化版本 |
get_detector_metadata | 列出可用检测器及其说明 | 了解检查内容 |
Slither 擅长发现的问题与无法发现的问题
| Slither 擅长发现的问题 | 仍需手动审查的问题 |
|---|---|
| 重入模式 | 业务逻辑缺陷 |
| 未受保护的函数 | 经济攻击向量(闪电贷组合) |
| 未使用的状态变量 | 跨协议组合风险 |
| 遮蔽问题 | 预言机操纵场景 |
| 不正确的 ERC20 接口 | 信任边界架构问题 |
| 死代码 | 特定于业务逻辑的 MEV/抢先交易问题 |
关键原则:Slither 通过静态分析提供真实依据,可减少对已知漏洞模式的漏报。但它无法推理协议层面的经济攻击,因此下方的手动检查清单至关重要。
平稳降级:如果未配置 slither MCP,请跳过本节,直接查看手动检查清单。所有检查项仍然有效且完整独立。
审计执行清单
进行安全审计时,请逐项检查:
重入:
- 所有包含外部调用的函数都使用
nonReentrant - 遵循 CEI 模式——外部调用后不读取状态
- 状态转换期间不使用视图函数作为预言机
访问控制:
- 每个修改状态的函数都有明确的访问修饰符
- 修饰符确实会回滚,而不是静默放行
- 管理员权限最小化且有文档说明
输入与逻辑:
- 没有未经验证的任意
call/delegatecall - 不使用
tx.origin进行身份验证 - 对成对输入验证数组长度
- 不存在先除后乘导致的精度损失
代币处理:
- 所有 ERC20 操作都使用
SafeERC20 - 正确处理转账收费代币(检查余额差值)
- 不缓存重基代币的余额
- 拒绝零金额转账
价格与预言机:
- 不使用原始现货价格
- 检查价格是否过期(
updatedAt/answeredInRound) - 强制执行最低流动性门槛
- 设置价格偏差断路器
签名与加密:
- 检查
ecrecover结果是否为address(0) - 签名数据包含
chainId、nonce、msg.sender、deadline - 使用 OZ
ECDSA(强制执行 low-s) - 将 MerkleProof 叶节点绑定到
msg.sender
闪电贷防护:
- 治理:快照投票 + 持有期 + 时间锁
- 价格:使用 TWAP 或多预言机,而不是单区块现货价格
- 金库:设置最低首次存款额或使用虚拟份额(ERC4626)
代理与升级(EVMbench):
- UUPS
_authorizeUpgrade使用onlyOwner— [EVMbench/basin H-01] -
upgradeTo/upgradeToAndCall保留onlyProxy— [EVMbench/basin H-01] - 实现合约的构造函数调用
_disableInitializers()— [EVMbench/basin H-01] - 存储布局与升级兼容(存储间隙或 ERC-7201)— [EVMbench/basin H-01]
信任边界与可组合性(EVMbench):
- 路由器/注册表的中继调用会验证源金库/合约授权 — [EVMbench/noya H-08]
- 清算操作会验证抵押品的实际所有权 — [EVMbench/benddao]
- 闪电贷回调路径无法被滥用来突破信任边界 — [EVMbench/noya H-08]
- 多合约交互中不存在对中间状态的依赖 — [EVMbench/noya H-08]
状态排序(EVMbench):
- 计数器/ID 递增在外部调用前完成 — [EVMbench/phi H-06]
- ETH 退款在所有状态更新后执行 — [EVMbench/phi H-06]
- 创建函数中的自动操作(自动买入等)在完全初始化后执行 — [EVMbench/phi H-06]
按地址绕过状态限制:
- 审计所有针对多地址绕过的
mapping(address => ...)限制 - 钱包间转账路径会传递相关限制状态
- 状态传递使用
max(_lastTxTime[to], _lastTxTime[from]),而不是block.timestamp(可被滥用进行 griefing)或直接赋值(会覆盖并缩短限制时间)
基础设施:
- 审计第三方依赖(桥接代码、继承合约)
- 不存在仍可调用且带有管理员/铸造功能的弃用合约
- 所有金库和管理员钱包均使用多签
- 前端交易验证(calldata 与预期一致)
AI Agent 审计方法
来源:EVMbench(OpenAI/Paradigm,2026 年 2 月)——在 Detect/Patch/Exploit 模式下,针对来自 40 个 Code4rena 审计仓库的 120 个高严重性漏洞评估 AI Agent。
审计策略
- 覆盖优先于深度:扫描所有范围内的文件;不要在发现第一个漏洞后就停止 [EVMbench §5, p.10]
- 三阶段审计:检测(识别漏洞)-> 修补(编写修复方案)-> 利用(构建 PoC)[EVMbench §3.2, p.5]
- 增量输出:审计过程中持续记录发现,以保留进度 [EVMbench Appendix G, Fig.18, p.24]
- 系统性类别扫描:按漏洞类别(重入、访问控制、数值、预言机……)检查,而不是凭直觉 [EVMbench §3.1, p.4]
- 验证修复:修补后,确认原有测试仍能通过,且漏洞利用不再可行 [EVMbench §3.2.2, p.5]
高频漏洞模式(Code4rena 数据)
来源:EVMbench Table 4(p.17)——40 个审计仓库
- 缺少访问控制(可升级性、清算、管理员功能)——basin H-01、munchables、benddao
- 重入 + 状态顺序错误(在更新状态前退款)——phi H-06、noya H-08
- 闪电贷突破信任边界(利用路由器/注册表的信任传递)——noya H-08
- 签名重放/抢先交易(绕过检查点、重放会话签名)——sequence H-01、H-02
- 数值精度/舍入(联合曲线、微额提款)——abracadabra H-02、size H-02
关键发现
来源:EVMbench Paper §4.1(p.7)、Fig.7(p.10)、Fig.10(p.18)、Fig.11(p.19)
- 提供机制提示后,修补成功率从约 40% 跃升至约 94% [Fig.7]——Agent 知道如何修复,但难以发现漏洞
- 大多数漏洞只需 ≤5 行代码即可修复 [Fig.10, p.18]
- 大多数漏洞利用只需 1-3 笔交易 [Fig.11, p.19]
- 发现数量最接近实际漏洞数量的 Agent 得分最高(质量 > 数量)[Fig.5, p.8]
2021-2026 年安全事件速查
| 日期 | 项目 | 损失 | 攻击类型 | 根本原因 | 来源 |
|---|---|---|---|---|---|
| 2021 年 10 月 | Cream Finance | $130M | 闪电贷 + 预言机 | 通过减少供应量操纵 yUSD vault 价格 | rekt.news |
| 2025 年 2 月 | Bybit | $1.4B | UI 注入/供应链攻击 | Safe{Wallet} 的 JS 因开发人员设备遭入侵而被篡改 | NCC Group |
| 2025 年 3 月 | Abracadabra | $13M | 逻辑缺陷 | cauldron 清算中的状态跟踪错误 | Halborn |
| 2025 年 7 月 | GMX v1 | $42M | 重入 | Arbitrum 上 GLP 池的跨合约重入 | Halborn |
| 2025 年 9 月 | Bunni | $8.4M | 闪电贷 + 舍入 | 提款舍入方向错误,导致 44 次微额提款 | The Block |
| 2025 年 10 月 | Abracadabra #2 | $1.8M | 逻辑缺陷 | cook() 验证标志被重置,导致无抵押借入 MIM | Halborn |
| 2026 年 1 月 | Step Finance | $30M | 密钥泄露 | 设备遭入侵,导致金库钱包私钥被盗 | Halborn |
| 2026 年 1 月 | Truebit | $26.4M | 旧版合约 | Solidity 0.6.10 中 mint 定价的整数溢出 | CoinDesk |
| 2026 年 1 月 | SagaEVM | $7M | 供应链攻击/桥 | 继承自 Ethermint 的预编译桥漏洞 | The Block |