Wake Arena:AI驱动的审计服务

  • Ackee
  • 发布于 18小时前
  • 阅读 74

Wake Arena 是一个用于发现Solidity智能合约漏洞的服务,它通过多代理AI分析和图驱动推理实现。在历史审计竞赛中,Wake Arena 发现了95个高危漏洞中的43个,超越了Zellic的自动化扫描器和普通GPT-5。Wake Arena在审计工作流程中发现了关键漏洞和独特发现,并帮助客户优化代码和降低安全成本。

Wake Arena: 基于图驱动推理的多智能体 AI 审计

在审计竞赛和生产协议中进行基准测试

2025年12月:

Josef Gattermayer, Ph.D.1,2

Michal Převrátil1

Martin Veselý1

Andrei Shchapaniak1

Josef Bazal1

1 Ackee Blockchain

2 布拉格捷克理工大学


执行摘要

我们介绍 Wake Arena,一项通过多智能体 AI 分析和图驱动推理发现 Solidity 智能合约中漏洞的服务。

Wake Arena 在历史审计竞赛中发现了 95 个高危漏洞中的 43 个,超过了 Zellic 的自动化扫描器 (41/95) 和普通 GPT-5 (24/95)。 在 2025 年 11 月,实验性地集成到 Ackee 的 Lido、Printr 和 Everstake 手动审计工作流程中时,Wake Arena 发现了 26 个发现。

具体来说,Wake Arena 在 Printr 审计期间,发现了 5 个严重漏洞和 5 个人类审计员未发现的独特发现

此外,LUKSO 担任了设计合作伙伴,在开发过程中提供了宝贵的反馈。 在纯粹由 AI 驱动的审计中,Wake Arena 识别出 10 个发现(2 个高危,6 个中危,1 个低危,1 个警告),只有两个假阳性。 LUKSO 的回应和验证有助于提高服务的准确性和用户体验。

跨基准测试和生产审计的指标:

  • 发现了所有报告发现的 33% 和关键发现的 50%
  • 假阳性率低于 50%
  • 真阳性率高于 50%

与通用 LLM 包装器不同,Wake Arena 结合了多智能体 AI 推理、通过数据依赖和控制流图进行的图驱动分析,以及来自 200 多次审计(确保超过 1800 亿美元 TVL)的 LLM 定制静态分析。


背景和动机

Ackee Blockchain 已经进行了 200 多次智能合约审计,确保了 1800 多亿美元的 TVL(Lido、Aave、Axelar、Safe)。 随着用于代码分析的 AI 功能的进步,我们构建了 Wake Arena,以利用这些功能,同时保持较低的假阳性率。

Wake Arena 是一个多智能体 AI 系统,它将我们的私有检测器库(来自数十亿美元审计中的 87 个检测器)与深度 AI 驱动的安全推理相结合,像高级审计员一样导航数据依赖关系图。 LLM 定制的静态分析将深入的代码见解馈送到完整的 AI 驱动的审计流水线中,该流水线具有图驱动的推理和来自多年审计经验的上下文理解。

问题陈述

团队需要一种一致、强大的安全工具,可以在高级审计之前可靠地发现重要漏洞,从而帮助协议以更清晰的代码到达,并将审计时间用于深入的协议逻辑审查。 我们希望帮助团队减少对表面级别工具的依赖,同时认识到高质量的手动审计对于关键系统仍然至关重要。


Wake Arena 的与众不同之处

1. 多智能体 AI 系统

一个多步骤的提示流水线结合了:

  • 使用多智能体交叉检查进行高级推理和验证
  • 嵌入在提示中的高级审计员专业知识的深度上下文理解
  • 从编译到报告生成的完整 AI 驱动的审计流水线

2. 图驱动的推理

具有数据依赖和控制流图的 LLM 定制静态分析导航代码以查找:

  • 通过跟踪执行路径的特定于协议的逻辑问题
  • 通过价值流分析的数学漏洞
  • 模式匹配错过的跨函数依赖关系

示例: 在 Lend 协议中,Wake Arena 跟踪了 LendStorage.borrowWithInterest 中一个深度嵌套的错误如何通过 getHypotheticalAccountLiquidityCollateral 和其他视图函数影响 CoreRouterCrossChainRouter 逻辑,从而导致拒绝服务回滚和协议中不正确的会计。 对错误影响的跟踪是需要深入的基于图的推理的原因。

3. 经过实战检验的静态分析集成到 AI 工作流程中

