├── src ├── lib.rs ├── main.rs └── ast.rs ├── Cargo.toml ├── .gitignore ├── rust-toolchain ├── test └── basic.smt2 ├── Cargo.lock ├── .envrc ├── shell.nix ├── default.nix ├── .github └── workflows │ └── build.yaml ├── flake.nix ├── readme.md └── flake.lock /src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pub mod ast; 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "solver" 3 | version = "0.1.0" 4 | edition = "2021" 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # cargo 2 | /target 3 | 4 | # nix 5 | /result 6 | 7 | # direnv 8 | /.direnv 9 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.59" 3 | components = [ "cargo", "rustc", "rust-src", "rustfmt", "clippy" ] 4 | profile = "default" 5 | -------------------------------------------------------------------------------- /test/basic.smt2: -------------------------------------------------------------------------------- 1 | (declare-fun foo (Int) Bool) 2 | (declare-const a Bool) 3 | (declare-const b Bool) 4 | (assert (and a (foo b))) 5 | (check-sat) 6 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "solver" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # use nix_direnv for flakes if we can 4 | if nix flake metadata > /dev/null 2>&1 && has nix_direnv_version; then 5 | use_flake 6 | else 7 | use_nix 8 | fi 9 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | use std::env; 4 | 5 | fn main() { 6 | let file_to_convert = env::args() 7 | .nth(1) 8 | .expect("Expected SMTLIB file with file extension"); 9 | println!("{}", file_to_convert); 10 | } 11 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | (import 2 | ( 3 | let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in 4 | fetchTarball { 5 | url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; 6 | sha256 = lock.nodes.flake-compat.locked.narHash; 7 | } 8 | ) 9 | { src = ./.; } 10 | ).shellNix 11 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | (import 2 | ( 3 | let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in 4 | fetchTarball { 5 | url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; 6 | sha256 = lock.nodes.flake-compat.locked.narHash; 7 | } 8 | ) 9 | { src = ./.; } 10 | ).defaultNix 11 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | on: [push] 2 | 3 | name: build 4 | 5 | jobs: 6 | check: 7 | name: build & test 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Install toolchain 12 | run: rustup show 13 | - name: Run cargo check 14 | uses: actions-rs/cargo@v1.0.1 15 | with: 16 | command: check 17 | -------------------------------------------------------------------------------- /src/ast.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-only 2 | //! Post typechecking AST, we only support QF_EUF at the moment 3 | 4 | pub struct Problem(Vec); 5 | 6 | pub enum Command { 7 | Assert(BoolOp), 8 | DeclareFun(String, Vec, Atom), 9 | DeclareVar(String, Atom), 10 | CheckSat(), 11 | GetModel(), 12 | } 13 | 14 | pub enum Atom { 15 | Bool(), 16 | BV(), 17 | } 18 | 19 | pub enum PolyOp { 20 | Eq(Vec), 21 | ITE(Box, Box, Box), 22 | } 23 | 24 | pub enum BVOp { 25 | Shr(Box, Box), 26 | Shl(Box, Box), 27 | Concat(Box, Box), 28 | Extract(usize, usize), 29 | BVNot(Box), 30 | BVNeg(Box), 31 | // ... more to come 32 | } 33 | 34 | pub enum BoolOp { 35 | LitBool(bool), 36 | VarBool(String), 37 | 38 | Not(Box), 39 | And(Vec), 40 | Or(Vec), 41 | XOr(Vec), 42 | Impl(Vec), 43 | Distinct(Vec), 44 | } 45 | 46 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | fenix = { 4 | url = "github:nix-community/fenix"; 5 | inputs.nixpkgs.follows = "nixpkgs"; 6 | }; 7 | flake-utils.url = "github:numtide/flake-utils"; 8 | naersk = { 9 | url = "github:nmattia/naersk"; 10 | inputs.nixpkgs.follows = "nixpkgs"; 11 | }; 12 | nixpkgs.url = "nixpkgs/nixos-unstable"; 13 | }; 14 | 15 | outputs = { self, fenix, flake-utils, naersk, nixpkgs }: 16 | flake-utils.lib.eachDefaultSystem (system: let 17 | pkgs = nixpkgs.legacyPackages.${system}; 18 | # TODO: figure out how to read this from the toochain file directly 19 | toolchain = fenix.packages.${system}.toolchainOf { 20 | channel = "1.59"; 21 | sha256 = "sha256-4IUZZWXHBBxcwRuQm9ekOwzc0oNqH/9NkI1ejW7KajU="; 22 | }; 23 | in { 24 | defaultPackage = (naersk.lib.${system}.override { 25 | inherit (toolchain) cargo rustc; 26 | }).buildPackage { 27 | src = ./.; 28 | }; 29 | 30 | devShell = pkgs.mkShell { 31 | nativeBuildInputs = [ (toolchain.withComponents [ 32 | "cargo" "rustc" "rust-src" "rustfmt" "clippy" 33 | ])]; 34 | }; 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # solver 2 | 3 | This is a shared project from a few groups working on tooling for verification of ethereum smart contracts. 4 | 5 | The aim is to build out a new SMT solver focused on efficient solving for the kind of queries 6 | commonly encountered when modelling smart contracts in smt. Essentially this means we want to 7 | optimize for non linear arithmetic over 256 bit bitvectors. We additionally aim to support 8 | uninterpreted functions and arrays. Support for other theories is not currently planned. 9 | 10 | We believe that starting a new solver instead of extending an existing solver has the following 11 | benefits: 12 | 13 | - A smaller domain focused solver should be able to achieve better performance when compared to a 14 | larger and more general system 15 | - Adding proofs to an existing solver can be a complex task. A new solver can be built from the 16 | ground up with efficient proof generation as a core design goal. The restricted set of theories is 17 | also helpful here. 18 | - Existing solvers make heavy use of bit-blasting when solving bit vector problems, while this works 19 | well for small bv instances, it does not scale to the 256bit needed when analysing evm programs. We 20 | intend to research and apply techniques more appropriate to very large bv instances (even at 21 | the expense of performance on small bv instances) 22 | - We can use a more modern toolchain (rust > c/c++) 23 | 24 | ## Development 25 | 26 | You need cargo 1.59 on your `PATH`. For nix users a `shell.nix` is provided that contains all 27 | required development dependencies. 28 | 29 | ``` 30 | cargo build # build 31 | cargo run # run 32 | ``` 33 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "fenix": { 4 | "inputs": { 5 | "nixpkgs": [ 6 | "nixpkgs" 7 | ], 8 | "rust-analyzer-src": "rust-analyzer-src" 9 | }, 10 | "locked": { 11 | "lastModified": 1649226351, 12 | "narHash": "sha256-5fQwF5kYpPC7w0SOfdbE9Z7o5/i/dyo1BxMLVCA2h3E=", 13 | "owner": "nix-community", 14 | "repo": "fenix", 15 | "rev": "c7e184561fe843abb861cd7d22c23066987078e2", 16 | "type": "github" 17 | }, 18 | "original": { 19 | "owner": "nix-community", 20 | "repo": "fenix", 21 | "type": "github" 22 | } 23 | }, 24 | "flake-utils": { 25 | "locked": { 26 | "lastModified": 1648297722, 27 | "narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=", 28 | "owner": "numtide", 29 | "repo": "flake-utils", 30 | "rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade", 31 | "type": "github" 32 | }, 33 | "original": { 34 | "owner": "numtide", 35 | "repo": "flake-utils", 36 | "type": "github" 37 | } 38 | }, 39 | "naersk": { 40 | "inputs": { 41 | "nixpkgs": [ 42 | "nixpkgs" 43 | ] 44 | }, 45 | "locked": { 46 | "lastModified": 1649096192, 47 | "narHash": "sha256-7O8e+eZEYeU+ET98u/zW5epuoN/xYx9G+CIh4DjZVzY=", 48 | "owner": "nmattia", 49 | "repo": "naersk", 50 | "rev": "d626f73332a8f587b613b0afe7293dd0777be07d", 51 | "type": "github" 52 | }, 53 | "original": { 54 | "owner": "nmattia", 55 | "repo": "naersk", 56 | "type": "github" 57 | } 58 | }, 59 | "nixpkgs": { 60 | "locked": { 61 | "lastModified": 1649225869, 62 | "narHash": "sha256-u1zLtPmQzhT9mNXyM8Ey9pk7orDrIKdwooeGDEXm5xM=", 63 | "owner": "NixOS", 64 | "repo": "nixpkgs", 65 | "rev": "b6966d911da89e5a7301aaef8b4f0a44c77e103c", 66 | "type": "github" 67 | }, 68 | "original": { 69 | "id": "nixpkgs", 70 | "ref": "nixos-unstable", 71 | "type": "indirect" 72 | } 73 | }, 74 | "root": { 75 | "inputs": { 76 | "fenix": "fenix", 77 | "flake-utils": "flake-utils", 78 | "naersk": "naersk", 79 | "nixpkgs": "nixpkgs" 80 | } 81 | }, 82 | "rust-analyzer-src": { 83 | "flake": false, 84 | "locked": { 85 | "lastModified": 1649178056, 86 | "narHash": "sha256-dcf7vKAkpdNvjd243LTGkUD6zLaLPN5deM2WTysG/Zs=", 87 | "owner": "rust-analyzer", 88 | "repo": "rust-analyzer", 89 | "rev": "2366d8e05f5f3585f95058fa7427cbde079914ed", 90 | "type": "github" 91 | }, 92 | "original": { 93 | "owner": "rust-analyzer", 94 | "ref": "nightly", 95 | "repo": "rust-analyzer", 96 | "type": "github" 97 | } 98 | } 99 | }, 100 | "root": "root", 101 | "version": 7 102 | } 103 | --------------------------------------------------------------------------------