返回博客

Autheo Network、UNCX 遭黑客攻击,损失约387万 USD | BlockSec 周报

Code Auditing
2026年10月22日
阅读约 10 分钟
核心要点
  • 本报告涵盖 3 起重大安全事件,估计总损失约为 387万 USD。这些事件分别涉及私钥泄露、代币归属核算错误和钱包种子生成机制薄弱。

  • UNCX Network 的 Smart Token Vesting V2 事件影响了 Ethereum、BNB Chain、Base 和 Robinhood Chain 上的 10 种资产。存在缺陷的份额汇总计算混合了按不同代币与份额比率创建的归属批次,使攻击者得以提取约 80.7万 USD 的已变现或经转移价值。

  • 资金池核算必须保持每个批次的代币数量、份额基数和归属进度之间的对应关系。将不同批次统一按同一比率核算,可能使某个头寸从共享余额中超额提取,从而减少可用于兑付其他头寸的资产。

过去一周(2026年10月12日–2026年10月18日),本文聚焦以下 3 起重大安全事件,估计损失总计约 387万 USD。

日期 事件 类型 估计损失
2026年10月12日 Autheo Network 私钥泄露 约 176万 USD
2026年10月14日 UNCX Network 记账错误 约 80.7万 USD
2026年10月18日 Qubic Wallet 弱种子生成 约 130万 USD

损失数字是根据已实现价值估算的。

  • UNCX Network:本文详细分析这一事件,因为其聚合份额计算缺陷提供了本周最清晰的合约记账教训。

免费安全扫描

使用我们的内部自动化分析引擎快速开展安全检查。

免费扫描

本周焦点:UNCX Network

2026年10月14日,攻击者利用了 UNCX Network 在 Ethereum、BNB Chain、Base 和 Robinhood Chain 上的 Smart Token Vesting V2 合约。该事件涉及 11 笔已确认的资金抽取交易中的 10 种资产,已实现或经转移的价值约为 80.7609万 USD [1]。根本原因是聚合份额计算存在缺陷,将以不同代币与份额比率创建的归属期批次混在一起。这导致仓位级记录与全局份额供应量出现偏差,使攻击者控制的仓位得以提取超过攻击者投入量的代币。

背景

UNCX Network 是一家多链 DeFi 基础设施提供商,其 Smart Token Vesting V2 产品允许项目按照基于时间的归属计划锁定 ERC-20 代币。每项计划由一个归属 ID 表示,并记录代币、创建者、受益人、总量、已释放数量以及一个或多个解锁批次。允许追加存入的软锁定仓位在创建后可以接收更多批次,而其创建者可以取消尚未归属的部分。

同一代币的各仓位在 VestingManager 中共用一笔余额,协议使用份额来确定每个仓位对该余额的归属量。因此,其记账有两个相互关联的层面:

Global pool, per token
  create / topUp: receive tokens and mint shares
  release: convert releasable shares into tokens
  _totalTokenShares[token]: active shares across all positions

Position record, per vesting ID
  _depositedShares[id]: share basis assigned to the position
  totalAmount: token amount represented by its tranches
  released: shares already paid to the beneficiary

执行释放时,管理合约首先计算计划中已有多少部分归属。它使用 _depositedShares[vestingId] 将 totalAmount 的该归属比例换算为已归属份额,减去 released,并将结果称为 releasableShares。在下方公式中,tokenBalance 是管理合约当前持有的该计划所涉代币的 ERC-20 余额,由该代币的所有仓位共享;_totalTokenShares[token] 则是对应的全局有效份额供应量。代币支付量取决于两者的比率:

amount = releasableShares * tokenBalance / _totalTokenShares[token]

通过归属功能存入代币会同时增加代币余额和份额供应量。直接向管理合约转入 ERC-20 代币则只改变代币余额,因此会改变每份份额代表的代币数量。只有当每项生命周期操作都能使仓位记录与全局供应量保持一致时,这种份额模型才能支持池化仓位。

漏洞分析

受影响的 Ethereum VestingManager 位于 0xA98F...99F5,其中的聚合份额计算存在缺陷,可通过 release()、topUpVesting() 和 cancel() 加以利用。其他三个网络上也存在同样受影响的部署。

为便于比较状态变化,下文分析引入 D、R 和 V 作为简写。这些符号并未出现在合约代码中;下表将各符号映射到相应的合约变量或表达式。映射值分为两类数量:

符号 合约变量 / 表达式 数量类型 含义
D _depositedShares[vestingId] 份额数量 分配给该仓位所有已记录存入款项的累计份额基数
R schedule.released 份额数量 已向受益人支付的累计份额
- schedule.totalAmount 代币数量 该仓位当前各批次记录的代币总量
- vestedAmount 代币数量 当前时刻按照这些批次的计划已归属的 totalAmount 部分
V vestedShare 份额数量 对 D 应用单一混合代币归属比例计算出的累计已归属份额