LLM 定制静态分析将有关分析代码的深入见解馈送到 AI,以:

  • 提供代码中没有的其他信息作为文本

  • 引用来自不同位置的相关代码段

  • 让 AI 使用与人类审计员相同的上下文信息和工具执行分析

    • *

评估方法

我们通过两种不同的方法评估了 Wake Arena 的性能:

  1. 合成基准 — 与行业标准数据集进行比较
  2. 真实审计 — 集成到生产安全审计中

1. 合成基准性能

我们接受 Zellic 基准数据集作为行业标准:来自历史审计竞赛(Code4rena 和 Sherlock)的 14 个协议,具有公开可用的代码库和经过多位安全研究人员审查的已验证发现。

协议 Wake Arena Zellic 的自动化安全扫描器 V12 普通 GPT-5 总计
Basin 2/2 2/2 2/2 2
Blackhole 2/2 2/2 1/2 2
Burve 2/9 2/9 2/9 9
Crestal 1/1 1/1 1/1 1
DODO 2/5 2/5 1/5 5
Lambo.win 2/4 2/4 2/4 4
Lend 13/28 10/28 4/28 28
Mellow 2/6 2/6 1/6 6
Munchables 4/5 4/5 2/5 5
Notional Exponent 2/11 2/11 0/11 11
Phi 4/7 6/7 3/7 7
Superfluid 1/2 1/2 1/2 2
TraitForge 2/6 1/6 2/6 6
Virtuals 4/7 4/7 2/7 7
总计 43/95 41/95 24/95 95

注释:

¹ 我们使用了与 Zellic 相同的历史审计竞赛数据集。 使用来自存储库根目录的提示“执行广泛的深度 Solidity 智能合约安全分析”测试了普通 GPT-5,没有特殊指导。 Wake Arena 扫描以标准配置运行。 测试于 2025 年 11 月进行。

性能比较

Wake Arena 检测到 95 个高危漏洞中的 43 个,实现了最高的检测率:

  • Wake Arena: 43/95 (45.3%)

  • Zellic 的自动化安全扫描器 V12: 41/95 (43.2%)

  • 普通 GPT-5: 24/95 (25.3%)

    • *

2. 真实审计性能

在 2025 年 11 月,Wake Arena 扫描已集成到 Ackee Blockchain 的生产协议手动审计过程中。 与孤立的基准环境不同,生产审计涉及互连的合约、不完整的配置以及从关键到信息的完整严重性范围。

真实审计结果

客户 项目 交付 天数 AI 发现 / 所有发现 关键 警告 信息
Lido Stonks 2.0 2025 年 12 月 2 日 15 4 / 17 0 / 0 0 / 0 1 / 1 1 / 2 1 / 5 1 / 9
Everstake ETH2 批量存款合约 2025 年 11 月 14 日 2 1 / 2 0 / 0 0 / 0 0 / 0 0 / 0 0 / 0 1 / 2
Printr 协议 2025 年 10 月 24 日 9 10 / 23 0 / 3 0 / 1 0 / 1 2 / 5 2 / 7 6 / 6
Printr 协议 2025 年 10 月 1 日 23 11 / 37 5 / 7 0 / 3 1 / 4 2 / 5 2 / 8 1 / 10
总计 49 26 / 79 5 / 10 0 / 4 2 / 6 5 / 12 5 / 20 9 / 27

局限性

Wake Arena 是一款用于发现重要漏洞的强大工具,但它有局限性:

Wake Arena 擅长发现:

  • 访问控制和授权错误
  • 状态管理和会计错误
  • 跨链和跨合约逻辑问题
  • 重入和回调漏洞
  • 参数验证和输入处理

Wake Arena 可能会错过:

  • 需要深入数学分析的新型加密漏洞
  • 需要进行广泛经济建模的协议设计缺陷
  • 跨越多个合约和链下系统的极其复杂的业务逻辑
  • 没有类似历史模式的零日攻击向量

理想用例:

在高级审计之前使用 Wake Arena 来:

  • 尽早发现表面级别和中等深度的漏洞
  • 以更清晰的代码进行手动审计
  • 将审计员时间集中在深入的协议逻辑和设计问题上
  • 通过早期检测降低总体安全成本

Wake Arena 是对关键系统的高质量手动审计的补充,而不是替代。


如何使用 Wake Arena

Wake Arena 现已在 ackee.xyz/wake/arena 上提供

