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 是紧凑拼接(两个 20 字节地址拼接为 40 字节)。
5. 陷阱的原因
Solidity 中 abi.encodePacked 和 abi.encode 产生不同的字节序列:
abi.encodePacked(addr1, addr2)→ 40 字节abi.encode(addr1, addr2)→ 64 字节
6. 如何解决
手动拼接两个地址(去掉 0x 前缀):
bash
# 紧凑拼接: 两个 20 字节地址拼接为 40 字节
KEY=$(cast keccak "0x${ADDR1_WITHOUT_0X}${ADDR2_WITHOUT_0X}")
7. 技术要点
| 要点 | 说明 |
|---|---|
abi.encodePacked vs abi.encode | 前者紧凑拼接,后者 32 字节对齐 — 哈希结果完全不同 |
| keccak256 作为身份验证 | 利用哈希的单向性和碰撞抗性做简单的 challenge-response |