Phink is a blazing-fastβ‘, property-based, coverage-guided fuzzer for ink! smart contracts. It enables developers to embed inviolable properties into their smart contract testing workflows, equipping them with automatic tools to detect vulnerabilities and ensure contract reliability before deployment. Please, read the documentation in order to properly use Phink.
β οΈ This project is actively under development with new features and improvements being made regularly. Contributions and feedback are welcome!
For documentation, visit our documentation site here. If you have any question, feedback, features suggestion, join our Discord.
Install
Building from source
Requirements
Install the requirements, configure AFL++ plugins and adapt the system configs
Install Phink
If you prefer to install Phink manually, follow these steps:
&&
Install Phink via Docker
Alternatively, you can use Docker to set up and run Phink without needing to manually install dependencies. Detailed instructions are available in README.Docker.md. To build the Docker image:
Usage
Via normal installation
If installed via Docker
To use Phink via Docker, you can run:
For instrumenting a contract:
Refer to README.Docker.md for more detailed instructions on using Phink with Docker.
Example
Adding some invariants
Below are some invariants created for the dns contract.
- Add the
phink
feature to yourCargo.toml
[]
= []
- Create your invariants as below:
Catching an invariant
Below, the trace after executing the crash:
π Now fuzzing `/tmp/ink_fuzzed_XqUCn/target/ink/transfer.json` (5H31F11yQUkqugbgC7ur4rT2WLKSkZKAZUfcmHkKoLkaRaZ4)!
π€― An invariant got caught! Let's dive into it
π«΅ This was caused by `phink_assert_cannot_transfer_1337`
π Find below the trace that caused that invariant
π± Executing new seed
+---------+-------------------------------------------------------------------+
| Message | Details |
+---------+-------------------------------------------------------------------+
| pay_me | β½οΈ Gas required : Weight(ref_time: 591391866, proof_size: 28781) |
| | π₯ Gas consumed : Weight(ref_time: 582570121, proof_size: 12443) |
| | πΎ Storage deposit : StorageDeposit::Charge(0) |
| | πΈ Message was payable, and 1809739 units were transferred |
+---------+-------------------------------------------------------------------+
List of samples
You can find various sample ink! smart-contracts in the sample/
directory. For detailed descriptions of these samples
and
instructions on how to instrument them for testing with Phink, please refer to the sample's README
file.
Features and upcoming ideas
- Integration of a custom runtime, using a generic one by default
- Invariants-based fuzzing
- Detection of incorrect arithmetic, reentrancy, and panic handlers
- Handling of ink! specific encoding and constructors
- Automatic contract instantiation
- Crafting multiple messages in a single transaction
- Visualization of ink! contract coverage
- Proper binary usage
- Enabling multi-contract fuzzing and cross-contract interactions
- Seed extraction out of unit and end-to-end tests
- Development of a custom fuzzing dashboard (default options: Ziggy/AFL++/Honggfuzz dashboard)
- Creation of default invariants common to every contract (research needed)
- Implementation of a snapshot-based fuzzing approach (research needed)