hacktricks/src/blockchain/smart-contract-security/mutation-testing-with-slither.md

117 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Mutation Testing za Solidity sa Slither (slither-mutate)
{{#include ../../banners/hacktricks-training.md}}
Mutation testing "tests your tests" tako što sistematski uvodi male promene (mutants) u vaš Solidity код и поново покреће ваш test suite. Ако тест не успе, mutant је killed. Ако тестови и даље пролазе, mutant преживи, откривајући слепу тачку у вашем test suite коју line/branch coverage не може да детектује.
Key idea: Coverage показује да је код извршен; mutation testing показује да ли је понашање заиста потврђено.
## Zašto coverage може зaварaти
Размотрите ову једноставну проверу прага:
```solidity
function verifyMinimumDeposit(uint256 deposit) public returns (bool) {
if (deposit >= 1 ether) {
return true;
} else {
return false;
}
}
```
Jedinični testovi koji proveravaju samo vrednost ispod i vrednost iznad praga mogu dostići 100% pokrivenost linija/grana, a ipak ne potvrditi granicu jednakosti (==). Refaktorisanje u `deposit >= 2 ether` i dalje bi prošlo takve testove, neprimetno narušivši logiku protokola.
Mutaciono testiranje otkriva ovaj nedostatak mutiranjem uslova i proverom da li testovi zakažu.
## Uobičajeni mutacioni operatori za Solidity
Slither-ov mehanizam za mutacije primenjuje mnoge male izmene koje menjaju semantiku, kao što su:
- Zamena operatora: `+``-`, `*``/`, etc.
- Zamena dodele: `+=``=`, `-=``=`
- Zamena konstanti: nenulta → `0`, `true``false`
- Negacija/zamena uslova unutar `if`/petlji
- Zakomentarisati cele linije (CR: Comment Replacement)
- Zameniti liniju sa `revert()`
- Zamena tipova podataka: npr. `int128``int64`
Cilj: eliminisati 100% generisanih mutanata, ili opravdati preživele jasnim obrazloženjem.
## Pokretanje mutacionog testiranja sa slither-mutate
Zahtevi: Slither v0.10.2+.
- Prikaži opcije i mutatore:
```bash
slither-mutate --help
slither-mutate --list-mutators
```
- Foundry primer (zabeleži rezultate i vodi kompletan log):
```bash
slither-mutate ./src/contracts --test-cmd="forge test" &> >(tee mutation.results)
```
- Ako ne koristite Foundry, zamenite `--test-cmd` načinom na koji pokrećete testove (npr. `npx hardhat test`, `npm test`).
Artefakti i izveštaji se podrazumevano čuvaju u `./mutation_campaign`. Neotkriveni (preživeli) mutanti se tamo kopiraju radi inspekcije.
### Razumevanje izlaza
Linije izveštaja izgledaju ovako:
```text
INFO:Slither-Mutate:Mutating contract ContractName
INFO:Slither-Mutate:[CR] Line 123: 'original line' ==> '//original line' --> UNCAUGHT
```
- Oznaka u uglastim zagradama je alias mutatora (npr., `CR` = Comment Replacement).
- `UNCAUGHT` znači da su testovi prošli pod mutiranim ponašanjem → nedostaje asercija.
## Smanjivanje vremena izvršavanja: prioritizujte mutante sa najvećim uticajem
Kampanje mutacije mogu trajati satima ili danima. Saveti za smanjenje troškova:
- Opseg: Počnite samo sa kritičnim ugovorima/direktorijumima, pa zatim proširite.
- Prioritetizujte mutatore: Ako mutant visokog prioriteta na liniji preživi (npr., cela linija je zakomentarisana), možete preskočiti varijante nižeg prioriteta za tu liniju.
- Paralelizujte testove ako vaš runner to omogućava; keširajte zavisnosti i build-ove.
- Fail-fast: zaustavite se rano kada promena jasno demonstrira prazninu u asercijama.
## Radni tok trijaže za mutante koji prežive
1) Pregledajte mutiranu liniju i ponašanje.
- Reproducirajte lokalno primenom mutirane linije i pokretanjem fokusiranog testa.
2) Ojačajte testove tako da proveravaju stanje, a ne samo povratne vrednosti.
- Dodajte provere granica jednakosti (npr., test threshold `==`).
- Proverite post-uslove: bilansi, total supply, efekti autorizacije i emitovani događaji.
3) Zamenite previše permisivne mock-ove realističnim ponašanjem.
- Osigurajte da mock-ovi nameću transfere, puteve greške i emitovanje događaja koji se dešavaju on-chain.
4) Dodajte invarijante za fuzz testove.
- Npr., očuvanje vrednosti, nenegativni saldi, invarijante autorizacije, monotonost supply-a gde je primenljivo.
5) Ponovo pokrenite slither-mutate dok preživeli ne budu uklonjeni ili dok se eksplicitno ne opravdaju.
## Studija slučaja: otkrivanje nedostajućih asercija stanja (Arkis protocol)
Kampanja mutacije tokom audita Arkis DeFi protocola je identifikovala preživele, kao što su:
```text
INFO:Slither-Mutate:[CR] Line 33: 'cmdsToExecute.last().value = _cmd.value' ==> '//cmdsToExecute.last().value = _cmd.value' --> UNCAUGHT
```
Komentarisanje dodele nije pokvarilo testove, što ukazuje na nedostatak post-state assertions. Osnovni uzrok: kod je verovao korisnički kontrolisanom `_cmd.value` umesto da verifikuje stvarne transfere tokena. Napadač bi mogao desinhronizovati očekivane i stvarne transfere kako bi isisao sredstva. Posledica: visok rizik po solventnost protokola.
Smernice: Smatrajte survivors koji utiču na value transfers, accounting, ili access control visokorizičnim dok nisu killed.
## Praktična kontrolna lista
- Pokrenite ciljanu kampanju:
- `slither-mutate ./src/contracts --test-cmd="forge test"`
- Razvrstajte survivors i napišite testove/invarijante koje bi pale pri mutiranom ponašanju.
- Proverite balances, supply, authorizations i events.
- Dodajte boundary testove (`==`, overflows/underflows, zero-address, zero-amount, empty arrays).
- Zamenite nerealne mocks; simulirajte failure modes.
- Iterirajte dok svi mutants ne budu killed ili opravdani komentarima i objašnjenjem.
## References
- [Use mutation testing to find the bugs your tests don't catch (Trail of Bits)](https://blog.trailofbits.com/2025/09/18/use-mutation-testing-to-find-the-bugs-your-tests-dont-catch/)
- [Arkis DeFi Prime Brokerage Security Review (Appendix C)](https://github.com/trailofbits/publications/blob/master/reviews/2024-12-arkis-defi-prime-brokerage-securityreview.pdf)
- [Slither (GitHub)](https://github.com/crytic/slither)
{{#include ../../banners/hacktricks-training.md}}