Skip to content

lsdogXG/nht-ctf

Repository files navigation

nht — GMX V1 Arbitrum Fork CTF

A self-contained CTF challenge that forks Arbitrum One at a fixed block and runs GMX V1 keepers in the background. Players connect to a public RPC and interact with a live GMX V1 state to solve the challenge.

What's running

  • Arbitrum One fork at block 355878386 via Hardhat
  • Private RPC (port 8546) — full Hardhat methods, used internally by keepers
  • Public RPC (port 8545) — proxy that strips out hardhat_*, evm_*, anvil_* admin methods so players can't impersonate accounts or mine blocks
  • Keeper daemon that processes:
    • OrderBook.executeIncreaseOrder / executeDecreaseOrder (via PositionManager)
    • PositionRouter.executeDecreasePositions (decrease queue)

The challenge entry-point contract is in contracts/exp.sol.

Quick start

Local

pnpm install
cp .env.example .env       # set ARB_RPC_URL to a real Arbitrum archive RPC

# Terminal 1 — start the fork
npm run rpc

# Terminal 2 — start the keeper daemon
npm run keeper

# Terminal 3 (optional) — public RPC proxy
npm run proxy

Or, one-shot:

bash scripts/up.sh "https://your-arbitrum-rpc"

Docker (recommended for CTF deployment)

Only the public RPC port is exposed; the private RPC and keepers run inside the container.

docker build -t nht-ctf .
docker run --rm -p 8545:8545 -e ARB_RPC_URL="https://your-arbitrum-rpc/" nht-ctf

Or via compose:

export ARB_RPC_URL="https://your-arbitrum-rpc/"
docker compose up --build

Layout

contracts/exp.sol           Challenge / exploit entry-point contract
hardhat.config.ts           Fork config, networks, solidity profile
flag.txt                    Placeholder flag (replace before deploying)
scripts/
  up.sh                     One-shot launcher (rpc + proxy + keeper)
  run-fork-rpc.sh           Start the private fork RPC
  public-rpc-proxy.ts       JSON-RPC proxy that blocks admin methods
  keeper-daemon.ts          GMX V1 keeper loop
  fund-player.ts            Fund the player address with ETH/USDC
  check-fork-health.ts      Sanity-check the fork is alive
  check-vault-wbtc-reserve.ts  Win-condition probe
  docker-entrypoint.sh      Container boot script
  lib/
    gmx-v1-abis.ts          ABIs used by the keeper
    gmx-v1-arbitrum.ts      Mainnet addresses
    keepers/orderbook.ts    OrderBook keeper
    keepers/position-router.ts  PositionRouter keeper
Dockerfile / docker-compose.yml

Notes

  • Do not expose the private RPC (8546) publicly — the public proxy is what players should hit.
  • Keeper config (addresses, intervals) lives at the top of scripts/keeper-daemon.ts — no CLI args.
  • Fund the player before letting them in: edit scripts/fund-player.ts then npm run fund.
  • Replace flag.txt with your real flag before deployment.

Stack

  • Hardhat 3 + viem toolbox
  • Solidity 0.8.28
  • TypeScript / Node 22 LTS
  • pnpm

License

MIT

About

GMX V1 Arbitrum fork CTF challenge: Hardhat fork + keeper daemon + RPC proxy with admin methods stripped

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors