Coder Social home page Coder Social logo

foundry-rs / foundry Goto Github PK

View Code? Open in Web Editor NEW
7.6K 73.0 1.5K 34.7 MB

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.

Home Page: https://getfoundry.sh

License: Apache License 2.0

Rust 99.59% Solidity 0.10% Shell 0.25% Dockerfile 0.04% Nix 0.03%
rust solidity evm testing fuzzing mainnet-fork blockchain ethereum tooling framework eth dapp seth dapptools

foundry's Introduction

Foundry logo

Foundry

Github Actions Telegram Chat Telegram Support

Install | User Book | Developer Docs | Crate Docs

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.

Foundry consists of:

  • Forge: Ethereum testing framework (like Truffle, Hardhat and DappTools).
  • Cast: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
  • Anvil: Local Ethereum node, akin to Ganache, Hardhat Network.
  • Chisel: Fast, utilitarian, and verbose solidity REPL.

Need help getting started with Foundry? Read the 📖 Foundry Book (WIP)!

Demo

Installation

See the installation guide in the book.

If you're experiencing any issues while installing, check out Getting Help and the FAQ.

Forge

Features

  • Fast & flexible compilation pipeline
    • Automatic Solidity compiler version detection & installation (under ~/.svm)
    • Incremental compilation & caching: Only changed files are re-compiled
    • Parallel compilation
    • Non-standard directory structures support (e.g. Hardhat repos)
  • Tests are written in Solidity (like in DappTools)
  • Fast fuzz testing with shrinking of inputs & printing of counter-examples
  • Fast remote RPC forking mode, leveraging Rust's async infrastructure like tokio
  • Flexible debug logging
    • DappTools-style, using DsTest's emitted logs
    • Hardhat-style, using the popular console.sol contract
  • Portable (5-10MB) & easy to install without requiring Nix or any other package manager
  • Fast CI with the Foundry GitHub action.

How Fast?

Forge is quite fast at both compiling (leveraging ethers-solc) and testing.

See the benchmarks below. More benchmarks can be found in the v0.2.0 announcement post and in the Convex Shutdown Simulation repository.

Testing Benchmarks

Project Forge DappTools Speedup
transmissions11/solmate 2.8s 6m34s 140x
reflexer-labs/geb 0.4s 23s 57.5x
Rari-Capital/vaults 0.28s 6.5s 23x

Note: In the above benchmarks, compilation was always skipped

Compilation Benchmarks

Compilation benchmarks

Takeaway: Forge compilation is consistently faster by a factor of 1.7-11.3x, depending on the amount of caching involved.

Cast

Cast is a swiss army knife for interacting with Ethereum applications from the command line.

More documentation can be found in the cast package.

Configuration

Using foundry.toml

Foundry is designed to be very configurable. You can configure Foundry using a file called foundry.toml in the root of your project, or any other parent directory. See config package for all available options.

Configuration can be arbitrarily namespaced by profiles. The default profile is named default (see "Default Profile").

You can select another profile using the FOUNDRY_PROFILE environment variable. You can also override parts of your configuration using FOUNDRY_ or DAPP_ prefixed environment variables, like FOUNDRY_SRC.

forge init creates a basic, extendable foundry.toml file.

To see your current configuration, run forge config. To see only basic options (as set with forge init), run forge config --basic. This can be used to create a new foundry.toml file with forge config --basic > foundry.toml.

By default forge config shows the currently selected foundry profile and its values. It also accepts the same arguments as forge build.

DappTools Compatibility

You can re-use your .dapprc environment variables by running source .dapprc before using a Foundry tool.

Additional Configuration

You can find additional setup and configurations guides in the Foundry Book:

Contributing

See our contributing guidelines.

Getting Help

First, see if the answer to your question can be found in book, or in the relevant crate.

If the answer is not there:

If you want to contribute, or follow along with contributor discussion, you can use our main telegram to chat with us about the development of Foundry!

Acknowledgements

  • Foundry is a clean-room rewrite of the testing framework DappTools. None of this would have been possible without the DappHub team's work over the years.
  • Matthias Seitz: Created ethers-solc which is the backbone of our compilation pipeline, as well as countless contributions to ethers, in particular the abigen macros.
  • Rohit Narurkar: Created the Rust Solidity version manager svm-rs which we use to auto-detect and manage multiple Solidity versions.
  • Brock Elmore: For extending the VM's cheatcodes and implementing structured call tracing, a critical feature for debugging smart contract calls.
  • All the other contributors to the ethers-rs & foundry repositories and chatrooms.

