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 字节(两个 20 字节地址拼接)abi.encode(addr1, addr2)→ 64 字节(各 32 字节对齐)keccak256结果完全不同!
6. 如何解决
去除 0x 前缀后手动拼接两个地址,然后计算 keccak256。
7. 技术要点
| 要点 | 说明 |
|---|---|
abi.encodePacked vs abi.encode | 前者紧凑拼接,后者 32 字节对齐 |
| S2 注册依赖 | 新钱包必须先完成 S1C1 注册才能完成 S2C2 |
| keccak256 作为身份验证 | 利用哈希确定性和碰撞抗性 |