获得访问权限后,通过 3 个步骤扫描你的协议:

  1. 上传代码库: 连接 GitHub 存储库或上传文件
  2. AI 驱动的分析: 多智能体系统使用图驱动的推理进行分析
  3. 接收报告: 包含发现、严重性评级和补救指南的综合 PDF

定价: 入门级审计定价,报告在数小时而不是数月内交付。

基础计划: 用于扫描一个订阅下的多个项目的授权计划的管理面板。


附录

Wake Arena 在历史审计竞赛中的表现

以下所有发现均由 Wake Arena 独立发现,无需特殊提示或人为帮助。 每个协议扫描都通过了完整的 AI 驱动的审计流水线:编译、图驱动的分析、多智能体推理和报告生成。

Basin (Code4rena, 2024 年 7 月)

Wake Arena 发现了人类研究人员报告的所有 2 个高危问题。

[H-01] 升级端点上缺少所有者或角色门控会导致未经许可的升级

函数 upgradeToupgradeToAndCall 仅依赖 _authorizeUpgrade 进行门控,后者仅强制执行环境检查(委托调用上下文、Aquifer 映射和 UUPS proxiableUUID),但不通过所有者或任何角色限制调用者。 任何外部调用者都可以调用升级端点并将实现更改为满足环境检查的任何候选者,从而绕过治理。

[H-02] decodeWellData 检查 decimal0 两次,使 decimal1 为 0,并在 0 应默认为 18 时错误地缩放 token1

函数 decodeWellDatadecimal0 使用相同的 sentinel 检查两次,并且从不在默认为 18 之前检查 decimal1。 当 decimal1 编码为 0 以表示为“默认为 18”时,它仍然为 0。 getScaledReserves 中的下游缩放然后将 token 1 乘以 10 ** (18 - 0) = 10 ** 18,错误地缩放储备并破坏定价、储备解决方案和利率计算。


Blackhole (2025 年 5 月)

Wake Arena 发现了人类研究人员报告的所有 2 个高危问题。

[H-01] setRouter 反转了零地址检查,仅允许 router = address(0)

函数 setRouter 反转了零地址保护,要求新路由器为零地址 (require(_router == address(0), "ZA"))。 这会阻止所有者配置任何有效的路由器。 如果路由器为零,则诸如 IGenesisPool(_genesisPool).launch(router, MATURITY_TIME) 之类的调用将使用无效地址,从而导致失败。

[H-02] createGauge 允许不受信任的 _algebraEternalFarming,授予任意 ERC20 批准并启用对工厂持有的奖励 token 的盗窃

函数 createGauge 是外部可调用的,没有修饰符,并接受调用者提供的 farmingParam.algebraEternalFarming。 它将其转发到内部 createEternalFarming,后者在对其进行外部调用之前,无条件地向用户提供的 _algebraEternalFarming 授予 1e10 的 ERC20 批准。 因为 _algebraEternalFarming 未根据受信任的注册表进行验证,所以任何参与者都可以将其指向他们控制的任意合约,从而允许他们使用授予的津贴通过 transferFrom 从工厂中提取 token。


Burve (Sherlock, 2025 年 4 月)

Wake Arena 发现了人类研究人员报告的 9 个高危问题中的 2 个。

[H-03] commit 中的不正确净额计算会在提款超过存款时删除存款

assetsToWithdraw > assetsToDeposit 时,commit 净额计算分支会错误地将 assetsToDeposit 置零,然后从 assetsToWithdraw 中减去它。 结果,不发生净额计算:完全提款执行,而挂起的存款被删除。 因为存款和提款已经改变了内部份额会计,假设会发生净额计算,所以这会创建未支持的份额和持久的会计不匹配。

[H-06] 在 removeValueSingle 中用作税基的未初始化返回变量启用零费用提款并削弱滑点检查

函数 removeValueSingle 在分配变量之前,从返回变量 removedBalance 计算 realTax。 因为 Solidity 中的返回变量已初始化为零,所以在乘法时 removedBalance 等于 0,因此 realTax 始终为 0。 用户提取全部总额,而无需支付配置的税款,协议不累积任何收入,并且针对总额而不是税后金额评估 minReceive 滑点保护。


Crestal (Sherlock, 2025 年 3 月)

Wake Arena 发现了人类研究人员报告的唯一高危问题。

[H-01] 通过公共 payWithERC20 进行未经身份验证的津贴耗尽

