There is a new version of this tutorial that is easier and quicker to follow. Please check it here.
In this tutorial, you will learn how to create a bug bounty on Bug Buster for a smart contract project!
Bug Buster expects bounties to be submitted in a particular format. All the necessary files (such as source code, binaries, etc.) must be bundled as an archive file with tar
and compressed with xz
. The final product should be a file with the .tar.xz
extension.
The archive file should contain a start.sh
file, which is the entry-point that will be called by the Bug Buster back-end when someone tries to exploit your bounty. It passes the path of the exploit file as argument, and checks the status code returned by the Shell script. If it exits with status code 0, it marks the exploit as valid and rewards the hacker.
In the case of smart contract bounties, the bundle only needs to contain the Solidity files of your project and its dependencies, and a few other files. The Bug Buster back-end already contains Reth, a production-level Ethereum node, Forge, a development smart contract development tool, and the Solidity compiler.
In order to follow this tutorial you will need to have the following dependencies installed on your machine:
To demonstrate how to submit a bounty for a smart contract project, let’s start with a new Forge project from scratch.
counter-bounty
mkdir counter-bounty
cd counter-bounty
forge init
script/Couner.s.sol
and tests/Counter.t.sol
which are created by default, but will not be used in this tutorial.rm script/Counter.s.sol test/Counter.t.sol
/src
folder called Counter
, which has a state variable number
, whose value can be set calling the function setNumber
and can be incremented by 1 calling the function increment
. See the code below.// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract Counter {
uint256 public number;
function setNumber(uint256 newNumber) public {
number = newNumber;
}
function increment() public {
number++;
}
}
increment
to intentionally insert an arithmetic overflow vulnerability.Never do this on code that is intented to be deployed on mainnet!
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract Counter {
uint256 public number;
function setNumber(uint256 newNumber) public {
number = newNumber;
}
function increment() public {
unchecked {
number++;
}
}
}
start.sh
script file in the root folder, which is the entry point for the execution of your project on Bug Buster. This script must: deploy your contract, set the initial state, execute the exploit code and, finally, run the assertions to check if the contract was exloited or not. Just paste the code below and read the comments to understand the sequence of actions.#!/usr/bin/env bash
source ./setup-exec-env.sh
>&2 echo "Deploying and registering project contracts..."
COUNTER=$(deploy_and_register src/Counter.sol Counter)
>&2 echo "Deploying exploit contract..."
EXPLOIT=$(deploy src/Exploit.sol Exploit)
>&2 echo "Running exploit..."
send "$EXPLOIT" 'run(address)' "$REGISTRY"
>&2 echo "Verifying contracts after exploit execution..."
number=$(cast call "$COUNTER" 'number()(uint256)')
if [ "$number" -eq 0 ]
then
>&2 echo "Valid exploit!"
exit 0
else
>&2 echo "No exploit found."
exit 1
fi
Set the execution permission for this file using the following command:
chmod +x start.sh
start.sh
file that was provided depends on another script called setup-exec-env.sh
. This script prepares Bug Buster's execution environment and must be kept with no modifications! wget https://raw.githubusercontent.com/crypto-bug-hunters/bug-buster/refs/heads/next/tests/bounties/src/adder/setup-exec-env.sh
chmod +x setup-exec-env.sh
Register.sol
and its corresponding interface IRegistry.sol
. As their name suggest, they register the deployment addresses of the project's contracts and make them available for all execution stages declared in the start.sh
file (it will become clearer later, when you read about the exploit code example). Download these files inside the src
folder using the command below.wget https://raw.githubusercontent.com/crypto-bug-hunters/bug-buster/refs/heads/next/tests/bounties/src/Register.sol
wget https://raw.githubusercontent.com/crypto-bug-hunters/bug-buster/refs/heads/next/tests/bounties/src/IRegister.sol
forge build
counter-bounty.tar.xz
file using the Forge cache to list all Solidity files necessary to compile the project. This helps reduce the size of the bundle, and, therefore, the cost of the base layer transaction.jq -r '.files|keys[]' cache/solidity-files-cache.json | \
xargs tar -cJf counter-bounty.tar.xz setup-exec-env.sh start.sh foundry.toml
https://github.com/crypto-bug-hunters/bug-buster.git
cd bug-buster
git switch next
The make machine
command may take some minutes to complete for the first time. This command builds the Cartesi Machine with a full Linux distro plus the Solidity compiler, Foundry, Reth, etc.
Check the links below for instructions on how to do the configuration using Metamask. If you use another wallet, don't worry because these are common configurations and it will not be difficult to find information on how to do that in your wallet.
Available Accounts
==================
(0) 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000.000000000000000000 ETH)
(1) 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 (10000.000000000000000000 ETH)
(2) 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC (10000.000000000000000000 ETH)
Private Keys
==================
(0) 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
(1) 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
(2) 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a
0x92C6bcA388E99d6B304f1Af3c3Cd749Ff0b591e2
) an ERC-20 contract provided by Cartesi CLI for testing purpose.counter-bounty.tar.xz
file.All right! The bug bounty for your project was created and now you can send some solidity code to interact with it.
number
to 1 and then call the increment method.// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.27;
import {IRegistry} from "src/IRegistry.sol";
import {Counter} from "src/Counter.sol";
contract Exploit {
function run(IRegistry registry) external {
Counter counter = Counter(registry.get("Counter"));
counter.setNumber(1);
counter.increment();
}
}
Isn't it awesome!? You submit a solidity code to interact with the bug bounty for the Counter
smart contract running in a sandboxed production-level EVM (Reth) inside an altVM (Cartesi Machine)!
Now it is time to become a white-hat-hacker and submit a code to exploit the arithmetic overflow that was introduced.
Counter
smart contract and click on Submit button.// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.27;
import {IRegistry} from "src/IRegistry.sol";
import {Counter} from "src/Counter.sol";
contract Exploit {
function run(IRegistry registry) external {
Counter counter = Counter(registry.get("Counter"));
uint256 currentNumber = counter.number();
uint256 maxUint256 = type(uint256).max - currentNumber;
counter.setNumber(maxUint256);
counter.increment();
}
}
If you would like to explore more the smart contracts bounty feature, try to create a bug bounty for your own project or for a project that you like/support/use.
Thanks for following this tutorial and learn more about Bug Buster!
If you have any comments, suggestions and/or doubts, please don't hesitate to reach out through our Telegram group or X account.