Welcome to the Sui Capture the Flag challenge! This CTF is designed to test and improve your understanding of Sui Move smart contracts, the Sui object model, and Programmable Transaction Blocks (PTBs).
Important: Do NOT clone or fork this repository directly. Instead, create a template copy so you have your own independent repo to work in.
- At the top of this repository's GitHub page, click the "Use this template" button (top-right corner).
- Select "Create a new repository".
- Give your repo a name, and make sure it is set to Public.
- Click "Create repository".
- Clone your newly created repository to your local machine:
git clone <your-new-repo-url>
cd <your-new-repo-name>Now that you have your own copy, set up your environment and create a keypair for interacting with the Sui blockchain.
- Node.js (v18 or higher recommended)
- pnpm package manager
- Navigate to the
scriptsdirectory:
cd scripts- Install dependencies:
pnpm install- Generate and fund a new keypair:
pnpm init-keypairThis will generate a new Ed25519 keypair and save it to keypair.json in the scripts directory. Make sure not to use this keypair in any production environments.
If you are at a hackathon or workshop event, ask your Sui rep for a dedicated faucet (or check the track details). Otherwise, use the Official Sui faucet.
You can view your account and balance on the Sui Explorer at:
https://suiscan.xyz/testnet/account/{your-address}
Deployed Contract Address: 0xd56e5075ba297f9e37085a37bb0abba69fabdf9987f8f4a6086a3693d88efbfd
Transaction Digest: AL133Jj44NV9euC6RreY1gjGHmCMwqfTcuKn6bbrKGqY
All challenges are Move modules within the single ctf package located in the contracts/ directory.
All challenges are independent of each other and can be done in any order!
contracts/
├── Move.toml # Package: ctf
└── sources/
├── flag.move # Base flag module
└── ... # Challenge modules will be added here
Extract the flag during the moving window.
- Examine the
[moving_window.move](./contracts/sources/moving_window.move)contract carefully. - Determine when the window is open.
- Implement your solution in
[scripts/src/moving_window.ts](./scripts/src/moving_window.ts). - Run your script with
pnpm moving-windowto extract the flag.
Buy a flag using USDC tokens.
- Examine the
[merchant.move](./contracts/sources/merchant.move)contract carefully. - Acquire USDC tokens on testnet.
- Implement your solution in
[scripts/src/merchant.ts](./scripts/src/merchant.ts). - Run your script with
pnpm merchantto extract the flag.
Open lootboxes until you get a flag (1 in 100,000 chance!).
- Examine the
[lootboxes.move](./contracts/sources/lootboxes.move)contract carefully. - Notice the odds of winning: 1 in 100,000. Brute forcing would cost hundreds of dollars in gas fees!
- You'll need to deploy your own Move contract to solve this efficiently.
- Create your exploit contract in the
[exploit/](./exploit/)directory. - Deploy your contract and call it repeatedly until you win.
Read the Sui randomness documentation, especially:
- The section on "Use (non-public) entry functions"
- Why
#[allow(lint(public_random))]exists and what it allows - What "composition attacks" means in this context
Key questions to consider:
- What's the difference between a
publicfunction and anentryfunction? - When a function is
public, what can other Move modules do with it? - How can you make a transaction abort conditionally to avoid paying gas for failed attempts?
- Look at the
extract_flag()function - what happens when you call it on a MaybeFlag without a flag?
Additional help:
- If you're getting
PostRandomCommandRestrictionserrors, remember that PTBs with randomness have restrictions on what commands can follow the random call.
Stake SUI tokens to earn the right to claim a flag.
- Examine the
[staking.move](./contracts/sources/staking.move)contract carefully. - Understand the staking requirements: you must stake a minimum of 1 SUI for at least 1 week (168 hours).
- Implement your solution in
[scripts/src/staking.ts](./scripts/src/staking.ts). - Run your script with
pnpm stakingto extract the flag.
Compete against other players to build your shield to the threshold and claim a flag — while sabotaging others along the way.
- Examine the
[sabotage_arena.move](./contracts/sources/sabotage_arena.move)contract carefully. - Register, build your shield, and attack opponents using
[scripts/src/sabotage_arena.ts](./scripts/src/sabotage_arena.ts). - Implement your solution to reach the shield threshold and claim a flag.
Note: This CTF is for educational purposes only. The keypair generated is for testnet use only and should never be used on mainnet or with real assets.