Warming up, let's get you setup and make sure you can connect to the blockchain infra ok :). Your challenge is to ensure the `isSolved()` function returns true!
Author: Blue Alder
[EightFiveFourFive.sol]
Writeup
Alright this is the first blockchain challenge I’ve ever completed, and it was pretty much just a test to make sure you know how to connect to their infra. I’m not a blockchain guy nor do I ever really intend to get super deep into blockchain, but even just trying to figure out how to connect to the infra took me a while and online resources weren’t very helpful, so I felt it was important to document this for absolute blockchain beginners like me.
This file defines a smart contract called EightFiveFourFive that we just need to interact with. The syntax looks pretty similar to many programming languages, so it’s not too hard to understand. The description states you need to call isSolved() and have it return true, meaning that the you_solved_it variable needs to be set to true. In the top of the contract, it’s defined to false, so we need to change that using the solve_the_challenge() function. This function takes the Keccak-256 hash of two variables and compares them, if the hashes are the same then you_solved_it will be true!
The two variables are answer and use_this. answer is passed as an argument to the function, meaning WE pass that variable when we call the function. The use_this variable is set when the contract is created, and since it’s not hard-coded we have to call the readTheStringHere() function to get it.
So solve chain is:
Call readTheStringHere() and save the output.
Pass that output as the sole parameter of solve_the_challenge() and call it.
Call isSolved()
Infrastructure
Just before we get into the Python code for interacting with the contract, I just want to show what the per-team instances looked like and what information is provided.
This beautiful UI contains the smart contract again, restates the goal, and displays the following information:
Player Balance - 1.0 ETH
Every transaction requires ETH to make, so your wallet is pre-initialized with more than enough
Player Wallet Address - 0x81ECd1984be45000Af31A83D09e78aCa762900A0
This is your entrypoint into the blockchain infrastructure
Chain ID and Block Time (tbh no idea what they are but I didn’t need them)
Creating Solve Script
I used the web3 Python library to solve this challenge. Even though this is a simple blockchain challenge, there are still quite a few lines to fill out. First, we’re going to start by making constants with the above info, create a Web3 Python object to interact with, and use our private key to authenticate to our account.
Now we need to create a contract object, linked to the CONTRACT_ADDRESS and initializing using the contract’s ABI. The ABI is standardized JSON that defines data and functions contained within the contract, and is parsed from the actual .sol file. To obtain the ABI for EightFiveFourFive.sol, I went to https://remix.ethereum.org/ and had it do it online. You right-click in File Explorer and upload the .sol file.
After doing this, I noticed a red line under the solidity version. In order to get the ABI, you need to compile the .sol file, and make sure that the compiler version matches the pragma line in the contract. I swtiched it to 0.8.19+commit.7dd6d404 (removing the underline), and pressed the Compile button.
After doing that, a few more buttons will appear in that same tab, one of which says ABI. You just click that to copy the ABI JSON to your clipboard.
Okay, now that we have the ABI, we can now initialize our contract object in our Python script.
Now that the solve script is set up and initialized, we can now follow our solve chain to get the flag. As a reminder, this is it:
Call readTheStringHere() and save the output.
Pass that output as the sole parameter of solve_the_challenge() and call it.
Call isSolved()
To get the use_this variable from the readTheStringHere() function, you do the following:
1 2 3
# Step 1 - call readTheStringHere() and save the output use_this = contract.functions.readTheStringHere().call() print("use_this: ", use_this)
This output the string "I can connect to the blockchain!", which is our magic phrase! Now to call the next function, a little more setup is needed and a transaction will go through.
Now if you’re wondering how the nonce is created, where the gas amount comes from, or even what Wei is, I have no idea. I just know it works and this is how you interact with it. Just like how wallets and contracts have hash addresses, so do transactions. After making a call to solve_the_challenge() with the use_this variable, you wait for a transaction receipt to ensure everything worked out right.
The last step is to call isSolved(), and then you can get the flag from the infrastructure!
1 2 3
# Step 3 - called isSolved() to check if the challenge is solved solved = contract.functions.isSolved().call() print(solved)