合约 Payment 中的函数 payWithERC20 是公共的,并接受任意 fromAddresstoAddress。 它调用 token.safeTransferFrom(fromAddress, toAddress, amount),而无需对调用者进行身份验证、将 fromAddress 绑定到 msg.sender 或验证任何已签名的授权。 任何用户都可以触发 fromAddress 授予此合约的任何津贴的支出,并将资金重定向到任意 toAddress


DODO 跨链 DEX (Sherlock, 2025 年 6 月)

Wake Arena 发现了人类研究人员报告的 5 个高危问题中的 2 个。

[H-04] withdrawToNativeChain 中未绑定的 params.fromToken 允许通过 DODO mixSwap 排出任意 token

withdrawToNativeChain 中未绑定的 params.fromToken 允许合约在执行 _doMixSwap 时通过 DODOApprove 批准和花费其持有的任意 token。 批准金额源自调用者提供的 amount,而要批准的 token 来自调用者提供的 params.fromToken。 由于未强制 params.fromToken 等于传入的 zrc20,因此可以排出任何合约持有的余额。

[H-05] 通过 claimRefund 中的授权绕过进行非 EVM 退款盗窃

函数 claimRefund 中的授权错误地绑定到非 EVM 退款的 msg.sender。 对于 refundInfo.walletAddress.length != 20 的退款,代码设置 receiver = msg.sender,然后检查 require(bots[msg.sender] || msg.sender == receiver)。 因为 receiver 通过构造等于 msg.sender,所以 require 始终为任何调用者通过,从而使任何地址都可以申领非 EVM 退款。


Lambo.win (Code4rena, 2024 年 12 月)

Wake Arena 发现了人类研究人员报告的 4 个高危问题中的 2 个。

[H-01] ERC20 模式的 cashIn 通过 msg.value 进行铸造,从而实现未支持的铸造和零信用存款

即使底层资产是 ERC20 token,函数 cashIn 也会根据 msg.value 铸造虚拟 token。 在 ERC20 分支中,该函数从调用者处转移 amount ERC20 token,但铸造 msg.value 虚拟 token,从而创建两种故障模式:以 msg.value == 0 存入 ERC20 的用户收到 0 个虚拟 token,而他们的 ERC20 被锁定,并且攻击者可以发送 amount == 0 的 ETH 以接收未支持的虚拟 token,他们可以 cashOut 来耗尽其他人的 ERC20 存款。

[H-02] 由于可预测的下一个克隆地址,通过预先创建 Uniswap 对(PAIR_EXISTS)进行前端运行 DoS

函数 createLaunchPad 使用 Clones.clone(通过 CREATE)部署一个新的报价 token 克隆,然后立即调用 Uniswap V2 createPair。 因为基于 CREATE 的地址是从工厂的地址及其 nonce 派生的,所以观察者可以预测下一个克隆地址。 攻击者可以前端运行并为 (virtualLiquidityToken, predictedQuoteToken) 预先创建该对,从而导致受害者的 createLaunchPad 回滚并显示 PAIR_EXISTS


Lend (Sherlock, 2025 年 6 月)

Wake Arena 发现了人类研究人员报告的 28 个高危问题中的 13 个。

[H-01] claimLend 未能在授予后递减 lendAccrued,从而允许重复的奖励申领和 LEND 耗尽

函数 claimLend 转移应计 LEND,但从不在存储中减少记录的应计额。 在成功转移后,lendAccrued(account) 保持不变,从而允许每当路由器持有足够的 LEND 时重复申领相同的应计额。 存储端分配函数仅增加 lendAccrued; 授予后没有路径会递减或清除它。

[H-03] borrowWithInterest 会为合法的多方向头寸回滚(两个数组都已填充)

函数 borrowWithInterest 强制执行对于给定用户及其在链上的标的资产,只能填充 crossChainBorrowscrossChainCollaterals 中的一个。 对于涉及跨不同远程链上相同标的资产的相反方向的合法多方向头寸,此不变性不成立,从而导致偿还和会计流程中的拒绝服务。

[H-04] 抵押品在偿还之前被扣押; LiquidationSuccess 使用外部 lToken,从而阻止跨链清算

抵押品在抵押品链上被扣押,然后才确保偿还,并且后续的 LiquidationSuccess 处理程序使用外部 lToken 地址进行偿还。 在债务链上,liquidateCrossChain 计算扣押 token 并发送 CrossChainLiquidationExecute,而无需首先从清算人处托管或提取偿还资金。 在抵押品链上,_handleLiquidationExecute 会立即更新会计并减少借款人的抵押品,而无需保证偿还将成功,从而破坏跨链清算流程并永久取消跨链借款人状态的同步。

