bg-ctf

Challenge 12: Give me the block!

In this challenge, you need to understand the complex inner workings of blocks to form some data with the same hash as a block.

Contract Overview

The contract has two main functions:

Hints

Hint 1 mintFlag(bytes memory rlpBytes) requires keccak256(rlpBytes) to be the same as blockhash(registeredBlock). It's virtually impossible to find data that hashes to the same value. How else can you get some data that has the same hash?
Hint 2 Under the hood, blockhash() has a keccak256() operation. If we figure out the parameters to this hash, we can pass that into the mintFlag() function!
Hint 3 A block hash is the Keccak-256 hash of the block header encoded in RLP. Note that this is Optimism, so the block header will be different! Specifically, here is the structure of the Optimism block header: ``` [ parentBlockHash, sha3Uncles, miner, stateRoot, transactionsRoot, receiptsRoot, logsBloom, number, gasLimit, gasUsed, timestamp, extraData, mixHash, nonce, // <- after PoW, 8 bytes of zeros baseFeePerGas, withdrawalsRoot, blobGasUsed, excessBlobGas, parentBeaconBlockRoot ] ```

Solution

Click to reveal solution 1. First, register for minting:
challenge12.preMintFlag();
uint256 targetBlock = block.number + challenge12.futureBlocks();
2. Get the block data for targetBlock. This can be obtained by an eth_getBlockByNumber call to an RPC. 3. After converting to a list (see hint #3), RLP encode it. 4. Submit the proof:
challenge12.mintFlag(rlpEncoded);
The contract will: - Verify the block number matches - Check that the RLP-encoded header matches the block hash - Mint your flag if everything is correct Congratulations! You've mastered block header verification and RLP encoding! 🎉