Skip to content

Commit

Permalink
Smart contract bounties without forge-std
Browse files Browse the repository at this point in the history
  • Loading branch information
guidanoli committed Dec 11, 2024
1 parent bded212 commit 907fdfe
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 106 deletions.
8 changes: 0 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -157,18 +157,10 @@ COPY --from=riscv64-build-stage /opt/build/bubblewrap/bwrap /usr/bin/bwrap
COPY --from=riscv64-build-stage /opt/build/bwrapbox/bwrapbox /usr/bin/bwrapbox
COPY --from=riscv64-build-stage /opt/build/bwrapbox/seccomp-filter.bpf /usr/lib/bwrapbox/seccomp-filter.bpf

# install forge-std
ARG FORGE_STD_VERSION=1.9.3
ADD https://github.com/foundry-rs/forge-std.git#v${FORGE_STD_VERSION} /usr/share/forge-lib/forge-std

# install openzeppelin-contracts
ARG OPENZEPPELIN_VERSION=5.1.0
ADD https://github.com/OpenZeppelin/openzeppelin-contracts.git#v${OPENZEPPELIN_VERSION} /usr/share/forge-lib/openzeppelin-contracts

# install forge-deploy-lib
ARG FORGE_DEPLOY_LIB_VERSION=0.0.0
ADD https://github.com/crypto-bug-hunters/forge-deploy-lib.git#v${FORGE_DEPLOY_LIB_VERSION} /usr/share/forge-lib/forge-deploy-lib

RUN useradd --home-dir /bounty bounty
RUN mkdir -p /bounties /bounty
RUN chown bounty:bounty /bounty
Expand Down
9 changes: 4 additions & 5 deletions tests/bounties/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,13 @@ ADDER_VERSIONS= safe unsafe
all: $(patsubst %,dist/adder-%-bounty.tar.xz,$(ADDER_VERSIONS))

dist/adder-%-bounty.tar.xz: \
build/adder-%-bounty/script/Setup.s.sol \
src/adder/start.sh \
src/adder/foundry.toml \
src/adder/src/IRegistry.sol \
src/adder/src/Registry.sol \
src/adder/src/IAdder.sol \
src/adder/src/%/Adder.sol \
src/adder/script/Assertion.s.sol
build/adder-%-bounty/src/Adder.sol
tar $(TAR_OPTS) $@ $^

build/adder-%-bounty/script/Setup.s.sol: src/adder/script/%/Setup.s.sol
build/adder-%-bounty/src/Adder.sol: src/adder/src/%/Adder.sol
mkdir -p $(@D)
cp $< $@
3 changes: 0 additions & 3 deletions tests/bounties/src/adder/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
broadcast
cache
deployment.json
exploited
lib
out
15 changes: 0 additions & 15 deletions tests/bounties/src/adder/foundry.toml

This file was deleted.

16 changes: 0 additions & 16 deletions tests/bounties/src/adder/script/Assertion.s.sol

This file was deleted.

17 changes: 0 additions & 17 deletions tests/bounties/src/adder/script/safe/Setup.s.sol

This file was deleted.

17 changes: 0 additions & 17 deletions tests/bounties/src/adder/script/unsafe/Setup.s.sol

This file was deleted.

8 changes: 8 additions & 0 deletions tests/bounties/src/adder/src/IRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.27;

interface IRegistry {
function get(string memory name) external view returns (address addr);
function set(string memory name, address addr) external;
}
13 changes: 13 additions & 0 deletions tests/bounties/src/adder/src/Registry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.27;

import {IRegistry} from "./IRegistry.sol";

contract Registry is IRegistry {
mapping(string name => address addr) public get;

function set(string memory name, address addr) external override {
get[name] = addr;
}
}
4 changes: 2 additions & 2 deletions tests/bounties/src/adder/src/safe/Adder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

pragma solidity ^0.8.27;

import {IAdder} from "../IAdder.sol";
import {IAdder} from "src/IAdder.sol";