[H-07] Redeem 因使用预应计 exchangeRateStored 而少付; 剩余底层资产滞留在路由器中

函数 redeem 使用在调用市场的 redeem 之前读取的 exchangeRateStored 计算 expectedUnderlyingredeem 调用会累积利息并使用应计后利率,因此路由器收到的底层资产多于转发给用户的底层资产。 差额仍然卡在路由器中并随着时间的推移而累积。

[H-08] borrowWithInterest 排除目标链抵押品,清零跨链债务并阻止清算

函数 borrowWithInterest 未能包括目标链上的跨链债务,因为抵押品分支错误地要求 destEid == currentEidsrcEid == currentEid。 在真正的跨链借款中,借款源于链 A,债务位于链 B 上,destEid == currentEidsrcEid != currentEid,因此条件始终为假。 这种不正确的零余额会破坏下游逻辑,包括流动性计算和清算限额。

[H-09] Supply 使用过时的 exchangeRateStored 贷记 lToken,从而导致会计漂移和赎回 DoS

Supply 使用从铸造之前获得的 exchangeRateStored,然后使用过时的汇率贷记 mintTokens。 后续的铸造调用会累积利息并使用应计后的汇率,因此铸造给路由器的实际 lToken 少于贷记金额。 这会产生持续的会计盈余,最终导致赎回回滚。

[H-10] 非原子跨链清算在收集偿还之前扣押抵押品,从而实现无偿扣押

清算协议首先在抵押品链上扣押抵押品,然后尝试从债务链上的清算人处收取偿还款。 在扣押之前没有托管人 token,因此如果清算人无法或不愿支付,则偿还失败,而抵押品已被重新分配。

[H-18] borrowWithInterest 中目标链上的跨链债务计数不足和偿还 DoS

跨链债务在目标链上变得不可见,因为 borrowWithInterest 抵押品分支使用无法满足的谓词,该谓词要求 destEidsrcEid 都等于 currentEid。 在目标链上,跨链抵押品记录的 destEid == currentEidsrcEid 设置为原始链,因此 srcEid == currentEid 始终为假,并且循环从不添加任何金额。 这会导致在 getHypotheticalAccountLiquidityCollateral 等辅助函数中计入的债务不足,以及偿还路径 DoS,其中 CoreRouter.repayBorrowInternal 需要 borrowedAmount > 0,但 borrowWithInterest 会错误地返回 0。

[H-19] 清算偿还使用抵押品 seizeTokens 而不是 repayAmount

在扣押抵押品后,LiquidationSuccess 处理程序使用 payload.amount 偿还借款人,但该字段在 _executeLiquidationCore 期间设置为 seizeTokens(抵押品 lToken 单位)。 必须使用借入资产的标的资产单位中的 repayAmount 执行偿还,从而导致不正确的债务结算。

[H-21] 过期的来源链抵押品快照支持抵押不足的跨链借款

目标链借款处理程序信任在发送时在来源链上拍摄的抵押品价值快照。 在消息传输过程中,来源链抵押品上没有锁定。 借款人可以在发起跨链借款之后但在目标执行之前提取来源链抵押品,从而允许抵押不足或无抵押的借款。

[H-22] 清算有效性检查使用错误的单位和错误的行动模型,从而可以扣押健康的账户

清算验证器 _checkLiquidationValid 对抵押品市场中的额外借款进行建模,并将 payload.amount 作为 borrowAmount 传递。 在此流程中,payload.amount 是要扣押的 lToken 的数量,而不是以标的资产计价的借款金额。 这会混合单位并错误地夸大清偿能力检查的“借用”端,从而可以清算健康的账户。

[H-25] LiquidationSuccess 使用外部 lToken 和错误的 EID; 在扣押抵押品后,偿还永远不会执行

在扣押抵押品链上的抵押品后,路由器会将 LiquidationSuccess 消息发送回债务链。 接收处理程序 _handleLiquidationSuccess 尝试查找借款头寸并使用抵押品链 destlToken 和不匹配的端点 ID 偿还债务。 这会导致处理程序无法找到记录或在与未知 lToken 交互时回滚,从而使偿还未执行,而抵押品已被扣押。

