Skip to content
On this page

S1C2: Just Call Me Maybe

1. Problem

The mintFlag(bytes32 key) function needs to be called, where key must equal keccak256(abi.encodePacked(msg.sender, address(this))).

2. Root Cause

The contract uses a simple form of identity verification: the key is composed of the hash of the caller's address and the contract's address. Since the caller cannot forge their own address, passing the challenge simply requires computing the key correctly.

3. Solution

Compute the key off-chain and submit it:

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. Pitfalls Encountered

ABI encoding format: cast abi-encode "f(address,address)" uses standard ABI encoding (each parameter occupies 32 bytes, left-padded with zeros), whereas Solidity's abi.encodePacked uses compact concatenation (two 20-byte addresses concatenated into 40 bytes).

5. Why the Pitfall Exists

In Solidity, abi.encodePacked and abi.encode produce different byte sequences:

  • abi.encodePacked(addr1, addr2) -> 40 bytes
  • abi.encode(addr1, addr2) -> 64 bytes

6. How to Resolve

Manually concatenate the two addresses (removing the 0x prefix):

bash
# Compact concatenation: two 20-byte addresses concatenated into 40 bytes
KEY=$(cast keccak "0x${ADDR1_WITHOUT_0X}${ADDR2_WITHOUT_0X}")

7. Key Takeaways

PointExplanation
abi.encodePacked vs abi.encodeThe former uses compact concatenation, the latter uses 32-byte alignment — the hash results are completely different
keccak256 as identity verificationUses the one-way and collision-resistant properties of hashing for a simple challenge-response scheme

Built with AiAda