在 release() 中,合约计算 releasableShares,将 schedule.released 增加相应数量,并从 _totalTokenShares[schedule.token] 中减去同一数量。它不会减少 _depositedShares[vestingId]。因此,释放后,该仓位在全局供应量中仅占有 D - R 份有效份额,尽管其存储的基数仍为 D。

function release(uint256 vestingId) external nonReentrant {
    ...
    uint256 releasableShares = _getReleasableShares(vestingId);
    uint256 balance = IERC20(schedule.token).balanceOf(address(this));
    uint256 amount =
        (releasableShares * balance) / _totalTokenShares[schedule.token];

    schedule.released += releasableShares;
    _totalTokenShares[schedule.token] -= releasableShares;
    IERC20(schedule.token).safeTransfer(msg.sender, amount);
}

cancel() 将单一混合归属比例应用于仓位的聚合份额基数。它首先通过 getVestedAmount(vestingId) 计算 vestedAmount,然后将以代币数量表示的已归属比例换算成份额,得到 V = (vestedAmount * D) / totalAmount。最后,该函数将 D - V 视为该仓位可移除的未归属份额。V 是累计值,并非先前支付后剩余的已归属份额。

function cancel(uint256 vestingId) external nonReentrant {
    ...
    uint256 vestedAmount = getVestedAmount(vestingId);
    uint256 remainingAmount = schedule.totalAmount - vestedAmount;

    uint256 vestedShare =
        vestedAmount * _depositedShares[vestingId] / schedule.totalAmount;
    uint256 sharesToRemove =
        _depositedShares[vestingId] - vestedShare;
    _totalTokenShares[schedule.token] -= sharesToRemove;

    _depositedShares[vestingId] = vestedShare;
    schedule.totalAmount = vestedAmount;
    schedule.cancelled = true;

    IERC20(schedule.token).safeTransfer(schedule.creator, remainingAmount);
}

缺陷就在于混合计算本身。每个批次都有各自的代币数量、归属进度,以及按添加该批次时生效的资金池比率铸造的份额数量。因此,应分别计算每个批次的已归属份额,再将其相加。但合约先汇总代币数量和份额基数,再将单一归属比例应用于合并后的仓位,因为它只存储一个 D 和一个 totalAmount。只有各批次具有相同的每代币份额比率或相同的归属进度时,两种计算方法才等价。在追加存入前直接转入代币会改变资金池比率,因此新批次每单位代币获得的份额远少于原批次。此时,对两个批次应用单一混合归属比例,可能算出不再代表其合计已归属份额的 V。

由于 R 已从仓位的累计已归属份额中支付,一项账目一致的计划必须满足 R <= V。违反这一不等式就是混合计算缺陷的直接表现。代码没有为仓位单独维护有效份额余额,而是直接从全局 _totalTokenShares 中减去 D - V。假设其他仓位贡献了 1000 份份额,而该仓位的数值为 D = 100 和 R = 80。取消前,全局供应量包含 1,000 + (D - R) = 1,020 份份额。如果混合计算得出 V = 60,cancel() 就会减去 D - V = 40,使全局份额仅剩 980 份,比其他仓位贡献的 1000 份少 20 份。如果全局供应量仅包含该仓位的 20 份有效份额,减去 40 就会发生下溢并导致交易回滚;只有共享资金池中包含其他仓位贡献的份额,这笔超额扣减才会成功。随后,函数存储 _depositedShares[vestingId] = 60,而 schedule.released 仍为 80,使仓位记录处于不可能成立的状态 D < R。

代码既不强制满足 R <= V,也不将 sharesToRemove 限制在该仓位的有效份额以内。因此,取消操作可能扣减已不属于全局供应量的历史份额。与此同时,它直接以代币单位转出 totalAmount - vestedAmount,而不通过资金池的份额比率换算退款。取消操作本身不会产生超额支付;它只是将全局份额供应量降至各仓位记录的有效份额总和之下,为后续超额赎回创造条件。

攻击分析