[H-27] 由于零 borrowIndex 路径,首次借款人在借款中绕过每个用户的抵押品检查

在函数 borrow 中,合约计算包括新金额在内的借款和抵押品,但当 currentBorrow.borrowIndex == 0(首次借款人)时,然后将 borrowAmount 派生为零。 每个用户的抵押品检查 collateral >= borrowAmount 变为 collateral >= 0,始终通过,并允许新用户借用由路由器持有的其他用户的抵押品。


Mellow (Sherlock, 2025 年 7 月)

Wake Arena 发现了人类研究人员报告的 6 个高危问题中的 2 个。

[H-01] 阈值绕过:重复的签名者条目在 checkSignatures 中被视为不同

Consensus 多重签名验证器根据阈值计算提供的签名,但不强制每个签名都由唯一的签名者生成。 可以在签名数组中重复相同的签名者以满足任何阈值,从而将 k-of-N 策略降级为有效地 1-of-N,只要一个注册签名者愿意或受到威胁。

[H-04] 跨非基础资产报告的协议费用双重累积,因为时间戳仅针对基础资产更新

协议费用累积检查点按金库存储在 timestamps 中。 函数 calculateFee 无条件地为任何资产添加与 block.timestamp - timestamps[vault] 成比例的基于时间的协议费用,而函数 updateState 仅在 asset == baseAsset[vault] 时才提前检查点,否则会提前返回。 这允许在不同的非基础资产报告中多次收取相同的经过时间,直到基础资产报告最终更新时间戳,从而系统地过多地铸造协议费用份额。


Munchables (Code4rena, 2024 年 7 月)

Wake Arena 发现了人类研究人员报告的 5 个高危问题中的 4 个。

[H-01] 传输时缺少 plotId 更新会导致占用卡住和事件不一致

函数 transferToUnoccupiedPlot 更新旧图和新图的占用位图,但从不更新质押 token 的 toilerState.plotId 字段。 结果,合约在存储中保留过时的图 ID,而 plotOccupied 映射反映了新图。 当承租人稍后调用 unstakeMunchable 时,该函数会释放旧图 ID(该 ID 已经为空),从而使新图永久标记为已占用,并阻止在该图上进行进一步的租用。

[H-02] 无效图检查中的一位偏移允许在已移除的图上进行耕种

_farmPlots 中的无效图检测使用 _getNumPlots(landlord) < _toiler.plotId 而不是正确的 >= 比较,从而错过了相等的情况。 当房东减少图的数量时,plotId 等于新图数量的 toilers 应标记为无效,但当前 代码无法检测到它。 结果,最高移除索引上的质押 token 继续耕种,就像图仍然存在一样,从而导致承租人和房东的会计错误。

[H-04] 当在无效图上使用房东的 lastUpdated 时,_farmPlots 中的时间增量下溢会导致回滚并阻止用户操作

当质押 token 的 plotId 超过房东的可用图时,_farmPlots 替换 timestamp = plotMetadata[landlord].lastUpdated,然后将耕种增量计算为 timestamp - _toiler.lastToilDate。 如果 plotMetadata[landlord].lastUpdated 为零(从未初始化)或早于 _toiler.lastToilDate,则减法会在 Solidity 0.8 下溢并回滚整个交易。 因为 forceFarmPlots 修饰符在关键函数(stakeMunchableunstakeMunchabletransferToUnoccupiedPlot)中执行 _farmPlots,所以此回滚会阻止用户耕种、移动到有效的图,甚至取消 质押 - 有效地锁定资产,直到元数据更新为止。

[H-05] _farmPlots 中的脏标志永远不会清除,从而永久禁用受影响 token 的耕种

当质押 token 的 plotId 不再有效(可用图缩小)时,_farmPlots 设置 toilerState[tokenId].dirty = true 以表示一次性调整。 在后续调用中,检查 if (_toiler.dirty) continue; 完全跳过该 token 的耕种。 在调整后,没有任何代码路径可以清除脏标志,包括在 transferToUnoccupiedPlot 中,因此除非所有者完全取消质押并重新质押,否则 token 将不再累积 schnibbles。


Notional Exponent (Sherlock, 2025 年 7 月)

Wake Arena 发现了人类研究人员报告的 11 个高危问题中的 2 个。

[H-03] 批量范围中的一位偏移:包括先前的 batchId,从而实现跨请求资产的错误归属

