A minimal and reusable Foundry project template for Ethereum CTF challenges following the Setup + Target pattern.
This template includes sample contracts, a Setup.sol wrapper, an optional Attacker.sol helper, and a Solidity script Solve.s.sol to automate the exploit process.
.
βββ .env
βββ .gitignore
βββ docker-compose.yml
βββ entrypoint.sh
βββ Dockerfile
βββ foundry.toml
βββ remappings.txt
βββ README.md
βββ src
β βββ Attacker.sol
β βββ Creature.sol
β βββ Setup.sol
βββ script
βββ Solve.s.sol
PRIVATE_KEY=0x⦠# Your EOA private key
SETUP_ADDRESS=0x⦠# Deployed Setup contract address
CHAIN_ID=31337 # Chain ID of the network
RPC_URL=https://β¦ # RPC endpoint for the chain
FOUNDRY_DISABLE_NIGHTLY_WARNING=trueLoad it with:
source .env # Linux/macOS
.\.env # Windows PowerShellout/
cache/
lib/
.env[profile.default]
solc_version = "0.8.15"
src = "src"
out = "out"
lib = "lib"
remappings = ["forge-std/=lib/forge-std/src/"]forge-std/=lib/forge-std/src/
- Clone the template
git clone https://github.com/you/ctf-foundry-template.git
cd ctf-foundry-template- Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup- Install Dependencies
forge install foundry-rs/forge-std- Setup Environment
cp .env.example .env
# Then edit your values inside .env- Compile Contracts
source .env
forge clean
forge build- Run the Exploit
forge script script/Solve.s.sol:Solve \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
# --chain-id $CHAIN_ID \
--broadcast \
-vvvv- Fetch the Flag
curl http://<CTF-HOST>/flag
# 1. Base + Prereqs
FROM ghcr.io/foundry-rs/foundry:latest AS builder
USER root
WORKDIR /app
COPY foundry.toml remappings.txt ./
RUN mkdir -p lib && \
git clone --depth 1 https://github.com/foundry-rs/forge-std lib/forge-std
COPY . .
RUN forge build --optimize
# 2. Runtime
FROM ghcr.io/foundry-rs/foundry:latest
WORKDIR /ctf
COPY --from=builder /app/lib ./lib
COPY --from=builder /app/out ./out
COPY --from=builder /app/src ./src
COPY --from=builder /app/script ./script
COPY entrypoint.sh ./
USER root
RUN chmod +x entrypoint.sh
USER forge
ENTRYPOINT ["./entrypoint.sh"]#!/usr/bin/env bash
set -e
if [ "$1" = "shell" ]; then
echo "π οΈ Starting interactive shell..."
exec bash
fi
echo "π Running solver script..."
forge script script/Solve.s.sol:Solve \
--rpc-url "$RPC_URL" \
--private-key "$PRIVATE_KEY" \
--chain-id "$CHAIN_ID" \
--broadcast \
-vvvv
echo "β
Script execution completed successfully."Make it executable:
chmod +x entrypoint.sh# Build image
docker build -t ctf-template .
# Run solver script
docker run --rm -e RPC_URL=$RPC_URL \
-e PRIVATE_KEY=$PRIVATE_KEY \
-e CHAIN_ID=$CHAIN_ID \
ctf-template
# Start a shell
docker run --rm -it -e RPC_URL=$RPC_URL \
-e PRIVATE_KEY=$PRIVATE_KEY \
-e CHAIN_ID=$CHAIN_ID \
ctf-template shellversion: "3.8"
services:
ctf-template:
build: .
env_file:
- .env
volumes:
- ./:/ctf
command: ["${COMMAND:-}"]# Build image
docker-compose build
# Run solver
docker-compose up --abort-on-container-exit
# Start a shell
COMMAND=shell docker-compose run --rm ctf-template- Replace
Creature.solwith your vulnerable target. - Update
Setup.solwith the correct logic and deployed target. - Modify
Solve.s.solto reflect the new logic. - Optionally add helpers like
Attacker.sol. - Use
.envto plug in dynamic values.
π§ Tip: Fork this template for each challenge. Keep it clean. Hack smart.