Appearance
S2C2: Show Me Your Key
1. 問題
mintFlag(bytes32 yourKey) を呼び出す必要があります。ここで yourKey は keccak256(abi.encodePacked(msg.sender, address(this))) と等しくなければなりません。
2. 原因
key は呼び出し元アドレスとコントラクトアドレスのコンパクト連結ハッシュによって生成されます。どちらも決定的であるため(呼び出し元は自分のアドレスを知っており、コントラクトアドレスは固定)、key は簡単に計算できます。
3. 解法
正しい方法で key を計算します:
bash
# 重要:abi.encodePacked はコンパクト連結であり、標準 ABI エンコーディングではありません!
ADDR1=$(echo $YOUR_ADDRESS | tr '[:upper:]' '[:lower:]' | sed 's/0x//')
ADDR2=$(echo $CHALLENGE | tr '[:upper:]' '[:lower:]' | sed 's/0x//')
KEY=$(cast keccak "0x${ADDR1}${ADDR2}")
cast send $CHALLENGE "mintFlag(bytes32)" "$KEY" --private-key $PK --rpc-url $RPC
4. 遭遇した落とし穴
ABI エンコーディング方法の誤り: cast abi-encode "f(address,address)" を使用すると標準 ABI エンコーディング(各パラメータ32バイト)が得られ、abi.encodePacked のコンパクトエンコーディングとは異なります。
5. 落とし穴の原因
Solidity の abi.encodePacked と abi.encode は異なるバイト列を生成します:
abi.encodePacked(addr1, addr2)→ 40 バイト(2つの20バイトアドレスを連結)abi.encode(addr1, addr2)→ 64 バイト(各32バイトにアラインメント)keccak256の結果は完全に異なります!
6. 解決方法
0x プレフィックスを除去した後、2つのアドレスを手動で連結し、keccak256 を計算します。
7. 技術的ポイント
| ポイント | 説明 |
|---|---|
abi.encodePacked vs abi.encode | 前者はコンパクト連結、後者は32バイトアラインメント |
| S2 登録依存関係 | 新しいウォレットは S2C2 を完了する前にまず S1C1 の登録を完了する必要があります |
| keccak256 による認証 | ハッシュの決定性と衝突耐性を利用します |