Skip to content

Commit ca387a4

Browse files
authored
Update E2E documentation (#118)
* initial commit to update e2e documentation * config option fix * added text about etheno edge cases * docker instructions improved
1 parent 71c18ac commit ca387a4

File tree

1 file changed

+36
-7
lines changed

1 file changed

+36
-7
lines changed

program-analysis/echidna/end-to-end-testing.md

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,20 @@ $ cd drizzle-box
2424
$ npm i truffle
2525
```
2626

27-
If ganache and ganache-cli are not installed, add them manually. In our example, we will run:
27+
If `ganache` is not installed, add it manually. In our example, we will run:
2828

2929
```
30-
$ npm i ganache ganache-cli
30+
$ npm i ganache
3131
```
3232

3333
Other projects using yarn will require:
3434

3535
```
36-
$ yarn add ganache ganache-cli
36+
$ yarn add ganache
3737
```
3838

39+
Ensure that `$ ganache --version` outputs `ganache v7.3.2` or greater.
40+
3941
It is also important to select *one* test script from the available tests. Ideally, this test will deploy all (or most) contracts, including mock/test ones. For this example, we are going to take a look to the `SimpleStorage` contract:
4042

4143
```solidity
@@ -78,11 +80,31 @@ Before starting to write interesting properties, it is necessary to to collect a
7880

7981
First, start Etheno:
8082

83+
```bash
84+
$ etheno --ganache --ganache-args="--miner.blockGasLimit 10000000" -x init.json
8185
```
82-
$ etheno --ganache --ganache-args "--deterministic --gasLimit 10000000" -x init.json
86+
87+
By default the following Ganache arguments are set via Etheno:
88+
- `-d`: Ganache will use a pre-defined, deterministic seed to create all accounts.
89+
- `--chain.allowUnlimitedContractSize`: Allows unlimited contract sizes while debugging. This is set so that there is no size limitations on the contracts that are going to be deployed
90+
- `-p <port_num>`: The `port_num` will be set to (1) the value of `--ganache-port` or (2) Etheno will choose the smallest port number higher than the port number on which Etheno’s JSON RPC server is running.
91+
92+
**NOTE:** If you are using Docker to run etheno, the commands should be:
93+
94+
```bash
95+
$ docker run -it -p 8545:8545 -v ~/etheno:/home/etheno/ trailofbits/etheno
96+
(you will now be working within the Docker instance)
97+
$ etheno --ganache --ganache-args="--miner.blockGasLimit 10000000" -x init.json
8398
```
99+
- The `-p` in the _first command_ publishes (i.e. exposes) port 8545 from inside the Docker container out to port 8545 on the host.
100+
- The `-v` in the _first command_ maps a directory from inside the Docker container to one outside the Docker container. After Etheno exits, the `init.json` file will now be in the `~/etheno` folder on the host.
101+
84102

85-
If Etheno fails to produce any output, then it fails to execute `ganache`. Check if `ganache` can be executed correctly from your terminal.
103+
104+
Note that if the deployment fails to complete successfully due to a `ProviderError: exceeds block gas limit` exception, increasing the `--miner.blockGasLimit` value can help.
105+
This is especially helpful for large contract deployments. Learn more about the various Ganache command-line arguments that can be set by clicking [here](https://www.npmjs.com/package/ganache).
106+
107+
Additionally, if Etheno fails to produce any output, then it failed to execute `ganache` under-the-hood. Check if `ganache` (with the associated command-line arguments) can be executed correctly from your terminal without the use of Etheno.
86108

87109
Meanwhile, in another terminal, run *one* test or the deployment process. How to run it depends on how the project was developed. For instance, for truffle, use:
88110

@@ -102,9 +124,9 @@ In the Drizzle example, we will run:
102124
$ truffle test test/simplestorage.js --network develop.
103125
```
104126

105-
After Etheno finishes, gently kill it using ctrl+c (twice). It will save the `init.json` file. If your test fails for some reason or you want to run a different one, restart etheno and re-run the test.
127+
After Etheno finishes, gently kill it by using Ctrl+c (or Command+C on Mac). It will save the `init.json` file. If your test fails for some reason or you want to run a different one, restart Etheno and re-run the test.
106128

107-
## Writing and running a property:
129+
## Writing and running a property
108130

109131
Once we have a json file with saved transactions, we can verify that the `SimpleStorage` contract is deployed at `0x871DD7C2B4b25E1Aa18728e9D5f2Af4C4e431f5c`, so we can easily write a contract (`./contracts/crytic/E2E.sol`) with a simple a property to test it:
110132

@@ -119,6 +141,8 @@ contract E2E {
119141
}
120142
```
121143

144+
For large, multi-contract deployments, using `console.log` to print out the deployed, contract addresses can be valuable in quickly setting up the Echidna testing contract.
145+
122146
This simple property checks if the stored data remains constant. To run it you will need the following echidna config file (`echidna.yaml`):
123147

124148
```yaml
@@ -140,4 +164,9 @@ crytic_const_storage: failed!💥
140164
141165
For this last step, make sure you are using `.` as a target for `echidna-test`. If you use the path to the `E2E.sol` file instead, then Echidna will not be able get information from all the deployed contracts to call the `set(uint256)` function and the property will never fail.
142166

167+
## Key considerations:
168+
When using Etheno with Echidna, note that there are two edge cases that may cause unexpected behavior:
169+
1. Function calls that use ether: The accounts that are created and used for testing in Ganache are not the same as the accounts that are used to send transactions in Echidna. Thus, the account balances of the Ganache accounts do not carry over to the accounts used by Echidna. So, if there is a function call logged by Etheno that requires the transfer of some ether from an account that exists in Ganache, this call will fail in Echidna.
170+
2. Fuzz tests that rely on `block.timestamp`: The concept of time is different between Ganache and Echidna. Echidna always starts with a fixed timestamp while Etheno will use Ganache's concept of time. This means that assertions or requirements in a fuzz test that rely on timestamp comparisons / evaluations may fail in Echidna.
171+
143172
In the next part of this tutorial, we will explore how to easily find where contracts are deployed with a specific tool based on Slither. This will be useful if the deployment process is complex and we need to test an specific contract.

0 commit comments

Comments
 (0)