Back to Blog

Revest Finance 漏洞:不只是重入攻击

Code Auditing
March 31, 2022
8 min read

2022年3月27日,以太坊上的质押DeFi项目Revest Finance因ERC-1155回调机制遭受攻击,导致价值约200万美元的代币(具体为BLOCKS、ECO、LYXe和RENA)被盗。我们第一时间分析了此次攻击,并在当晚(UTC+8)发布了分析推文。

事实上,在发布推文时,我们对Revest TokenVault合约中的某个函数仍存有疑虑。我们深入研究了该合约以理解其功能。之后,我们发现了一个** otro critical zero-day vulnerability**,可以通过远为简单的方式进行利用,并造成与已发生攻击相同的巨大损失

随后,我们立即联系了Revest Finance团队,他们迅速回应并提出了一个针对该漏洞的临时解决方案。在确认该漏洞无法被触发后,我们决定发布这篇博客。

本博客的后续内容将分为三个部分:Revest Finance的机制、原始重入攻击以及新的零日漏洞

Revest Finance FNFT是什么?

Revest Finance的金融非同质化代币(FNFT)使得锁定资产的未来权利可以进行无需信任的转让。入口合约(Revest 合约)提供了三种不同的接口来通过锁定底层资产来铸造FNFT:

  • mintTimeLock:底层资产将在一段时间后解锁。
  • mintValueLock:当底层资产的价值高于或低于规定值时,它将被解锁。
  • mintAddressLock:底层资产将被指定的账户解锁。

Revest合约连接了其他三个合约来锁定和解锁底层资产。

  • FNFTHandler:继承自ERC-1155代币。它为每一次锁定创建一个带有递增fnftId的新FNFT。锁定在创建时规定了新FNFT的总供应量。FNFT不能以其他方式铸造,但可以被销毁以解锁底层资产。

  • LockManager:在创建时记录每个锁定的解锁条件,并在解锁时决定锁定是否可以被解锁。

  • TokenVault:接收和发送底层资产,并记录每个FNFT的元数据,例如指定FNFT的价值。

我们以mintAddressLock为例来说明铸造FNFT的过程。

图 1
图 2

以上两图描述了FNFT的创建、铸造和销毁过程。 具体来说,用户A将100 WETH锁定到Revest Finance,创建了相应的FNFT,fnftId为1。最终,它以指定的份额将100个1-FNFT铸造给指定的接收者。

请注意,一旦底层资产被解锁,那么每个1-FNFT都可以被销毁以接收一(*1e18)个WETH。如图2所示,用户B通过销毁25个1-FNFT提取了25(*1e18)个WETH。

此外,Revest合约还提供了另一个名为depositAdditionalToFNFT的接口,该接口存在两个漏洞,将在下文中讨论。

我们首先使用以下两图来描述此函数的正常用法。

图 3
图 4

depositAdditionalToFNFT函数向现有的锁定(由fnftId指定)添加更多的底层资产。合理地(图3),它要求指定的数量与指定FNFT的总供应量相同,然后将添加的资产均匀分配给每个指定的FNFT。

否则(图4),它会创建一个带有最新fnftId的新锁定,销毁指定数量的旧FNFT并铸造指定数量的新FNFT,然后将新锁定的depositAmount记录为旧锁定depositAmount与指定金额的总和,如下面的代码所示。

// 现在,我们转移到Token Vault
if(fnft.asset != address(0)){
    IERC20(fnft.asset).safeTransferFrom(_msgSender(), vault, quantity * amount);
}

ITokenVault(vault).handleMultipleDeposits(fnftId, newFNFTId, fnft.depositAmount + amount);

emit FNFTAddionalDeposited(_msgSender(), newFNFTId, quantity, amount);

由于TokenVault合约中记录的depositAmount表示一个指定FNFT可以提取的底层资产量,该操作将指定数量的旧FNFT的价值从旧锁定转移到新锁定。

(指定数量大于总供应量将回滚交易)

重入漏洞是什么?

