Appearance
S1C2: Just Call Me Maybe
1. 問題
mintFlag(bytes32 key) 関数を呼び出す必要があります。key は keccak256(abi.encodePacked(msg.sender, address(this))) と等しくなければなりません。
2. 原因
コントラクトはシンプルな認証方式を使用しています:key は呼び出し元アドレスとコントラクトアドレスのハッシュで構成されます。呼び出し元は自分のアドレスを偽装できないため、key を正しく計算すれば通過できます。
3. 方案
オフチェーンで key を計算して送信します:
bash
KEY=$(cast keccak $(cast abi-encode "f(address,address)" "$YOUR_ADDRESS" "$CHALLENGE"))
cast send $CHALLENGE "mintFlag(bytes32)" "$KEY" --private-key $PK --rpc-url $RPC
4. 遭遇したトラップ
ABIエンコード形式: cast abi-encode "f(address,address)" は標準のABIエンコード(各パラメータ32バイト、左側ゼロパディング)を使用しますが、Solidity の abi.encodePacked はコンパクトに連結します(2つの20バイトアドレスが40バイトに連結されます)。
5. トラップの原因
Solidity では abi.encodePacked と abi.encode は異なるバイト列を生成します:
abi.encodePacked(addr1, addr2)→ 40バイトabi.encode(addr1, addr2)→ 64バイト
6. 解決方法
2つのアドレスを手動で連結します(0xプレフィックスを除去):
bash
# コンパクト連結: 2つの20バイトアドレスを40バイトに連結
KEY=$(cast keccak "0x${ADDR1_WITHOUT_0X}${ADDR2_WITHOUT_0X}")
7. 技術ポイント
| ポイント | 説明 |
|---|---|
abi.encodePacked vs abi.encode | 前者はコンパクト連結、後者は32バイトアライメント — ハッシュ結果は完全に異なる |
| keccak256による認証 | ハッシュの一方向性と衝突耐性を利用したシンプルな challenge-response |