以下分析以一笔有代表性的 Ethereum 交易 0x352065...c23823 为例。攻击合约在这笔交易中针对五种代币执行了相同的核心步骤,并对每种代币使用闪电流动性。

  • 步骤 1:攻击者创建了一个立即归属的小仓位 #5058,以及两个规模大得多、立即归属且允许追加存入的软锁定仓位 #5059 和 #5060。小仓位被保留用于最后提取,而大仓位提供了破坏全局记账所需的历史份额记录。

  • 步骤 2:攻击者释放了两个大仓位。在最初接近 1:1 的资金池比率下,每次释放返还的数量都约等于各自的净存入量。相应份额从 _totalTokenShares 中移除,但原始数值仍保留在仓位 #5059 和 #5060 的 _depositedShares 记录中,仅在各计划单独的 released 字段中记为已释放。

  • 步骤 3:攻击者直接向 VestingManager 转入代币。这恢复了代币余额,却没有恢复已释放的份额,因此每份剩余份额代表的代币数量大幅上升。

  • 步骤 4:攻击者向已释放的两个大仓位追加存入。由于追加存入按新近升高的每份份额代币数量定价,大额代币存入仅铸造了少量新份额。此时,这些仓位同时包含庞大的过时历史基数和少量有效份额贡献。

  • 步骤 5:攻击者取消了两个已追加存入的仓位。每次取消操作都将单一混合归属比例应用于聚合后的历史存入份额。重新计算的 vestedShare 低于已释放份额,因此 sharesToRemove 超过了该仓位的有效贡献。尽管每个仓位在追加存入时只增加了少量有效份额,全局供应量却因每个仓位而减少了约 5.0e25 份虚增份额。

  • 步骤 6:在分母被严重低估后,攻击者释放了保留的小仓位。在所举的代币实例中,约 5.73e22 个原始单位的净存入量提取了约 1.07e26 个原始单位,约为存入量的 1,873 倍。攻击者利用扭曲后的比率重复创建和释放仓位的循环,并偿还了闪电流动性。

官方事件报告在 11 笔已确认的资金抽取交易中发现了相同模式。部分变体以原子方式完成,其他变体则在一笔关联交易中执行最终释放。UNCX 在剔除攻击者本金、临时闪电交易量和已返还资产后,根据已实现或经转移的收益计算出约 80.7609万 USD 的数字 [1]。

开始使用 Phalcon Explorer

深入分析交易,明智采取行动

立即免费试用

结论

根本原因是聚合份额记账存在缺陷。协议将以不同代币与份额比率创建的批次合并,再将单一归属比例应用于其聚合份额基数。这错误计算了累计已归属份额,使一个仓位能够移除超过其仍在贡献的份额,并导致仓位级记录与全局份额供应量出现偏差。攻击者利用被低估的全局供应量,从共享余额中提取了原本仍需用于兑付其他归属仓位的代币。

对于允许后续存入且份额比率会发生变化的记账模型,应保留每个批次的代币数量、份额基数和归属进度,而不是按单一比率混合计算。模型还应确保累计支付永不超过累计已归属份额,并确保仓位移除的份额不超过其有效贡献。

参考资料

[1] UNCX Network Smart Token Vesting V2 事件报告

Web3 最佳安全审计机构

上线前验证设计、代码和业务逻辑

订阅最新动态
损失约54.2万美元:MakerDaoBot 漏洞利用事件|BlockSec 周报
Security Insights

损失约54.2万美元:MakerDaoBot 漏洞利用事件|BlockSec 周报

本报告涵盖2026/10/05至2026/10/11以太坊上的1起安全事件,估计损失约54.2万美元。攻击合约部署恶意适配器,并将其传入缺乏访问控制的MakerDaoBot函数,使机器人授予该适配器操作其内部MakerDAO余额的权限。适配器结算了4笔旧版ETH-A拍卖,将200单位ETH-A抵押品兑换为WETH;攻击合约随后将其解包,并向攻击者转出200 ETH。

损失约4.18亿美元:Bitget、NEAR Intents遭利用攻击 | BlockSec Weekly
Security Insights

损失约4.18亿美元:Bitget、NEAR Intents遭利用攻击 | BlockSec Weekly

本双周安全报告记录了2026年9月21日至10月4日期间发生的八起事件,涉及以太坊、BNB Chain、Solana、比特币、波场、XRP Ledger、Zcash、Avalanche、NEAR等网络,损失约4.184亿美元。详细分析涵盖Bitget因第三方安全产品漏洞损失3.875亿美元,以及NEAR Intents因退款验证缺陷和状态回滚缺失损失387万美元。

Bitget 3.875亿美元链下漏洞事件:不止于密钥与合约
Security Insights

Bitget 3.875亿美元链下漏洞事件:不止于密钥与合约

2026年9月24日,攻击者利用第三方安全产品漏洞,获取内部凭证并伪造提现指令,导致Bitget部分运营钱包资金转出约3.875亿美元,涉及以太坊、其他EVM网络、XRP Ledger、Zcash和TRON,私钥及冷钱包未受影响。本文梳理事件路径与资金流向,分析资产快速转换及生态恢复应对,提出机构纵深防御体系,并说明授权区块链渗透测试如何验证跨层安全假设。

Web3 最佳安全审计方

在上线之前验证设计、代码与业务逻辑,对标业内最高安全标准。

BlockSec 审计