在本节中,我们将说明重入攻击是如何工作的,并讨论根本原因和修复方法。

图 5
图 6
图 7

以上三图基本描述了重入攻击的整个过程。具体来说,攻击者首先锁定零RENA代币以铸造2个无价值的1-FNFT。其次,攻击者再次锁定零RENA代币,但铸造了360,000个同样无价值(目前)的2-FNFT。在最后一步,攻击者通过继承自ERC-1155代币标准的FNFTHandler的回调机制,重新进入Revest合约的depositAdditionalToFNFT函数,该函数在更新fnftId之前,将fnftId为2的锁定的depositAmount覆盖。结果,攻击者获得了360,001个2-FNFT,其depositAmount为1e18,这意味着他可以从TokenVault合约中提取360,001 * 1e18 RENA。此外,唯一成本是1e18 RENA。

修复方法

Revest Finance的代码完全符合经典的重入模式:使用fnftId -> 通过回调机制进行外部调用 -> 更新fnftId。因此,修复问题的最直接方法是打破这种模式。修复后的代码如下所示:

function mint(
    address account, 
    uint id, 
    uint amount, 
    bytes memory data
) external override onlyRevestController {
    require(amount > 0, "Invalid amount");
    require(supply[id] == 0, "Repeated mint for the same FNFT");
    supply[id] += amount;
    fnftsCreated += 1;
    _mint(account, id, amount, data);
}

首先,它将更新操作移到外部调用(_mint)之前,这可以避免攻击。其次,由于系统不允许铸造零FNFT和重复铸造同一FNFT,它添加了两个检查以确保系统按预期工作,从而提高系统的安全性。

新的零日漏洞

在分析Revest Finance的代码时,TokenVault合约中的handleMultipleDeposits函数总是让我们感到困惑,其代码如下所示。

function handleMultipleDeposits(
    uint fnftId,
    uint newFNFTId,
    uint amount
) external override onlyRevestController {
    require(amount >= fnfts[fnftId].depositAmount, 'E003');
    IRevest.FNFTConfig storage config = fnfts[fnftId];
    config.depositAmount = amount;
    mapFNFTToToken(fnftId, config);
    if(newFNFTId != 0) {
        mapFNFTToToken(newFNFTId, config);
    }
}

在调用depositAdditionalToFNFT函数时,handleMultipleDeposits函数会更改旧锁定的depositAmount或记录新锁定的depositAmount。当newFNFTId为零时,它不记录新锁定的depositAmount,因为这是一个向现有锁定添加额外资产的操作。

根据常识,当newFNFTId不为零时,它只记录新锁定的depositAmount,而不更改旧锁定的depositAmount。然而,代码告诉我们,它不仅记录新锁定的depositAmount,还更改了旧锁定的depositAmount

我们认为这是一个严重的零日逻辑漏洞,并编写了一个PoC来验证它。以下三图描述了PoC的工作原理。

图 8
图 9
图 10

具体来说,攻击者首先锁定零RENA来铸造360,000个1-FNFT。之后,攻击者直接调用depositAdditionalToFNFT函数来创建一个新的锁定。由于逻辑错误,TokenVault合约将旧锁定的depositAmount错误地从零更改为1e18。结果,攻击者获得了价值359,999 RENA的359,999个1-FNFT。显然,PoC比实际的重入攻击要简单得多。

修复漏洞的临时解决方案

这是一个逻辑错误,我们建议使用以下代码进行修复。

function handleMultipleDeposits(
    uint fnftId,
    uint newFNFTId,
    uint amount
) external override onlyRevestController {
    require(amount >= fnfts[fnftId].depositAmount, 'E003');
    IRevest.FNFTConfig memory config = fnfts[fnftId];
    config.depositAmount = amount;
    if(newFNFTId != 0) {
        mapFNFTToToken(newFNFTId, config);
    } else {
        mapFNFTToToken(fnftId, config);
    }
}

