leonardoalt / yools

Tools for Yul.
GNU General Public License v3.0
137 stars 5 forks source link
ethereum evm formal-verification hacktoberfest solidity yul

yools - tools for Yul

Yools is [so far] an experimental symbolic execution engine for Yul. It translates Yul programs into sets of SMT constraints and queries an SMT solver to detect reachability of a certain program state. Currently the only user facing approach is to detect whether a program may revert or not.

What's supported

NOT THAT MUCH PLEASE BE PATIENT

Yul's entire syntax is supported, but not all EVM builtin functions are. The SMT encoding follows the usual BMC-style unrolling of loops up to a certain constant bound which can be chosen by the user. This means that results are not always sound in the presence of loops, and in such case results are always under the assumption that loops do not iterate over the given bound.

Usage

Currently there is one subcommand symbolic which contains the available features.

$ yools symbolic --help
yools-symbolic
Symbolically execute Yul programs checking for revert reachability

USAGE:
    yools symbolic [OPTIONS] --input <FILE.yul>

OPTIONS:
    -h, --help                         Print help information
    -i, --input <FILE.yul>             Yul source file
    -l, --loop-unroll <LOOP_UNROLL>    Loop unrolling limit [default: 10]
    -s, --solver <SOLVER>              SMT solver [default: cvc5]

Toy example:

// switch.yul
{
    let t := 0
    switch calldataload(0)
    case 0 { t := add(t, 10) }
    case 1 { t := add(t, 10) }
    case 2 { t := add(t, 10) }
    default { t := add(t, 10) }

    if iszero(eq(t, 10)) { revert(0, 0) }
}
$ yools symbolic -i switch.yul
All reverts are unreachable.

Why this

Most Formal Verification tools for Ethereum smart contracts focus on EVM bytecode, understandably. A few others target Solidity source code. Verifying Yul instead has some particular advantages over the 2 approaches:

Of course the approach used here also has disadvantages over the 2:

All approaches are valuable and can/should be used together.

Features

Please check the open issues to see what features are still not supported or are planned.

Research

One of the goals of this project is to allow for highly customizable semantics when generating the SMT constraints that represent the program. For example, there are different ways to represent calldata, memory, and storage symbolically. It is hard to tell in advance which might be better, and ultimately that can be also highly dependent on the analyzed Yul program as well. It is important to experiment with different approaches, and this is what we want to achieve.

A few potential directions are given below:

Calldata/Memory/Storage encoding

There are many different ways one may want to encode these memory regions symbolically. For example, storage is often encoded as an SMT Array from BV256 to BV256, which is convenient given that SLOAD and STORE always handle entire words. Memory, however, requires different handling due to single bytes being read/written. We would like to eventually experiment with different approaches to encode the 3 memory regions.

Function/loop summaries

TODO

ABI encoding/decoding abstraction

TODO

Parallelism

TODO

State variable abstraction

TODO

Revert data abstraction

TODO

External calls

TODO

Contributing

If you're interested in contributing please reach out! There are lots of exciting thing to do in different levels of Rust/SMT/Yul.