foundry's People

Contributors

bernard-wagner avatar brockelmore avatar calldata avatar ckoopmann avatar clabby avatar danipopes avatar devanoneth avatar evalir avatar gakonst avatar github-actions[bot] avatar grandizzy avatar joshiedo avatar jpopesculian avatar klkvr avatar mattsse avatar mds1 avatar meetmangukiya avatar ncitron avatar ngotchac avatar odyslam avatar onbjerg avatar paulrberg avatar psushi avatar rkrasiuk avatar shawnharmsen avatar shekhirin avatar tarrencev avatar transmissions11 avatar tynes avatar zerosnacks avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

foundry's Issues

dapp build parity

Currently dapp build dumps Name -> CompiledContract to dapp.sol.json, essentially the core output of ethers::Solc::build

whereas the OG's output is { contracts: { "path": {"name: {"abi": [..], "evm": {..}, "metadata" }} }}

To get the same out, probably some changes are needed for ethers as well

dapp build creates non-deterministic json structure

Running the same dapp build will create different json files that are structurally the same, but are serialized in a different order. The order is reversed at random intervals.

For example, one invocation may create a json file that defines ContractA and then ContractB, while the next invocation may create a json file that defines ContractB and then ContractA.

While the json are interchangeable, they are not identical and they can't be compared as strings.

This was discovered when setting up tests for brew, which tested the output of dapp build.

Screenshot 2021-09-22 at 3 01 15 PM
.

solc corruption

If I disrupt solc download (e.g ctrl + c), then the installation is corrupted and no tests can run. I have to remove ~/.svm with rm -rf and try again.

It should fail gracefully, or detect the corruption on start and download again.

image

jsonrpc node over the evm instance used

given an implementer of the EVM trait mentioned in #23 and a database type (probably in-memory map), we should be able to run an RPC node that "acts" like a blockchain.

the logic under service could act as inspiration https://github.com/brockelmore/rust-cevm/blob/35cdefb760d41197ccfadc8c446343f20eba9080/service/src/EVM/mod.rs, but if possible we should try doing this with the tokio/hyper stack for performance reasons and the ability to inject extra middleware etc., e.g. https://github.com/tokio-rs/axum#usage-example with a jsonrpc module like how https://github.com/AtsukiTak/warp-json-rpc would work with https://github.com/seanmonstar/warp

ref: #174

Regex on contracts directory mismatches dapptools

Default contracts variable uses regex to locate files. Dapptools just makes you define the top level directory (i.e. ./contracts), where as rs makes you do ./contracts/**/*.sol. We should likely match them as otherwise you run into this if migrating from dapptools:

Compiling files under ./contracts
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 21, kind: IsADirectory, message: "Is a directory" }', solc/src/lib.rs:199:30
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Abstract away forking to a proper cache

#[derive(Clone)]
pub struct Cache<Value> {
    inner: Arc<RwLock<InnerCache<T>>,
}

struct InnerCache<T> {
    cached: HashMap<String, CachedValue<T>>,
}

Since the values are retrieved via async, we probably need something like this to keep track if we're currently fetching some value

pub enum CachedValue<Value> {
    Cached(Value),
    Pending(<Maybe the future that returns the Value>),
}

Perhaps this can be simplified with lru::Cache or the cached crate which supports async

Originally posted by @mattsse in #70 (comment)

Improve accessibility for all EVM languages

With the development and rise of EVM focused programming languages - besides Vyper and Solidity - like Fe and Sway I think we should make it as easy as possible to make dapptools-rs accessible for these languages.

I don't have enough knowledge at the moment to assess if this is already possible or how big the effort would be to make the integration as easy as possible for future languages.

Gas snapshotting wishlist

  • Account for gas refunds! OG tools does not right now.

  • Don't include test call overhead in gas snapshots. OG tools includes some of the overhead rn:

Screen Shot 2021-11-16 at 4 42 42 PM

Screen Shot 2021-11-16 at 4 42 21 PM

  • - --diff flag that shows how much gas usage changed from the last snapshot

    • Summarizes % change of aggregated gas usage across all test funcs
    • Leaderboard for which tests' gas usage changed the most (by %).
      • Show gas units diff and % diff
  • - Gas snapshots for fuzz tests

    • Median & mean
    • Gas usage per range of inputs like:
testAddThatExitsEarlyOnLargeNumbers(100-500) = ~5000 gas
testAddThatExitsEarlyOnLargeNumbers(500+) = ~100 gas
  • Breakdown of not only gas usage of tests but gas usage of functions the tests call like hardhat-gas-reporter

