3 unstable releases

0.2.1 Feb 20, 2023
0.2.0 Feb 20, 2023
0.1.0 Jan 30, 2023

#757 in Database interfaces

AGPL-3.0

3MB
726 lines

Foundry 2 Echidna

The purpose of this tool is to transform the foundry broadcast JSON file to an Etheno-like JSON file for seamless Foundry integration with Echidna.

Demo

Demo GIF

Installation

Make sure you have Rust installed.

Install from crates.io: cargo install foundry2echidna

Install from source:

git clone https://github.com/ChmielewskiKamil/foundry2echidna/foundry2echidna &&
cd foundry2echidna &&
cargo install --path .

How to use it

Once you have foundry2echidna installed, you are ready to transform broadcast files.

  1. In the root of your Foundry project, run the command foundry2echidna. By default, if no arguments were passed, the tool will look for the following:
  • Your broadcast in broadcast/*.s.sol/31337/run-latest.json
  • And will output to src/crytic/init.json

You can pass custom input and output paths like this:

foundry2echidna --input-path path/to/broadcast.json --output-path path/to/init.json

Or, for short: foundry2echidna -i path/to/broadcast.json -o path/to/init.json

  1. Seed Echidna with the generated init.json file. Add the following to your echidna_config.yaml:
  • initialize: path/to/init.json (for your custom output path)
  • or initialize: src/crytic/init.json (for the default output path, if no arguments were provided)
  1. Update your EchidnaTest contract, just like you would be interacting with the contracts deployed on the blockchain.
  • Get the appropriate contract addresses from the broadcast file generated by Foundry (run-latest.json).
// Get address of the Counter contract from the broadcast file
counter = Counter(0x1234...);

// This works for contracts deployed by Factories and function calls as well
counterFactory = CounterFactory(0x456...);
anotherCounterDeployedByFactory = AnotherCounter(0x678...);
  1. Run Echidna.

Integrate foundry2echinda with your project

Here you can find dev documentation on docs.rs.

You can use the transform_broadcast function that takes two arguments:

  • input_path
  • output_path

to deserialize and serialize broadcast files.


Data Model (inner workings)

Etheno handles two main groups of events* (via EventSummaryPlugin):

  • Contract creations
  • Function calls

ContractCreated event has the following fields:

  • event - this is just the name of the type of the event -> ContractCreated
  • from - this is the address of the contract creator
  • contract_address - deployed contract address
  • gas_used - the amount of gas used in the transaction
  • gas_price - gas price used in the transaction
  • data - transaction data
  • value - Ether sent in the transaction

FunctionCall event has the following fields:

  • event - this is just the name of the type of the event -> FunctionCall
  • from - address of an account that made the call
  • to - address of an account that has been called
  • gas_used - the amount of gas used in the transaction
  • gas_price - gas price used in the transaction
  • data - transaction data
  • value - Ether sent in the transaction

*There is also block mined event, but it's not crucial for Echidna setup (?)

Foundry broadcast structure is more complicated than that, but we only care about a couple of fields. Since we want to transform the broadcast into this Etheno-like structure, the appropriate fields must be mapped together.

Etheno field Foundry field
event transactions[i].transaction_type
from transactions[i].transaction.from
to transactions[i].transaction.to
contract_address transactions[i].contract_address
gas_used receipts[i].gas_used
gas_price receipts[i].effective_gas_price
data transactions[i].transaction.data
value transactions[i].transaction.value

Dependencies