Appearance
激震!「Shards NFTマーケットプレイス」に潜む、百万USDCの罠とDVT回収の謎
ブロックチェーンとNFTの世界は常に進化を遂げていますが、その革新の裏には、巧妙に隠された脆弱性が潜んでいることも少なくありません。「Damn Vulnerable DeFi」チャレンジから登場した「Shards NFTマーケットプレイス」は、まさにそんなスリリングなシナリオを提供します。今回は、この画期的なマーケットプレイスに隠された謎を解き明かし、その深淵を覗いてみましょう。
「Shards」とは何か?分散型NFT取引の新境地
「Shards NFTマーケットプレイス」は、その名の通り、非常に価値あるNFT(Damn Valuable NFTs, DVNs)を分割して取引できる、パーミッションレスなスマートコントラクトです。驚くべきことに、これらのNFTは「シャード(断片)」と呼ばれるERC1155トークンとして提供され、買い手はこれらのシャードを購入することができます。売主への支払いは、NFT全体が売却された時点で初めて行われる仕組みです。
マーケットプレイスは、売主から1%の「Damn Valuable Token(DVT)」手数料を徴収します。この手数料は安全なオンチェーンボルトに保管され、さらにDVTステーキングシステムと連携しています。
しかし、そこに異変が起きています。誰かが1つのNFTを「100万USDC」という破格の価格で売りに出しているのです。これは単なる高額な取引なのでしょうか?それとも、何か裏があるのでしょうか?
プレイヤーとしてのあなたの使命は、「DVTを一切持たない状態から、たった1回のトランザクションで可能な限りの資金を救出し、指定されたリカバリーアカウントに預けること」です。
巧妙な契約設計:ShardsNFTMarketplaceのメカニズム
この挑戦を理解するには、核となるスマートコントラクトの動作を深く掘り下げる必要があります。
1. openOffer (オファー開設) 売主はNFTを預け、分割数(totalShards)と総価格(price、USDC換算)を設定してオファーを開設します。ここで注目すべきは、売主は自身が保有するDVTから、マーケットプレイスに1%の手数料を支払う点です。この手数料はマーケットプレイス契約のDVT残高として蓄積されます。
2. fill (購入) 買い手はシャードを購入し、DVTで支払います。支払い額はUSDC価格と現在のDVT/USDCレートに基づいて算出されます。買い手からのDVTはマーケットプレイス契約に送金されます。オファーのシャードが全て売却されると、マーケットプレイスは売主にNFT売却代金を支払います。
3. cancel (キャンセル) 買い手は購入後、一定期間内に購入をキャンセルできます。キャンセルが実行されると、マーケットプレイスは買い手にDVTを返金します。この返金は、マーケットプレイス契約が保有するDVT残高から行われます。
4. ShardsFeeVault (手数料ボルト) マーケットプレイスに蓄積されたDVT手数料は、オーナーの操作によりこのボルトに送金され、必要に応じてステーキングされます。
鍵となる脆弱性:DVTトークンの非標準的挙動 (推測)
このチャレンジの核心は、「DVTを一切持たないプレイヤーが、どのようにしてfill関数を呼び出し、マーケットプレイス内の資金を盗み出すか」という点にあります。通常のERC20トークンでは、transferFrom関数を呼び出すには、呼び出し元がトークンを保有しているか、事前にapproveされている必要があります。しかし、プレイヤーはDVTを持っていません。
ここで、DamnValuableTokenというトークン自体が、このチャレンジの肝となる「非標準的な挙動」を持っていると推測されます。具体的には、ShardsNFTMarketplaceコントラクト内のfill関数で呼ばれるpaymentToken.transferFrom(msg.sender, address(this), amount)が、プレイヤーがDVTを保有していなくても、あるいはマーケットプレイスがプレイヤーにDVT利用を承認していなくても、なぜか実行可能であるという可能性です。
もしこれが事実であれば、プレイヤーは実質的に「無料で」シャードを購入できることになります。そして、これが資金回収への道を開きます。
攻撃シナリオ:単一トランザクションでのDVT回収
攻撃は、次のようなシーケンスで実行されます。
- 攻撃者コントラクトのデプロイ: プレイヤーは、攻撃ロジックを含むコントラクト(
MyContract)をデプロイします。このコントラクトが、以降の操作のmsg.senderとなります。 - 「擬似的な購入」の実行 (
fill):MyContractは、マーケットプレイスのfill関数を繰り返し呼び出します。DVTトークンの非標準的な挙動により、DVT残高を持たないにもかかわらず、fillが成功すると仮定します。この操作により、マーケットプレイスの内部的なシャード在庫が減少し、同時に購入記録が作成されます。 - 即座の「キャンセル」実行 (
cancel):MyContractは、先ほど作成した購入を直ちにcancel関数でキャンセルします。cancel関数は、マーケットプレイスが保有するDVT残高から、買い手(MyContract)に返金を行います。 - 資金の流出: この「無料で買う→(マーケットプレイスの残高から)返金を受ける」サイクルを繰り返すことで、
MyContractはマーケットプレイス契約内に蓄積されていたDVT(特に、売主が支払った手数料)を効率的に吸い上げることができます。 - リカバリーアカウントへの送金: 最終的に、
MyContractは吸い上げたDVTをすべて指定されたリカバリーアカウントに送金し、ミッション完了となります。
この一連の操作は、単一のトランザクション内で実行される必要があります。これは、攻撃者コントラクトのコンストラクタ内で全てのロジックを完結させることで達成されます。
まとめ:監査の重要性と隠れた危険性
「Shards NFTマーケットプレイス」チャレンジは、NFTの分割取引という魅力的なコンセプトの裏に、DVTトークンの実装における潜在的な欠陥を巧妙に隠しています。外部のコントラクトとやり取りする際、特にカスタムトークンを扱う場合には、そのトークンの挙動が標準仕様と異なる可能性を常に考慮し、徹底的なセキュリティ監査を行うことの重要性を強く示唆しています。
一見価値ある「Damn Valuable Token」も、その内部に思わぬ落とし穴が潜んでいる可能性があるのです。
このチャレンジは、DeFiプロトコル開発者、セキュリティ研究者、そしてスマートコントラクト監査人にとって、示唆に富む貴重な学習機会となるでしょう。あなたのコードは本当に安全ですか?