Appearance
S1C3: Empty Contract?
1. 問題
コントラクトは etherscan 上で「空」と表示されます(検証済みソースコードなし)が、実際にはロジックを持っています。mintFlag() を呼び出して NFT を取得する必要があります。
2. 原因
コントラクトの mintFlag() 関数は、実際にはコンストラクタ内で自動的に呼び出されます。このチャレンジの核心は、コントラクトがデプロイ時点で目標を達成していることを理解し、攻撃者が同じコントラクトをデプロイして(コンストラクタ内で攻撃する)必要があることです。
3. 方案
攻撃用コントラクトをデプロイし、コンストラクタ内でターゲットコントラクトが必要とする状態を設定した後、ターゲットコントラクトの攻撃関数を呼び出します:
solidity
contract S1C3Solution {
constructor(address challenge) {
// Setup logic here
IChallenge(challenge).mintFlag();
}
}
4. 遭遇したトラップ
コンストラクタ攻撃のタイミング: mintFlag のチェックロジックは、コンストラクタ内とデプロイ後で実行環境が異なります。
5. トラップの原因
コントラクトのストレージ状態は、コンストラクタ実行中と実行後で異なります — block.timestamp などの一部の状態変数は、コンストラクタ実行中に予測可能です。
6. 解決方法
Foundry スクリプトを使用して攻撃用コントラクトをデプロイし、コンストラクタ内ですべてのロジックを完了させます。
7. 技術ポイント
| ポイント | 説明 |
|---|---|
| コンストラクタ攻撃 | Solidity コントラクトのコンストラクタはデプロイ時に自動実行され、ワンショット攻撃に利用可能 |
| デプロイ済み vs コンストラクタ | コントラクトはコンストラクタ内では特定のチェックを通過できるが、デプロイ後はできない(例:EXTCODESIZE がゼロであることに依存する場合) |