Back to Blog

リベスト・ファイナンスの脆弱性:リエントランシーだけではない

Code Auditing
March 31, 2022
8 min read

2022年3月27日、Ethereum上のステーキングDeFiプロジェクトであるRevest Financeが、ERC-1155のコールバックメカニズムにより攻撃を受け、約200万ドル相当のトークン(BLOCKS、ECO、LYXe、RENA)が盗難されました。私たちはまずこの攻撃を分析し、その夜(UTC+8)に分析結果をツイートしました。

実際、Twitterに投稿した時点では、Revest TokenVaultコントラクトの関数についてまだ疑問がありました。その機能を理解しようとコントラクトを調査しました。その後、さらに単純な方法で悪用可能であり、発生した攻撃と同様の甚大な損失を引き起こす可能性のある、もう一つの重大なゼロデイ脆弱性を発見しました。

その後、すぐにRevest Financeチームに連絡したところ、迅速に対応していただき、脆弱性に対する回避策を提案してくださいました。脆弱性がトリガーされないことを確認した後、このブログを公開することにしました。

このブログの後半は、Revest Financeのメカニズム、元のリエントランシー攻撃、そして新しいゼロデイ脆弱性の3つの部分で構成されます。

Revest Finance FNFTとは

Revest FinanceのFinancial Non-Fungible Token(FNFT)は、ロックされた資産の将来の権利のトラストレスな移転を可能にします。エントリーコントラクト(Revestコントラクト)は、基盤となる資産をロックしてFNFTをミントするための3つの異なるインターフェースを提供します。

  • mintTimeLock: 基盤となる資産は、一定期間後にアンロックされます。
  • mintValueLock: 基盤となる資産は、その価値が所定の値を超えたり下回ったりしたときにアンロックされます。
  • mintAddressLock: 基盤となる資産は、所定のアカウントによってアンロックされます。

Revestコントラクトは、基盤となる資産をロックおよびアンロックするために、他の3つのコントラクトを接続します。

  • FNFTHandler: ERC-1155トークンから継承しています。ロックごとにFNFTをインクリメントするfnftIdで新しいFNFTを作成します。ロックは、作成時に新しいFNFTの総供給量を規定します。FNFTは他の方法ではミントできませんが、基盤となる資産をアンロックするためにバーン(焼却)することができます。
  • LockManager: ロック作成時に各ロックのアンロック条件を記録し、アンロック時にロックがアンロック可能かどうかを決定します。
  • TokenVault: 基盤となる資産を受け取り、送信し、各FNFTのメタデータ(指定されたFNFTの価値など)を記録します。

FNFTミントプロセスを説明するために、mintAddressLockを例として取ります。

図1
図2

上記の2つの図は、FNFTがどのように作成、ミント、バーンされるかを説明しています。具体的には、ユーザーAが100 WETHをRevest Financeにロックし、fnftIdを1とする対応するFNFTを作成します。最後に、指定された受信者に指定されたシェアで100個の1-FNFTをミントします。

基盤となる資産がアンロックされると、1-FNFTはそれぞれ1 (*1e18) WETHを受け取るためにバーンできます。図2に示すように、ユーザーBは25個の1-FNFTをバーンして25 (* 1e18) WETHを引き出します。

さらに、RevestコントラクトはdepositAdditionalToFNFTという別のインターフェースを提供しており、これが次に説明する2つの脆弱性を引き起こします。

この関数の通常の利用方法を説明するために、まず以下の2つの図を使用します。

図3
図4

depositAdditionalToFNFT関数は、既存のロック(fnftIdで指定)にさらに基盤となる資産をロックします。合理的には(図3)、指定された数量が指定されたFNFTの総供給量と同じであることを要求し、追加された資産を各指定されたFNFTに均等に分配します。

それ以外の場合(図4)は、最新のfnftIdで新しいロックを作成し、指定された数量の古いFNFTをバーンして指定された数量の新しいFNFTをミントし、古いロックのdepositAmountと指定された金額の合計を新しいロックのdepositAmountとして記録します。これは以下のコードに示す通りです。

// Now, we transfer to the 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は、指定された1つのFNFTが引き出せる基盤となる資産の量を示すため、この操作は古いFNFTの指定された数量の価値を古いロックから新しいロックに転送します。

(指定数量が総供給量を超える場合は、トランザクションはリバートされます)

リエントランシー脆弱性とは

この部分では、リエントランシー攻撃がどのように機能するかを説明し、根本原因と修正方法について議論します。

図5
図6
図7

上記の3つの図は、リエントランシー攻撃の全体プロセスを基本的に説明しています。具体的には、攻撃者はまずゼロのRENAトークンをロックして、価値のない2つの1-FNFTをミントします。次に、攻撃者は再度ゼロのRENAトークンをロックしますが、価値のない360,000個の2-FNFTをミントします(現時点では)。最後のステップで、攻撃者はERC-1155トークン標準から継承したFNFTHandlerのコールバックメカニズムを介してRevestコントラクトのdepositAdditionalToFNFT関数に再エントリし、fnftIdが更新される前に、fnftIdが2のロックのdepositAmountを上書きします。その結果、攻撃者はdepositAmountが1e18の360,001個の2-FNFTを取得します。これは、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の繰り返しミントを許可しないため、システムが期待どおりに機能することを保証するための2つのチェックを追加し、システムの安全性を向上させることができます。

新しいゼロデイ脆弱性

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(Proof of Concept)を作成しました。以下の3つの図は、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);
    }
}

2つの脆弱なコントラクト(TokenVaultおよびFNFTHandler)は多くの重要な状態を格納しているため、プロジェクトは状態を移行せずにTokenVaultコントラクトおよびFNFTHandlerコントラクトを再デプロイすることはできません。この脆弱性によるさらなる攻撃を避けるために、プロジェクトは lite versionのRevestコントラクトを再デプロイし、より複雑な関数を無効にして、潜在的な攻撃者が利用できる表面積を減らしました。回避策を確認した後、lite 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などの著名な投資家から2回の資金調達で数千万米ドルを獲得しています。

公式ウェブサイト: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