Skip to content
On this page

S1C2: Just Call Me Maybe

1. 問題

mintFlag(bytes32 key) 関数を呼び出す必要があります。keykeccak256(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.encodePackedabi.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

Built with AiAda