foundry-rs / foundry Goto Github PK
View Code? Open in Web Editor NEWFoundry 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
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
right now we use https://github.com/roynalnaruto/svm-rs/ and call out to the binary: https://github.com/gakonst/dapptools-rs/blob/f9cde71d7eaf115f624974d533bd347b8e959d59/dapp/src/solc.rs#L62
prelim benchmarks are promising:
https://forum.openzeppelin.com/t/a-faster-solidity-compiler-cli-in-rust/2546
https://github.com/axic/solc-rust
https://github.com/spalladino/solc-rs
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
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
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
.
brockelmore/rust-cevm@30eefd0 pretty clean
https://github.com/brockelmore/rust-cevm/search?q=fork+backend
if we can parallelize requests with join
s, multithreaded tokio runtime etc. to get very high performance that'd be great
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
.
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
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
because we're deploying contracts via the runtime_bytecode
. we probably should be doing sputnik.create_call
with the full bytecode.
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.
HEVM OG implementation: https://github.com/dapphub/dapptools/blob/a2b96cc2dbc28508c9fe699d6438bf6eccafc2ad/src/hevm/src/EVM.hs#L1929-L2058
@brockelmore cheat codes in his fork of sputnik
https://github.com/brockelmore/rust-cevm/blob/35cdefb760d41197ccfadc8c446343f20eba9080/testing/src/tester/mod.rs#L204-L290
https://github.com/brockelmore/rust-cevm/blob/35cdefb760d41197ccfadc8c446343f20eba9080/src/executor/stack.rs#L857-L930
"evmodin::Message
does not have this field"
Since we depend on the github repo, evmodin::Message
changed out from under us. If you update your registry you'll see the error.
Relevant link: https://github.com/vorot93/evmodin/blob/767c310aba2e9f8e303af852915ae7a3afc010a2/src/common.rs#L170-L200
With Gitpod and dapptools.rs, you should really be able to develop anywhere, from whatever device.
It could be interesting to offer it as an option and relatively easy to surface the integration.
look for
under:
$HOME/
$HOME/.foundry
$HOME/.config/foundry
We need to expand the fuzz_param
function to generate proptest strategies for other types.
We should also look into how this would work for Abi Encoder V2 types.
(The same should be done for the encode_input
function so that we can convert any type from String to a Token
)
Feature branch towards release: https://github.com/odyslam/dapptools.rs/tree/release-prep
Latest commit: https://fb6306eb.dapptools-rs.pages.dev/
as title
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
new evm is in town, with tracing support 💯 https://github.com/bluealloy/revm/ - let's integrate it
Implement a debug feature where the user can go through the smart contract, Opcode by Opcode.
Since many people are familiar with console.sol we should support it. It'd be simply a new call
hook inside the Handler where instead of hooking on the CHEATCODE_HANDLER, we'd hook on CONSOLE_ADDRESS
Relatedly, dapptools-style logs via emitted event logs were implemented in #96
As title, right now we need to either manually specify them or via the DAPP_REMAPPINGS
env var
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.
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:
I would love to see a dapptools-template port using dapptools-rs after the first release.
#[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)
Echidna has a feature called "constant mining" where it scrapes return values and adds those values to its dictionary to retry as inputs later.
Without this feature, Echidna would (and did) miss the Dappsys DSChief bug.
wasm-pack build
work and add to CIideally abstract over the backend so we can use both of the below:
https://github.com/AltSysrq/proptest
https://github.com/BurntSushi/quickcheck
instead using just the function selector as calldata, detect if the function has args and generate random inputs for N iterations
https://github.com/gakonst/dapptools-rs/blob/master/dapp/src/runner.rs#L104
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
@transmissions11 leaked some alpha by @MrChico from the dapphub chat
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
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
alternatives:
metrics:
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:
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.
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.
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.
@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
};
Both live under https://github.com/gakonst/ethers-rs/tree/master/ethers-signers/src/
Implemented in 2 steps:
Fuzzing is great but it does not cover all potential code paths, it just sprays and prays randomly right now
Create a Rust Symbolic EVM which we ideally implement the Evm
trait for so that it can be used seamlessly in forge
.
should we create a place to discuss things? there are several approaches:
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?
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
➜ 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
so that we can deploy contracts
bonus points for etherscan verification (multi or single file?). maybe @PaulRBerg's code can useful here https://github.com/paulrberg/multisol/
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:
- --diff
flag that shows how much gas usage changed from the last snapshot
- Gas snapshots for fuzz tests
testAddThatExitsEarlyOnLargeNumbers(100-500) = ~5000 gas
testAddThatExitsEarlyOnLargeNumbers(500+) = ~100 gas
related: dapphub/dapptools#761
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.