Skip to content
On this page

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.encodePackedabi.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 作为身份验证利用哈希确定性和碰撞抗性

Built with AiAda