|
1 | 1 | # Fuzzing Tests |
2 | 2 |
|
3 | 3 |
|
4 | | -In case you receive an error like "Access violation in stack frame 5 at address 0x200005eb0 of size 8". Use this quide in order to fix it. |
| 4 | +## How to run the tests: |
5 | 5 |
|
6 | | -- Install trident-cli -- `cargo install trident-cli --version 0.13.0-rc.1` |
7 | 6 |
|
8 | | -- Make sure that `trident-test/cargo.toml` has |
| 7 | +### 1. Install trident-cli |
9 | 8 |
|
10 | | -```rust |
11 | | -[dependencies.trident-fuzz] |
12 | | -version = "0.13.0-rc.1" |
13 | | -features = ["token"] |
| 9 | +```bash |
| 10 | +cargo install trident-cli --version 0.13.0-rc.2 |
14 | 11 | ``` |
15 | 12 |
|
16 | | -- Leave the anchor lang dependency as it is. |
| 13 | +### 2. Build the programs |
17 | 14 |
|
18 | | -- In order to compile use `cargo build-sbf --manifest-path programs/futarchy/Cargo.toml --arch v2` (or similar for other programs) -- with solana-cli version 3.1.9. |
| 15 | +```bash |
| 16 | +# execute from project root |
| 17 | +make build-all |
| 18 | +``` |
| 19 | + |
| 20 | +> [!WARNING] |
| 21 | +> Make sure the Solana-CLI version is 3.1.9. |
19 | 22 |
|
20 | | -- Make sure that the Trident.toml points to the correct location to load the program from. |
| 23 | +### 3. Run the tests |
| 24 | + |
| 25 | +```bash |
| 26 | +trident fuzz run fuzz_0 |
| 27 | +# or another fuzz test by name |
| 28 | +``` |
21 | 29 |
|
22 | | -- If above done, call `trident fuzz run fuzz_0` |
23 | 30 |
|
24 | 31 | ## Fuzz Test Suites |
25 | 32 |
|
26 | 33 | ### fuzz_0 - Liquidity Operations |
27 | | -Focuses on `provide_liquidity` and `withdraw_liquidity` instructions with simple invariants: |
28 | | -- Users cannot withdraw more tokens than they deposited (prevents theft) |
29 | | -- Token balances and reserves maintain consistency |
30 | | -- Position liquidity accounting is correct |
| 34 | +Exercises randomized `provide_liquidity` and `withdraw_liquidity` flows for multiple users after the pool is seeded with initial liquidity. The suite is mainly looking for accounting bugs in LP minting/burning, reserve updates, and per-user position tracking. |
| 35 | + |
| 36 | +The invariants focus on ensuring deposits move assets from users into the pool, withdrawals move assets back out in the correct direction, LP position liquidity only changes consistently with the action taken, and no user can withdraw materially more than they have contributed apart from tiny rounding dust. |
31 | 37 |
|
32 | 38 | ### fuzz_1 - Spot Trading |
33 | | -Focuses on `spot_swap` instructions with simple invariants: |
34 | | -- Buy swaps: trader base balance increases, quote balance decreases; pool base reserves decrease, quote reserves increase |
35 | | -- Sell swaps: trader base balance decreases, quote balance increases; pool base reserves increase, quote reserves decrease |
36 | | -- Reserve accounting matches DAO vault balances |
37 | | -- Pool maintains consistency (empty pool has zero reserves) |
| 39 | +Exercises repeated `spot_swap` buy and sell operations against a seeded spot pool. It is focused on catching incorrect reserve updates, fee accounting mistakes, and trader balance changes that move opposite to the intended swap direction. |
| 40 | + |
| 41 | +The invariants focus on swap-direction sanity for both the trader and the pool, plus end-of-iteration checks that on-chain spot reserves and protocol fee balances still reconcile with the DAO vault balances and that an empty pool cannot report non-zero reserves. |
38 | 42 |
|
39 | 43 | ### fuzz_2 - Conditional Trading (Simple Principle) |
40 | | -For conditional trading we avoid re-implementing AMM math in the fuzz test. |
41 | | -Instead, we check conservation-style invariants and token parity: |
42 | | - |
43 | | -- Underlying token conservation: |
44 | | - - Total `base` across tracked holders + base conditional vault underlying account stays constant. |
45 | | - - Total `quote` across tracked holders + quote conditional vault underlying account stays constant. |
46 | | -- Conditional token parity: |
47 | | - - Total pass-base equals total fail-base (over tracked owners). |
48 | | - - Total pass-quote equals total fail-quote (over tracked owners). |
49 | | -- Per-swap direction sanity: |
50 | | - - Trader input token does not increase. |
51 | | - - Trader output token does not decrease. |
52 | | - - Market pool reserve direction matches swap type (buy/sell). |
53 | | - |
54 | | -This catches leaks/mint-burn inconsistencies while staying independent from internal pricing/arbitrage math. |
| 44 | +Sets up an active futarchy proposal with conditional vaults and then fuzzes `conditional_swap` operations across the pass and fail markets. Instead of re-implementing the AMM pricing logic off-chain, this suite is aimed at detecting leaks, broken split/merge behavior, and incorrect conditional reserve movement through conservation-style checks. |
| 45 | + |
| 46 | +The invariants focus on total underlying token conservation across tracked holders and vaults, pass/fail token parity for both base and quote legs, and simple trade-direction checks that the trader spends the input asset, receives the output asset, and moves the selected conditional pool reserves in the expected direction. |
55 | 47 |
|
56 | 48 | ### fuzz_3 - Mixed Spot + Conditional Trading (Proposal Active) |
57 | | -This suite keeps DAO in `PoolState::Futarchy` (proposal launched and active) and fuzzes both: |
58 | | -- `spot_swap` flows for Alice/Bob |
59 | | -- `conditional_swap` (pass/fail, buy/sell) flows for Alice/Bob |
60 | | - |
61 | | -Invariant idea for this mixed suite: |
62 | | - |
63 | | -- Global conservation (no hidden mint/burn): |
64 | | - - Total tracked `base` underlying remains constant. |
65 | | - - Total tracked `quote` underlying remains constant. |
66 | | -- Conditional parity: |
67 | | - - Total pass-base equals total fail-base (over tracked owners). |
68 | | - - Total pass-quote equals total fail-quote (over tracked owners). |
69 | | -- Conditional trade sanity: |
70 | | - - Trader input token should not increase. |
71 | | - - Trader output token should not decrease. |
72 | | - - Selected conditional market reserves move in the expected direction. |
73 | | -- Spot trade sanity (while AMM is Futarchy): |
74 | | - - Spot buy: trader base should not decrease, trader quote should not increase. |
75 | | - - Spot sell: trader base should not increase, trader quote should not decrease. |
76 | | - |
77 | | -Why this approach: we validate accounting and directional behavior without copying the full |
78 | | -on-chain pricing/arbitrage math into the fuzz test. |
| 49 | +Keeps the DAO in active `PoolState::Futarchy` and mixes `spot_swap` and `conditional_swap` flows in the same run. This is the most integration-heavy futarchy suite: it is designed to catch accounting mismatches between the spot pool, conditional pools, and vault balances while both trading modes interact during an active proposal. |
| 50 | + |
| 51 | +The invariants focus on conservation of the underlying assets, pass/fail conditional token parity, directional sanity for both spot and conditional swaps, and aggregated vault-to-reserve alignment while the AMM is in futarchy mode. At the end of each run it also finalizes the proposal and checks that the system cleanly transitions back to spot mode with reserves and vault balances still aligned. |
| 52 | + |
| 53 | +### fuzz_launchpad - Launch Lifecycle |
| 54 | +Exercises the main `launchpad` lifecycle with mostly-valid but occasionally-invalid actions across `initialize_launch`, `start_launch`, `fund`, `close_launch`, `set_funding_record_approval`, `complete_launch`, `refund`, `claim`, and the post-completion paths for additional token allocation and performance package initialization. The suite is focused on state machine safety, custody of deposited funds, and making sure launch progression cannot be bypassed by malformed account combinations or bad signers. |
| 55 | + |
| 56 | +The invariants focus on whether each instruction preserves the expected launch state transitions, whether funding records and approval amounts stay consistent with committed funds, whether successful completion/refund/claim paths pay out from the right vaults to the right parties, and whether optional post-launch distribution steps remain tied to the finalized launch state. |
| 57 | + |
| 58 | +### fuzz_pbpp - Price Based Performance Package |
| 59 | +Exercises the full performance package flow: `initialize_performance_package`, `start_unlock`, `complete_unlock`, authority changes, and proposal/execution of package updates. The suite is focused on the package state machine around oracle-driven unlocking as well as the authority and recipient control paths that can mutate package configuration. |
| 60 | + |
| 61 | +The invariants focus on ensuring unlock only progresses when time and oracle conditions are satisfied, token release goes to the configured recipient path, administrative changes respect the expected authority/recipient permissions, and state transitions remain coherent as the package moves from locked to unlocking to completed or through approved configuration changes. |
| 62 | + |
| 63 | +### fuzz_mint_governor - Mint Authorization And Limits |
| 64 | +Exercises a simplified `mint_governor` flow centered on adding, updating, removing, and using a single mint authority. The suite is focused on two things only: unauthorized access should fail, and minting should respect the configured `max_total` limit for the authorized minter. |
| 65 | + |
| 66 | +The invariants focus on keeping the tracked governor configuration stable after initialization and ensuring the tracked mint-authority PDA either does not exist when removed or matches the expected authorized minter, configured mint cap, and cumulative minted amount when active. |
0 commit comments