由于两个易受攻击的合约:TokenVaultFNFTHandler存储了大量关键状态,项目无法在不迁移状态的情况下重新部署TokenVault合约和FNFTHandler合约。为了避免该漏洞遭受进一步攻击,项目重新部署了Revest合约的精简版本,禁用了更复杂的功能,以减少潜在攻击者的攻击面。在检查了临时解决方案后,我们认为精简版的Revest合约可以缓解本博客中提到的可能攻击。

启示

确保DeFi项目的安全并非易事。除了代码审计,我们认为社区应该采取主动措施来监控项目状态,并在攻击发生之前就阻止它

关于BlockSec

BlockSec是一家领先的区块链安全公司,成立于2021年,由一群全球知名的安全专家组成。公司致力于提高新兴Web3世界的安全性和可用性,以促进其大规模采用。为此,BlockSec提供智能合约和EVM链安全审计服务,用于安全开发和主动阻止威胁的Phalcon平台,用于资金追踪和调查的MetaSleuth平台,以及用于Web3构建者在加密世界高效冲浪的MetaDock扩展。

迄今为止,公司已为MetaMask、Uniswap Foundation、Compound、Forta和PancakeSwap等300多家知名客户提供服务,并在两轮融资中从Matrix Partners、Vitalbridge Capital和Fenbushi Capital等领先投资者那里获得了数千万美元的投资。

官方网站:https://blocksec.com/

官方Twitter账号:https://twitter.com/BlockSecTeam

Sign up for the latest updates
Newsletter - April 2026
Security Insights

Newsletter - April 2026

In April 2026, the DeFi ecosystem experienced three major security incidents. KelpDAO lost ~$290M due to an insecure 1-of-1 DVN bridge configuration exploited via RPC infrastructure compromise, Drift Protocol suffered ~$285M from a multisig governance takeover leveraging Solana's durable nonce mechanism, and Rhea Finance incurred ~$18.4M following a business logic flaw in its margin-trading module that allowed circular swap path manipulatio

~$7.04M Lost: GiddyDefi, Volo Vault & More | BlockSec Weekly
Security Insights

~$7.04M Lost: GiddyDefi, Volo Vault & More | BlockSec Weekly

This BlockSec weekly security report covers eight attack incidents detected between April 20 and April 26, 2026, across Ethereum, Avalanche, Sui, Base, HyperLiquid, and MegaETH, with total estimated losses of approximately $7.04M. The highlighted incident is the $1.3M GiddyDefi exploit, where the attacker did not break any cryptography or use a flash loan but simply replayed an existing on-chain EIP-712 signature with the unsigned `aggregator` and `fromToken` fields swapped out for a malicious contract, demonstrating how partial signature coverage turns any historical signature into a generic permit. Other incidents include a $3.5M Volo Vault operator key compromise on Sui, a $1.5M Purrlend privileged-role takeover, a $413K SingularityFinance oracle misconfiguration, a $142.7K Scallop cross-pool index injection, a $72.35K Kipseli Router decimal mismatch, a $50.7K REVLoans (Juicebox) accounting pollution, and a $64K Custom Rebalancer arbitrary-call exploit.

Weekly Web3 Security Incident Roundup | Apr 13 – Apr 19, 2026
Security Insights

Weekly Web3 Security Incident Roundup | Apr 13 – Apr 19, 2026

This BlockSec weekly security report covers four attack incidents detected between April 13 and April 19, 2026, across multiple chains such as Ethereum, Unichain, Arbitrum, and NEAR, with total estimated losses of approximately $310M. The highlighted incident is the $290M KelpDAO rsETH bridge exploit, where an attacker poisoned the RPC infrastructure of the sole LayerZero DVN to fabricate a cross-chain message, triggering a cascading WETH freeze across five chains and an Arbitrum Security Council forced state transition that raises questions about the actual trust boundaries of decentralized systems. Other incidents include a $242K MMR proof forgery on Hyperbridge, a $1.5M signed integer abuse on Dango, and an $18.4M circular swap path exploit on Rhea Finance's Burrowland protocol.

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit