Skip to content
On this page

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.encodePackedabi.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

Built with AiAda