contract SafeAdder is IAdder {
contract Adder is IAdder {
uint256 public number = 1;

function add(uint256 x) external override {
Expand Down
4 changes: 2 additions & 2 deletions tests/bounties/src/adder/src/unsafe/Adder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

pragma solidity ^0.8.27;

import {IAdder} from "../IAdder.sol";
import {IAdder} from "src/IAdder.sol";

contract UnsafeAdder is IAdder {
contract Adder is IAdder {
uint256 public number = 1;

function add(uint256 x) external override {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,19 @@

pragma solidity ^0.8.27;

import {DeploymentReaderScript} from "forge-deploy-lib/src/DeploymentScript.sol";

import {IRegistry} from "src/IRegistry.sol";
import {IAdder} from "src/IAdder.sol";

contract ExploitScript is DeploymentReaderScript {
function run() external {
loadDeployment();
IAdder adder = IAdder(getContract("Adder"));
contract Exploit {
function run(IRegistry registry) external {
IAdder adder = IAdder(registry.get("Adder"));

uint256 number = adder.number();
uint256 increment;
unchecked {
increment = type(uint256).max - number + 1;
}

vm.startBroadcast();
adder.add(increment);
vm.stopBroadcast();
}
}
37 changes: 24 additions & 13 deletions tests/bounties/src/adder/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ RETH_VERSION=1.0.5
alias reth="reth-$RETH_VERSION"

>&2 echo "Setting up Forge project..."
cp -r foundry.toml src script /tmp
cp "$1" /tmp/script/Exploit.s.sol
cp -r /usr/share/forge-lib /tmp/lib
cp -r src /tmp
cp "$1" /tmp/src/Exploit.sol
cd /tmp

>&2 echo "Building Forge project..."
Expand All @@ -39,7 +38,7 @@ export ETH_RPC_URL=$HTTP_ADDR:$HTTP_PORT

while true
do
if chain_id=`cast chain-id 2>/dev/null`
if chain_id=$(cast chain-id 2>/dev/null)
then
if [[ $chain_id == 1337 ]]
then
Expand All @@ -63,24 +62,36 @@ done

PK=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

run_forge_script() {
forge script --silent --fork-url $ETH_RPC_URL "$@"
deploy() {
forge create --json --private-key "$PK" "$1:$2" | jq -r .deployedTo
}

run_forge_script_broadcast() {
run_forge_script --broadcast --slow --private-key $PK "$@"
>&2 echo "Deploying registry contract..."
REGISTRY=$(deploy src/Registry.sol Registry)

send() {
>/dev/null cast send --private-key "$PK" "$@"
}

deploy_and_register() {
address=$(deploy "$@")
send "$REGISTRY" 'set(string,address)' "$2" "$address"
echo "$address"
}

>&2 echo "Deploying contracts..."
FOUNDRY_PROFILE=deploy run_forge_script_broadcast script/Setup.s.sol:SetupScript
>&2 echo "Deploying and registering project contracts..."
ADDER=$(deploy_and_register src/Adder.sol Adder)

>&2 echo "Deploying exploit contract..."
EXPLOIT=$(deploy src/Exploit.sol Exploit)

>&2 echo "Running exploit..."
FOUNDRY_PROFILE=exploit run_forge_script_broadcast script/Exploit.s.sol:ExploitScript
send "$EXPLOIT" 'run(address)' "$REGISTRY"

>&2 echo "Testing contracts..."
FOUNDRY_PROFILE=test run_forge_script script/Assertion.s.sol:AssertionScript
number=$(cast call "$ADDER" 'number()(uint256)')

if [ -f exploited ]
if [ "$number" -eq 0 ]
then
>&2 echo "Valid exploit!"
exit 0
Expand Down
57 changes: 57 additions & 0 deletions tests/tests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ local timestamp = 1697567000
local first_bounty_final_state
local second_bounty_final_state
local third_bounty_final_state
local fourth_bounty_final_state

describe("tests on Lua bounty", function()
local bounty_code = "tests/bounties/dist/lua-5.4.3-bounty.tar.xz"
Expand Down Expand Up @@ -796,6 +797,7 @@ describe("tests on (linked) Lua bounty", function()
},
},
})
fourth_bounty_final_state = res.state.bounties[bounty_index + 1]
end)

-- advance to just before deadline
Expand Down Expand Up @@ -887,5 +889,60 @@ end
end)
end)

describe("tests on Adder bounty", function()
local name = "Adder"
local description = "Try to break the Adder smart contract written in Solidity"
local bounty_code = "tests/bounties/dist/adder-unsafe-bounty.tar.xz"
local bounty_valid_exploit = readfile("tests/bounties/src/adder/src/unsafe/Exploit.sol")
local bounty_index = 4
local bounty_deadline = timestamp + 3600

it("should create bounty", function()
local res = advance_input(machine, {
sender = DEVELOPER1_WALLET,
kind = "CreateAppBounty",
timestamp = timestamp,
data = {
name = name,
description = description,
deadline = bounty_deadline,
token = CTSI_ADDRESS,
codeZipBinary = tobase64(readfile(bounty_code)),
},
})
expect.equal(res.status, "accepted")
expect.equal(res.state, {
bounties = {
first_bounty_final_state,
second_bounty_final_state,
third_bounty_final_state,
fourth_bounty_final_state,
{
deadline = bounty_deadline,
description = description,
exploit = null,
imgLink = "",
name = name,
sponsorships = null,
token = CTSI_ADDRESS,
withdrawn = false,
},
},
})
end)

it("should accept inspect of a exploit that succeeded", function()
local res = inspect_input(machine, {
sender = HACKER1_WALLET,
timestamp = timestamp,
data = {
bountyIndex = bounty_index,
exploit = tobase64(bounty_valid_exploit),
},
})
expect.equal(res.status, "accepted")
end)
end)

lester.report() -- Print overall statistic of the tests run.
lester.exit() -- Exit with success if all tests passed.

0 comments on commit 907fdfe

Please sign in to comment.