Skip to content

Commit bd3b0fc

Browse files
committed
full tutorial
1 parent 28eda32 commit bd3b0fc

1 file changed

Lines changed: 83 additions & 1 deletion

File tree

src/fuzz_tutorial.md

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,5 +157,87 @@ RUST_LOG=info ./target/release/movy sui fuzz
157157

158158
- `RUST_LOG=info` will print some helpful logs.
159159
- `-l ./test-data/counter` points to the target package with the Movy test modules.
160+
- `-o /tmp/out` will tell Movy to save outputs to `/tmp/out` and we will cover this later.
160161

161-
This shall work, but not really trigger a crash because the invariant always holds. You might simply modify the counter code from `counter.value = counter.value + n;` to something like `counter.value = counter.value + 1;` and rerun to see crashes happening.
162+
You could see logs like:
163+
164+
```
165+
[INFO movy_replay::env] Committing testing std 0x000000000000000000000000000000000000000000000000000000000000000b
166+
[INFO movy_replay::env] Committing testing std 0x0000000000000000000000000000000000000000000000000000000000000001
167+
[INFO movy_replay::env] Committing testing std 0x0000000000000000000000000000000000000000000000000000000000000002
168+
[INFO movy_replay::env] Committing testing std 0x0000000000000000000000000000000000000000000000000000000000000003
169+
...
170+
[INFO movy::sui::env] Deploying the local package at ./test-data/counter/
171+
[INFO movy_replay::env] Compiling ./test-data/counter/ with test mode...
172+
[INFO movy_replay::env] Detected a movy_init at: 0x9ae10865d456c2a9ebc47b754db3f77b96eebb049192a26fce0577aaca3a5e2a::counter_tests
173+
[INFO movy_replay::env] Commiting movy_init effects...
174+
...
175+
[INFO movy_fuzz::operations::sui_fuzz] [Client Heartbeat #0] run time: 33s, clients: 1, corpus: 3, objectives: 0, executions: 326, exec/sec: 9.632, code-fb: 68/16384 (0%), stability: 1/1 (100%)
176+
```
177+
178+
Generally, Movy does the following things to test the contracts.
179+
180+
- First, Movy will spin up an empty fork of the Chain, in this case, the Sui chain.
181+
- Movy will deploy the Sui standard framework to the fork in the testing mode, which enables the `0x1::unit_test` and `0x2::test_scenario`.
182+
- Then Movy will invoke the Move compiler to compile the given project `./test-data/counter` to obtain modules and their interfaces.
183+
- Movy further will deploy the modules to our fork (at `0x9ae10865d456c2a9ebc47b754db3f77b96eebb049192a26fce0577aaca3a5e2a`) and execute `movy_init` in the testing modules.
184+
- Once everything is ready, Movy starts to assemble random transactions. Gnerally, the `corpus` metrics indicates the number of interesting inputs, the `objectives` indicates the number of crashing inputs that violate invariants and `code-fb` refers to the code coverage.
185+
186+
## Trigger a Violation
187+
188+
The fuzzing in the previous section shall work, but not really trigger a crash because the invariant always holds. Now let's manually add a bug for our counter implementation:
189+
190+
```
191+
public fun increment(counter: &mut Counter, n: u64) {
192+
- counter.value = counter.value + n;
193+
+ counter.value = counter.value + 1;
194+
}
195+
```
196+
197+
Note we intentionally broke the invariant: only increase `1` though users request to increas `n`. Rerun Movy with the project and we could see:
198+
199+
```
200+
...
201+
[INFO movy_fuzz::operations::sui_fuzz] [Objective #0] run time: 24s, clients: 1, corpus: 2, objectives: 3, executions: 247, exec/sec: 10.27, code-fb: 104/16384 (0%), stability: 1/1 (100%), crash-fb: 118/16384 (0%)
202+
```
203+
204+
> In case you see errors like "The given output is already there....", rerun Movy with `-f` parameter to automatically remove the existing results. The mechanism is to prevent accidental removal of previous fuzzing campaigns.
205+
206+
Movy immediately could find a `objectives` and this indicates that we found the violations.
207+
208+
## Replay and Inspect a Violation
209+
210+
In addition to finding violations, Movy also supports inspect how violation happens by _replaying the violations_. Recall that we have the `-o /tmp/out` option to Movy to save outputs to `/tmp/out` and it is time to see the contents.
211+
212+
```bash
213+
> ls /tmp/out
214+
args.json crashes/ env.bin fuzz_meta.json queue/
215+
```
216+
217+
- `args.json` is the arguments that start Movy, i.e., the CLI parameters.
218+
- `fuzz_meta.json` is the metadata we setup for the fuzzing campaign, including the target contracts and their interfaces.
219+
- `env.bin` is a binary file that holds our forked chain contents.
220+
- `queue/` saves the interesting seeds and we can ignore it in this tutorial.
221+
- `crashes/` saves the violations Movy have found.
222+
223+
Since we have found some violations, we shall have at least `crashes/0.json` and we can replay it by providing the saved environment:
224+
225+
```
226+
RUST_LOG=info ./target/release/movy sui replay-seed \
227+
-s /tmp/out/crashes/0.json \
228+
-e /tmp/out/env.bin \
229+
-m /tmp/out/fuzz_meta.json \
230+
--trace
231+
```
232+
233+
> The output of a full trace is usually very long. Saving to a text file and using an editor is highly recommended.
234+
235+
This will print a full trace including everything during execution and we could see that:
236+
237+
```
238+
├─ 0x977654ad5e98ce5a09b7bbac3421b312aef7370b0bfc889e6181a8bcc23d8b9c:counter_tests:movy_post_increment(...)
239+
...
240+
│ └─ 0x977654ad5e98ce5a09b7bbac3421b312aef7370b0bfc889e6181a8bcc23d8b9c:oracle:crash_because(...)
241+
```
242+
243+
So the invariant violation happens exactly in `movy_post_increment`.

0 commit comments

Comments
 (0)