The Foundry fundamentals cheat sheet
CTF-hacking is the new Netflix-and-chill
We at Inference do smart contract hacking for a living. We go to work in the morning, audit smart contracts, and go back home. Sometimes there is no going to work and going back home even (thank you, smart working), so all that is left in our lives is hacking. Do you know what we sometimes enjoy doing after hours? Some more hacking. So we test our skills with challenges and CTFs that we find online, and oh-boy does HackTheBox have a beautiful smart contract track.
In this series of challenges you can test several common attack vectors you usually identify when doing Solidity smart contract audits. We cannot provide any spoilers (it is against the platform’s policy for all live challenges), but what we can do is share with you the fundamental cheat sheet necessary to be able to solve the challenges. Once you are up to speed with the tools, all you need to do is to identify the vulnerability (or vulnerabilities) in each challenge and code the solution. The easy part, basically.
In order to solve all the challenges, all we used was coding skills (some challenges require you to code some basic smart contracts in Solidity), and basic Foundry skills. The first part, coding in Solidity, you can pick up anywhere you want (there is some great Youtube content from Patrick Collins, for example), but we would like to recommend the following hands-on tutorial: CryptoZombies.
For what concerns learning Foundry, instead, we’ve got you covered. Here you can find all the commands (ALL of them, we did not need anything more than these) you will need to work through the challenges.
What is Foundry?
A good question to ask before using a Foundry cheat sheet is the obvious, albeit extremely relevant, one: what is Foundry?
Foundry is a development toolbox that allows you to create projects, deploy smart contracts and test them. It comes in the form of a suite of tools that allows you to deploy and interact with your smart contract from the command line: you can query its balance, call its entrypoints, analyze the history of a blockchain, and much more. A beautifully thought-out, comprehensive documentation can be found here: Foundry Book. Finally, with the intro out of the way, let’s take a look at the necessary tools and commands to solve the HackTheBox challenges from the HackenProof Track.
The cheat sheet
Creating a project
Navigate to a new folder where you want to create your project and run:
forge init .
The command will create a skeleton for a Solidity smart contract development project. What you want to do at this point is to clean all files in the src, test and script subfolders, and write your new contracts in src. If you are going to use any additional library (not necessary), place it in the lib folder.
Deploying a contract
First step, code a contract. To deploy it, run:
forge create src/Attack.sol:Attack --rpc-url $RPC --private-key $PRIV
Please note, $RPC is the url of the challenge ending in “/rpc”, to connect to the node running on the chain, and $PRIV is the private key of the account that has been assigned to you. An automated bash command to extract the address of the newly created contract (that we used repeatedly) is shown below:
ATTACK=$(forge create src/Attack.sol:Attack --rpc-url $RPC --private-key $PRIV | grep "Deployed to" | cut -d " " -f3)
You can now refer to your newly deployed contract as $ATTACK.
Now, what if your contract has a constructor that accepts parameters? You can provide them with the flag “--constructor-args”, as shown here:
forge create src/Attack.sol:Attack --constructor-args $AUCTION $VALUE_2 --rpc-url $RPC --private-key $PRIV
If your constructor is payable, you can also send ether to it using the “--value” flag, for example:
forge create src/Attack.sol:Attack --constructor-args $AUCTION $VALUE_2 --rpc-url $RPC --private-key $PRIV --value 1ether
If you don’t specify the unit (ether), you will send wei, remember that when picking how much you want to send to the contract.
Retrieving relevant on-chain information
Sometimes it will be useful to have some general information about the environment you are working with. Here is how to do it:
- If you wish to retrieve the chain-id, use:
cast chain-id --rpc-url $RPC
- You are not sure you have enough ether to pay for the gas cost of the next transaction, we have all been there. Run an estimate to know the cost beforehand, with:
cast estimate $TARGET "punch()" --rpc-url $RPC
- The gas price can fluctuate, stay up to date with the current value before running your transaction by using:
cast gas-price --rpc-url $RPC
- Often, during the challenges, you will want to know whether your attack worked and you managed to drain the funds of some contract or address. Other times, you just want to know how much you have left to run your attacks. To figure that out, run:
cast balance $ADDRESS --rpc-url $RPC
- You need to know the timestamp of a specific block. For example (wink), the timestamp of the genesis block. Use this:
cast age 1 --rpc-url $RPC
Interacting with the contract
Beautifully coded, perfectly deployed, all you need now to destroy the challenge and obtain eternal glory is to interact with the contract and call its entrypoints. Ready to launch the final attack?
- To interact with an entrypoint that does not require ether nor parameters:
cast send $ATTACK "attack()" --rpc-url $RPC --private-key $PRIV
- To interact with an entrypoint that requires ether but no parameters:
cast send $ATTACK "attack()" --rpc-url $RPC --private-key $PRIV –value 1ether
- To interact with an entrypoint that takes parameters, you can use the following layout. Please note, “$PLAYER” is the variable containing the address that will be passed to the “claim” entrypoint:
cast send $ATTACK 'claim(address)' $PLAYER --rpc-url $RPC --private-key $PRIV
- To interact with a view you don’t need to provide your private key. Apart from this nuance, views work like regular entrypoints, for example:
cast call $ADDRESS "owner(address)" $PLAYER --rpc-url $RPC
Wrapping up
Sometimes challenges you find online might be discouraging, especially if you are just starting out. Having to face mountains of docs before being able to even write a single line of code (let alone complete your first hack) can put you off and prevent you from ever starting on the wonderful journey of smart contract auditing. That is why we put this together, so that you can just think of what you need (it won’t be easy, but this much you have to put in yourself), and then come here and check out how exactly it is done in Foundry. If you think we missed out on some command that is necessary to solve the HackTheBox track, please let us know. Also, if you have any suggestion regarding new content that might be useful to the web3 auditing community, or any comment whatsoever, reach out.
As always, if you need a security audit, send us an email at [email protected], and let’s get going securing your projects!