Skip to content
On this page

S2C2: Show Me Your Key

1. Problem

You need to call mintFlag(bytes32 yourKey), where yourKey must equal keccak256(abi.encodePacked(msg.sender, address(this))).

2. Cause

The key is generated from the hash of the compact concatenation of the caller's address and the contract address. Since both are deterministic (the caller knows their own address, and the contract address is fixed), the key can be easily computed.

3. Solution

Compute the key using the correct method:

bash
# Key point: abi.encodePacked is compact concatenation, NOT standard ABI encoding!
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. Pitfalls Encountered

Incorrect ABI Encoding: Using cast abi-encode "f(address,address)" produces standard ABI encoding (each parameter 32 bytes) rather than the compact encoding of abi.encodePacked.

5. Why the Pitfall Occurred

Solidity's abi.encodePacked and abi.encode produce different byte sequences:

  • abi.encodePacked(addr1, addr2) -> 40 bytes (two 20-byte addresses concatenated)
  • abi.encode(addr1, addr2) -> 64 bytes (each 32-byte aligned)
  • The keccak256 results are completely different!

6. How to Resolve

Strip the 0x prefix, manually concatenate the two addresses, then compute keccak256.

7. Technical Takeaways

PointExplanation
abi.encodePacked vs abi.encodeThe former uses compact concatenation, the latter uses 32-byte alignment
S2 Registration DependencyNew wallets must complete S1C1 registration before S2C2
keccak256 as Identity VerificationLeverages hash determinism and collision resistance

Built with AiAda