函数 _finalizeWithdrawImplcanFinalizeWithdrawRequestinitialBatchIdfinalBatchId(包括 finalBatchId)进行迭代。 但是,在 initiateRedemption 之前捕获 initialBatchId,之后捕获 finalBatchId; 如果 batchId 在发起期间递增,则当前请求的 upxETH 位于 (initialBatchId + 1 .. finalBatchId) 中。 包括 initialBatchId 会扫描先前批次的余额,从而导致当前请求赎回属于较早请求的 upxETH。 [H-06] 由于 s_batchNonce 中的 16 位 nonce 溢出,导致大约 6.5 万个请求后的提款启动 DoS

提款请求标识符在高位打包了一个 16 位的 s_batchNonce,并在启动期间使用 ++s_batchNonce。在 Solidity 0.8+ 中,对 uint16 的算术运算会进行检查;一旦计数器达到 65535,下一次递增将恢复,从而永久拒绝通过此管理器启动进一步的提款。


Phi (Code4rena, 2024 年 10 月)

Wake Arena 发现了人工研究员报告的 7 个高危问题中的 4 个。

[H-01] 艺术品创建签名缺乏域分离,从而实现跨链重放

createArt 授权流程验证了 (uint256 expiresIn, string uri, bytes credData) 上的个人签名,而没有绑定到 block.chainidaddress(this)。如果配置了相同的 phiSignerAddress,则链 A 的有效艺术品创建签名可以在链 B 上重放,从而在链上创建意外的重复艺术品,并绕过每链的推广策略。

[H-02] createArt 签名未绑定 CreateConfig,从而允许参数劫持和收入重定向

工厂签名仅涵盖 (expiresIn, uri, credData),不绑定 CreateConfig 字段或调用者。任何拥有有效签名 payload 的一方都可以抢跑并提交带有任意 artistreceivermintFee 和 timing 参数的 createArt。攻击者通过 onlyArtCreator 修饰符获得持久控制权并重定向收入。第一次创建还会永久修复每个 cred 的 ERC1155 合约地址。

[H-05] 公共 helper _addCredIdPerAddress 允许任意修改每个用户的仓位元数据(恶意破坏/DoS)

函数 _addCredIdPerAddress 被声明为 public,没有访问控制,并接受任意 sender_ 地址。任何外部调用者都可以将任意 credId_ 值附加到另一个帐户的 _credIdsPerAddress 数组中,并覆盖其存储的索引映射。攻击者可以使用重复或不存在的条目来膨胀受害者的仓位数组,歪曲索引映射,并降低 getPositionsForCurator 中的分页和查看结果,同时还会设置不一致的状态,从而增加移除失败的可能性。

[H-05] 公共 _removeCredIdPerAddress 允许未经授权的删除和卖至零 DoS

函数 _removeCredIdPerAddress 被声明为 public,没有访问控制。任何外部调用者都可以从任何地址的仓位数组中删除任何 credId,从而使 _credIdsPerAddress 与其索引映射不同步。当合法用户稍后卖至零时,由于索引不匹配,合约将恢复,从而永久阻止该仓位的卖至零。

[H-06] 通过 _handleTrade buy 路径中的退款进行重入允许绕过 sell-lock

单笔交易流程仅在通过外部调用退还 excessPayment 后才更新 lastTradeTimestamp[credId_][curator_]。恶意合约可以在退款期间重新进入,并在时间戳更新之前立即调用 sellShareCred。锁定检查使用过时的时间戳,允许在购买后立即出售,并绕过冷却期。该函数缺少 nonReentrant 保护。


Superfluid (Sherlock, 2025 年 6 月)

Wake Arena 发现了人工研究员报告的 2 个高危问题中的 1 个。

[H-01] provideLiquidity 可以花费质押的 token(没有可用余额检查),从而导致重复计算和会计账目中断

函数 provideLiquidity 不强制要求 supAmount 受 locker 的可用(未质押)余额的限制。质押仅更新内部 _stakedBalance,而 token 仍然在此合约的地址中,因此 Uniswap 的仓位管理器可以在铸造 LP 仓位时提取质押的 token。这违反了不变式 FLUID.balanceOf(this) >= _stakedBalance,从而可以进行重复计算(相同的 token 会累积质押和 LP 奖励),并可能在以后中断会计账目和解锁流程。


TraitForge (Code4rena, 2024 年 7 月)

Wake Arena 发现了人工研究员报告的 6 个高危问题中的 2 个。