image

related: dapphub/dapptools#761

  • flamegraphs like tenderly

image

Strange `No such file` error

Using yam repo, and running any of the following results in a weird error:

Inside the scripts folder run:

$ dapp test --fork-url "https://c2b849cff6a24e57beeac6bae21033b1.eth.rpc.rivet.cloud/" --verbosity 5 --match test_onchain_prop_18 --contracts=../contracts

changing the contracts directory to renamed as src:

dapp test --fork-url "https://c2b849cff6a24e57beeac6bae21033b1.eth.rpc.rivet.cloud/" --verbosity 5 --match test_onchain_prop_18

both result in this unhelpful error:

Oct 18 16:52:24.479 ERROR dapp: error=No such file or directory (os error 2)
Error: No such file or directory (os error 2)

Location:
    /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/result.rs:1675:27

good auto config options

look for

  • requirements.txt (#181)
  • .dapprc
  • .forgerc

under:

  • the current directory
  • $HOME/
  • $HOME/.foundry
  • $HOME/.config/foundry

Flaky installation of Solc on CI

We use svm-rs by @roynalnaruto, which is used for managing the global solc binary's version, by installing each version under ~/.svm/4version/solc-$version. For some reason, when running on CI the installation process seems to be flaky, e.g. below:

telegram-cloud-photo-size-2-5366071301866894295-y

We should fix that. Maybe there's a bug downstream in svm-rs (e.g. there should be some sort of global mutex that says "hey a solc version is being installed right now, wait for it to unlock before you try running solc"

I tried doing that manually with the lock inside solc/lib.rs but it was not enough apparently.

Support piped input for encode/decode commands

➜  dapptools-rs git:(master) ✗ cargo run --bin seth -- --to-ascii 0x547572626f44617070546f6f6c73
    Finished dev [unoptimized + debuginfo] target(s) in 0.46s
     Running `target/debug/seth --to-ascii 0x547572626f44617070546f6f6c73`
TurboDappTools

➜  dapptools-rs git:(master) ✗ echo '0x547572626f44617070546f6f6c73' | cargo run --bin seth -- --to-ascii
    Finished dev [unoptimized + debuginfo] target(s) in 0.30s
     Running `target/debug/seth --to-ascii`
error: The following required arguments were not provided:
    <hexdata>

USAGE:
    seth --to-ascii <hexdata>

For more information try --help

Currently these commands need to be able to accept piped input:

  • --from-ascii
  • --to-checksum-address
  • --to-ascii
  • --to-bytes32
  • --to-dec
  • --to-fix
  • --to-hex
  • --to-hexdata
  • --to-uint256
  • --to-wei

Symbolic Rust EVM

benchmarks against other clients

alternatives:

  • hardhat
  • truffle
  • upstream dapptools

metrics:

  • compilation time
  • unit tests time
  • symbolic tests time & memory usage

stdlib support

Requested feature

It'd be nice if we could import popular contracts in our Solidity without needing to install them as libraries. An example of that in the wild is Hardhat's console.sol being available as import hardhat/console.sol.

Suggested solution

We’d include_str the solidity for some contracts in the binary, and when parsing the solidity imports in ethers-solc, we’d see if any of these are imported as ``import ‘std/Vm.sol’` and inject them (cc @mattsse ).

Example usage: Cheatcodes, maybe Solmate or some subset of it, ..?

That’d make it very easy to run forge test Foo.sol where inside it imports popular stuff, for writing quick testing ‘scripts’ effectively. It also saves you from having to maintain a ds-test submodule lib

abstract over EVM implementation

instead of being compatible only with Sputnik, ideally we should define a trait EVM which has the functions we need (e.g. call) and we implement it for all EVMs we have. This would allow us to have better benchmarks, feature sets etc. It also means that we could use HEVM for any symbolic tests and fast Rust EVMs for everything else

fuzzing should abstract strings into bytes

Accurate fuzzing of a contract should fuzz a string with pure bytes. The reason is rust's String is utf8, and most tooling (notable, abi encoder) expects the string to truly be a utf8 string. The issue arises that the evm doesn't actually care if its true utf8 - it just treats it as bytes. So an attacker could construct a non-utf8 set of bytes and pass it as an input of a string parameter.

If a contract relies on strict utf8 encoding, the fuzzer will always miss this. Issues arise because the abi encoder expects an utf8 string so its a bit of a pain to work around but should be done

Invariant Testing

@transmissions11 leaked some alpha by @MrChico from the dapphub chat

telegram-cloud-photo-size-1-5096339203830163703-x
telegram-cloud-photo-size-1-5096339203830163702-x

This algorithm should be easy to do inside our fuzzer logic.

you should run the invariant func once before you do any txs
Because sometimes it doesn’t hold off the bat but then that changes after txs or if all the txs revert then the invariant will show as passed when it may have totally failed if ever called
dapphub/dapptools#745

Remove `Clone` trait bound from EVM

The Problem

In #44 we made required EVM to be Clone with the following rationale:

A requirement of fuzzing was to make the EVM cloneable, since the TestRunner only accepts Fns which cannot mutate their environment, meaning that we had to add a Clone restriction on it in the fuzzing-related code.

..and also noted:

if we can remove the Clone requirement by using a factory, and splitting the fuzz tests to a separate function so we can run fuzz tests w/o tracing even when the EVM uses a tracer in non-fuzz tests

We worked around this requirement by patching our dependencies and making the EVMs clone-able. This probably won't scale well given that EVMs may own or reference state or tracers that cannot be cloned or is too expensive to clone, so we'll need to fix this ASAP.

Possible Solution

@vorot93 suggested that instead of Clone'ing, we could use a factory function like so:

let evm_factory = || {
    EvmOdin::new(...)
};
let factory_fn = || {
    let mut evm = (evm_factory)()
    evm.setup();
    evm
};

seth feature parity

Problem & Context

Currently, cast and its cli are not at feature parity with seth.

All of Seth's commands can be found here, and the so far implemented cast commands can be found here.

Solution

Pick any of the commands that are not implemented, and go for it!

Some reference PRs on how this was done for other commands for newcomers can be seen below:

Installing with Homebrew doesn't work

Description

I used the command from dapptools.rs:

$ brew install dapptools-rs

But I got this error:

Warning: No available formula or cask with the name "dapptools-rs".
==> Searching for similarly named formulae...
Error: No similarly named formulae found.
==> Searching for a previously deleted formula (in the last month)...
Error: No previously deleted formula found.
==> Searching taps on GitHub...
Error: No formulae found in taps.

Environment

create a a discussion community

should we create a place to discuss things? there are several approaches:

  1. github issue
  2. github discussion
  3. discord
  4. telegram
  5. or reuse dappchat...

Add rustfmt.toml

suggested options

reorder_imports = true
imports_granularity = "Crate"
max_width = 120  # default is 100
use_small_heuristics = "Max"
comment_width = 100
wrap_comments = true
binop_separator = "Back"
trailing_comma = "Vertical"
trailing_semicolon = false
use_field_init_shorthand = true

Configs are listed here https://rust-lang.github.io/rustfmt/?version=v1.4.36

Any directory named `lib` in contracts dir throws error

When you have a structure like this:

./
|->lib
|->src
      |-> lib
      |-> my_thing
...

The automated remapping tries to treat the ./src/lib directory as a remapping directory and will likely fail because of that (seen here). I don't know upstream ramifications of a change like this, but it is one option:

 /// Gets all the remappings detected
    pub fn find_many(path: &str) -> eyre::Result<Vec<Self>> {
        let path = std::path::Path::new(path);

        if let Ok(paths) = std::fs::read_dir(path) {
            let remappings = paths
                .into_iter()
                // TODO: Surely there must be a better way to convert to str
                .map(|path| Self::find(&path?.path().display().to_string()))
                // Do we want to silently ignore the errors?
                .filter_map(|x| x.ok())
                .collect();
            Ok(remappings)
        } else {
            Ok(vec![])
        }
    }

Basically just ignore any errors when remapping fails for a directory. This would likely hide error associated with other remappings?

nicer API for writing pure Rust tests

We already support non-Solidity tests as shown here, but gotta make the API better: https://github.com/gakonst/dapptools-rs/blob/master/dapp/src/multi_runner.rs#L191-L227.

The nicest way to write Solidity tests, would be to write an ethers-rs middleware that instead of doing RPC requests (https://github.com/gakonst/ethers-rs/blob/master/ethers-providers/src/provider.rs#L124), it’d do direct EVM calls. I think this is doable and tbh is ~equivalent to Solidity tests. All dapp test really does is continuously call all sol functions starting with test* by directly calling the EVM, so really just an abstraction

structured stack & call traces

dapptools / hardhat-style tracing are extremely good. evmodin has utilities for that natively with its interrupts API and there's open PRs to do that in sputnik

dapptools trace is just too good to not have:
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.