[H-01] 批量铸造循环使用全局 _tokenIds,从而在第 1 代上限后阻止 mintWithBudget

mintWithBudget while 条件将全局 token 计数器 _tokenIds 与每代限制 maxTokensPerGen 进行比较。由于 _tokenIds 在所有代中单调递增,因此在第一代铸造 maxTokensPerGen 个 token 后,条件 _tokenIds < maxTokensPerGen 将永远变为 false,从而阻止在后续代中进行任何进一步的批量铸造。

[H-02] 在空投开始之前销毁,让当前持有者减少初始铸币者的空投分配

burn(uint256 tokenId) 中,在空投尚未开始时,合约会从 initialOwners[tokenId] 中减去熵。initialOwners 在铸造时设置,并且永远不会在转移时更新。任何当前持有者或批准的 operator 都可以先销毁 token,然后再开始空投,并强制从原始铸币者的空投分配中扣除。


Virtuals (Code4rena, 2025 年 4 月)

Wake Arena 发现了人工研究员报告的 7 个高危问题中的 4 个。

[H-01] 无需许可的验证器注册会增加 sybil 集膨胀、基本评分操纵和基于 gas 的 DoS

函数 addValidator 是公开可调用的,并且缺乏访问控制,从而允许任何帐户为任何 virtualId 注册任意验证器。在调用时,addValidator 无条件地调用 _addValidator_initValidatorScore,这会将附加到每个 virtual 的验证器数组,并分配与 DAO 的提案计数相关的非零基本分数。这可以实现验证器集的 sybil 膨胀、通过非零基本分数向上操纵聚合验证器评分,以及 _validators[virtualId] 数组的无限增长——增加了消费者循环(如 totalUptimeScore)中的 gas 成本,并在下游流程中出现实际的 out-of-gas 回滚。

[H-03] updateImpact 中的未绑定 virtualId 允许跨角色影响和数据集评分操纵

函数 updateImpact 接受调用者控制的 virtualIdproposalId,并使用 _coreServices[virtualId][_cores[proposalId]] 计算基线服务,这两个参数之间没有绑定。合约不会持久保存从 proposalId 到其原始角色的任何映射,因此任何来电者都可以将受害 proposalId 与不相关的 virtualId 配对,以将成熟度与错误的角色上次服务或零进行比较。这会直接更改 _impacts[proposalId],并且当提案具有关联的数据集时,还会重写 _impacts[datasetId]_maturities[datasetId],从而破坏跨角色评分。

[H-04] 未检查的 parentId 允许跨 DAO 血统伪造和无限制的子项增长

铸造函数接受任意 parentId,并且仅强制执行 parentId != proposalId,然后写入链接并附加到父级的子项,而没有验证父级是否存在、是否属于同一虚拟角色,或者调用者是否有权修改父级的血统。这允许任何提议者伪造跨 DAO 血统,将子项附加到不存在的父项,并膨胀 _children[parentId] 以进行恶意破坏。攻击者可以使来自 DAO A 的 token 显示为 DAO B 铸造的 token 的子项,或者用数千个子项垃圾邮件发送一个流行的父项,从而破坏下游消费者的假设并使 getChildren(parentId) 对索引器来说变得繁重。

[H-06] promptMulti 可以转移到零地址或过时的 TBA,因为 prevAgentId 永远不会更新

promptMulti 循环将 prevAgentId 初始化为 0,将 agentTba 初始化为 address(0),但永远不会在循环内更新 prevAgentId。因此,当 agentId == 0 时,刷新条件 if (prevAgentId != agentId) 会失败,从而使 agentTba 保持不变。对于 agentId == 0 的第一个元素,agentTba 仍为 address(0),并且 token.safeTransferFrom(sender, agentTba, amounts[i]) 尝试转移到零地址,从而导致标准 ERC20 token 回滚。对于在非零 agentId 之后跟随的任何稍后 agentId == 0 的元素,来自上一个 agent 的过时 agentTba 会被重用,从而将资金错误地定向到错误的接收者。


致谢

感谢 Lido、Printr、Everstake 和 LUKSO 参与 Wake Arena 的生产验证。


访问

Wake Arena: ackee.xyz/wake/arena

请求访问


Ackee 区块链安全

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

0 条评论

请先 登录 后评论
Ackee
Ackee
Cybersecurity experts | We audit Ethereum and Solana | Creators of @WakeFramework , Solidity (Wake) & @TridentSolana | Educational partner of Solana Foundation