Skip to content
This repository was archived by the owner on Oct 10, 2024. It is now read-only.

Commit 764c45a

Browse files
authored
Echidna tests and slither fixes (#543)
* Fix existing tests and update README.md * Parallelize CircleCI tests * Ignore some slither detectors * Ignore more slither detectors and fix tests * Add slither configuration file * Speed up mythril tests and remove unnecessary slither flags * Reduce timeout and sign commit * Change mythril timeout
1 parent f8c93e3 commit 764c45a

22 files changed

+241
-442
lines changed

.circleci/config.yml

Lines changed: 58 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -46,155 +46,143 @@ jobs:
4646
working_directory: contracts
4747
command: |
4848
if [[ "${CIRCLE_NODE_INDEX}" == 0 ]]; then
49-
myth analyze --solv=0.5.15 ./oracle.sol --execution-timeout=900
49+
myth analyze --solv=0.5.15 ./oracle.sol --execution-timeout=800
5050
fi
5151
no_output_timeout: 20m
5252
- run:
5353
working_directory: contracts
5454
command: |
5555
if [[ "${CIRCLE_NODE_INDEX}" == 1 ]]; then
56-
myth analyze --solv=0.5.15 ./wallet.sol --execution-timeout=900
56+
myth analyze --solv=0.5.15 ./wallet.sol --execution-timeout=800
5757
fi
5858
no_output_timeout: 20m
5959
- run:
6060
working_directory: contracts
6161
command: |
6262
if [[ "${CIRCLE_NODE_INDEX}" == 2 ]]; then
63-
myth analyze --solv=0.5.15 ./holder.sol --execution-timeout=900
63+
myth analyze --solv=0.5.15 ./holder.sol --execution-timeout=800
6464
fi
6565
no_output_timeout: 20m
6666
- run:
6767
working_directory: contracts
6868
command: |
6969
if [[ "${CIRCLE_NODE_INDEX}" == 3 ]]; then
70-
myth analyze --solv=0.5.15 ./licence.sol --execution-timeout=900
70+
myth analyze --solv=0.5.15 ./licence.sol --execution-timeout=800
7171
fi
7272
no_output_timeout: 20m
7373
- run:
7474
working_directory: contracts
7575
command: |
7676
if [[ "${CIRCLE_NODE_INDEX}" == 4 ]]; then
77-
myth analyze --solv=0.5.15 ./tokenWhitelist.sol --execution-timeout=900
77+
myth analyze --solv=0.5.15 ./tokenWhitelist.sol --execution-timeout=800
7878
fi
7979
no_output_timeout: 20m
8080
- run:
8181
working_directory: contracts
8282
command: |
8383
if [[ "${CIRCLE_NODE_INDEX}" == 5 ]]; then
84-
myth analyze --solv=0.5.15 ./walletDeployer.sol --execution-timeout=900
84+
myth analyze --solv=0.5.15 ./walletDeployer.sol --execution-timeout=800
8585
fi
8686
no_output_timeout: 20m
8787

8888
slither:
8989
docker:
9090
- image: trailofbits/eth-security-toolbox:latest
9191
working_directory: /tmp/contracts
92+
parallelism: 6
9293
steps:
9394
- run: sudo -n apt-get update && sudo -n apt-get install -y openssh-client
9495
- checkout
95-
- run:
96-
command: solc-select 0.5.15
96+
- run: solc-select 0.5.15
9797
- run:
9898
working_directory: slither
9999
command: |
100-
slither ../contracts/wallet.sol ||
101-
echo "export FAILED=true" >> $BASH_ENV
100+
if [[ "${CIRCLE_NODE_INDEX}" == 0 ]]; then
101+
slither ../contracts/wallet.sol
102+
fi
102103
no_output_timeout: 5m
103104
- run:
104105
working_directory: slither
105106
command: |
106-
slither ../contracts/oracle.sol ||
107-
echo "export FAILED=true" >> $BASH_ENV
107+
if [[ "${CIRCLE_NODE_INDEX}" == 1 ]]; then
108+
slither ../contracts/oracle.sol
109+
fi
108110
no_output_timeout: 5m
109111
- run:
110112
working_directory: slither
111113
command: |
112-
slither ../contracts/licence.sol ||
113-
echo "export FAILED=true" >> $BASH_ENV
114+
if [[ "${CIRCLE_NODE_INDEX}" == 2 ]]; then
115+
slither ../contracts/licence.sol
116+
fi
114117
no_output_timeout: 5m
115118
- run:
116119
working_directory: slither
117120
command: |
118-
slither ../contracts/holder.sol ||
119-
echo "export FAILED=true" >> $BASH_ENV
121+
if [[ "${CIRCLE_NODE_INDEX}" == 3 ]]; then
122+
slither ../contracts/holder.sol
123+
fi
120124
no_output_timeout: 5m
121125
- run:
122126
working_directory: slither
123127
command: |
124-
slither ../contracts/tokenWhitelist.sol ||
125-
echo "export FAILED=true" >> $BASH_ENV
128+
if [[ "${CIRCLE_NODE_INDEX}" == 4 ]]; then
129+
slither ../contracts/tokenWhitelist.sol
130+
fi
126131
no_output_timeout: 5m
127132
- run:
128133
working_directory: slither
129134
command: |
130-
slither ../contracts/walletDeployer.sol ||
131-
echo "export FAILED=true" >> $BASH_ENV
135+
if [[ "${CIRCLE_NODE_INDEX}" == 5 ]]; then
136+
slither ../contracts/walletDeployer.sol
137+
fi
132138
no_output_timeout: 5m
133-
- run:
134-
command: test ! $FAILED
135139

136140
echidna:
137141
docker:
138142
- image: trailofbits/eth-security-toolbox:latest
139143
working_directory: /tmp/contracts
144+
parallelism: 6
140145
steps:
146+
- run: sudo -n apt-get update && sudo -n apt-get install -y openssh-client
141147
- checkout
142-
- run:
143-
command: solc-select 0.5.15
144-
- run:
145-
command: |
146-
slither-flat --convert-external contracts/wallet.sol &&
147-
echidna-test echidna/addressWhitelist.sol --config echidna/addressWhitelist.yaml TEST ||
148-
echo "export FAILED=true" >> $BASH_ENV
149-
no_output_timeout: 20m
150-
- run:
151-
command: |
152-
slither-flat --convert-external contracts/controller.sol &&
153-
echidna-test echidna/controller.sol --config echidna/controller.yaml TEST ||
154-
echo "export FAILED=true" >> $BASH_ENV
155-
no_output_timeout: 20m
156-
- run:
157-
command: |
158-
echidna-test echidna/date.sol --config echidna/date.yaml TEST ||
159-
echo "export FAILED=true" >> $BASH_ENV
160-
no_output_timeout: 20m
161-
- run:
162-
command: |
163-
echidna-test echidna/ecRecover.sol --config echidna/ecRecover.yaml TEST ||
164-
echo "export FAILED=true" >> $BASH_ENV
165-
no_output_timeout: 20m
148+
- run: solc-select 0.5.15
149+
- run: find contracts -maxdepth 1 -type f -name '*.sol' -exec slither-flat --convert-external {} \;
166150
- run:
167151
command: |
168-
echidna-test echidna/ecRecover.sol --config echidna/ecRecover.yaml TEST ||
169-
echo "export FAILED=true" >> $BASH_ENV
170-
no_output_timeout: 20m
152+
if [[ "${CIRCLE_NODE_INDEX}" == 0 ]]; then
153+
echidna-test echidna/addressWhitelist.sol --config=echidna/addressWhitelist.yaml --contract=TEST
154+
fi
155+
no_output_timeout: 15m
171156
- run:
172157
command: |
173-
echidna-test echidna/gasTopUpLimit.sol --config echidna/gasTopUpLimit.yaml TEST ||
174-
echo "export FAILED=true" >> $BASH_ENV
175-
no_output_timeout: 20m
158+
if [[ "${CIRCLE_NODE_INDEX}" == 1 ]]; then
159+
echidna-test echidna/controller.sol --config=echidna/controller.yaml --contract=TEST
160+
fi
161+
no_output_timeout: 15m
176162
- run:
177163
command: |
178-
echidna-test echidna/ownable.sol --config echidna/ownable.yaml TEST ||
179-
echo "export FAILED=true" >> $BASH_ENV
180-
no_output_timeout: 20m
164+
if [[ "${CIRCLE_NODE_INDEX}" == 2 ]]; then
165+
echidna-test echidna/date.sol --config=echidna/date.yaml --contract=TEST
166+
fi
167+
no_output_timeout: 15m
181168
- run:
182169
command: |
183-
echidna-test echidna/parseJson.sol --config echidna/parseJson.yaml TEST ||
184-
echo "export FAILED=true" >> $BASH_ENV
185-
no_output_timeout: 20m
170+
if [[ "${CIRCLE_NODE_INDEX}" == 3 ]]; then
171+
echidna-test echidna/gasTopUpLimit.sol --config=echidna/gasTopUpLimit.yaml --contract=TEST
172+
fi
173+
no_output_timeout: 15m
186174
- run:
187175
command: |
188-
echidna-test echidna/spendLimit.sol --config echidna/spendLimit.yaml TEST ||
189-
echo "export FAILED=true" >> $BASH_ENV
190-
no_output_timeout: 20m
176+
if [[ "${CIRCLE_NODE_INDEX}" == 4 ]]; then
177+
echidna-test echidna/ownable.sol --config=echidna/ownable.yaml --contract=TEST
178+
fi
179+
no_output_timeout: 15m
191180
- run:
192181
command: |
193-
echidna-test echidna/stringProps.sol --config echidna/stringProps.yaml TEST ||
194-
echo "export FAILED=true" >> $BASH_ENV
195-
no_output_timeout: 20m
196-
- run:
197-
command: test ! $FAILED
182+
if [[ "${CIRCLE_NODE_INDEX}" == 5 ]]; then
183+
echidna-test echidna/spendLimit.sol --config=echidna/spendLimit.yaml --contract=TEST
184+
fi
185+
no_output_timeout: 15m
198186

199187
workflows:
200188
version: 2
@@ -218,7 +206,7 @@ workflows:
218206
filters:
219207
tags:
220208
ignore: ""
221-
# - echidna:
222-
# filters:
223-
# tags:
224-
# ignore: ""
209+
- echidna:
210+
filters:
211+
tags:
212+
ignore: ""

echidna/README.md

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,48 @@
1-
# Echidna tests for TokenCard contracts
1+
# Properties
22

3-
This directory contains some properties for testing TokenCard contracts where three users are defined:
3+
This directory contains some properties for testing Solidity contracts where multiple users are defined:
44

5-
* `echidna_owner`: the owner of the contract only used to execute the contract constructor
6-
* `echidna_attack`: an unprivileged user, used to execute the randomly generated transactions
7-
* `echidna_user`: another unprivileged user, also used to execute randomly generated transactions in cases where multiple users are necessary
5+
- `echidna_deployer`: Deployer address used to execute the contract constructor.
86

9-
We test a variety of properties, such as:
10-
* Whitelist addition and removal operations properly modify the whitelist
11-
* The owner of a contract cannot be changed.
12-
* Spending limits are properly bounded by the spend limit values
13-
* Spending limits do in fact reset daily
14-
* Differential testing of the different interger parsing functions produce identical results
7+
- `echidna_owner`: Address of the user that owns an ownable contract.
8+
9+
- `echidna_controller`: Controller address assigned to a controllable contract.
10+
11+
- `echidna_attacker`: An unprivileged user, used to execute the randomly generated transactions.
12+
13+
# Configuration
14+
15+
Individual tests can be configured using yaml configuration files.
16+
17+
A full list of test configuration options can be found here: [default.yaml](https://github.com/crytic/echidna/blob/master/examples/solidity/basic/default.yaml)
1518

1619
# Instructions
1720

18-
1. Uncompress this file in the root of [TokenCard's contract repository](https://github.com/tokencard/contracts). We tested this example with version [2.0.0](https://github.com/tokencard/contracts/commit/b99b7d1670f9ad7b90335e8391fe63fd7e20de9b).
19-
2. Install the latest revision of [Echidna](https://github.com/crytic/echidna/#installation). Note that `ecRecover.sol` requires the `dev-hevm-0.29` branch of Echidna to run.
20-
3. Execute `echidna-test` with one of the `*.sol` files and its corresponding `*.yaml` config file. For example, an invocation with `spendLimit.sol` would look like:
21+
Normally the echidna tests run in CircleCI but they can also be invoked locally for development purposes.
22+
23+
Run trail of bits security toolbox and mount the contracts directory, you need to make sure that the path is an absolute path:
24+
25+
docker run -v $GOPATH/src/github.com/tokencard/contracts:/contracts -it trailofbits/eth-security-toolbox:latest
26+
27+
Run `echidna-test` command on each test contract:
28+
29+
echidna-test echidna/spendLimit.sol --config=echidna/spendLimit.yaml --contract=TEST
30+
31+
Analyzing contract: spendLimit.sol:TEST
32+
echidna_fixed_spendLimitValue: passed!
33+
echidna_bounded_spendLimitAvailable: passed!
34+
echidna_fixed_owner: passed!
35+
echidna_daily_spendLimitAvailable: passed!
36+
37+
Unique instructions: 900
38+
Unique codehashes: 1
39+
40+
# Tools
41+
42+
Sometimes it's necessary to convert external functions in a contract to public functions so that they can be called inside the derived TEST contract.
2143

22-
```
23-
$ echidna-test spendLimit.sol --config spendLimit.yaml TEST
24-
...
44+
For this it's advisable to use the `slither-flat` command like so:
2545

26-
Analyzing contract: spendLimit.sol:TEST
27-
echidna_fixed_spendLimitValue: passed! 🎉
28-
echidna_bounded_spendLimitAvailable: passed! 🎉
29-
echidna_fixed_owner: passed! 🎉
30-
echidna_daily_spendLimitAvailable: passed! 🎉
46+
slither-flat --convert-external contracts/wallet.sol
3147

32-
Unique instructions: 900
33-
Unique codehashes: 1
34-
```
48+
This will create a new flattened contract at `critic-export/flattening/Wallet.sol` which can then be imported in the test file as `import "crytic-export/flattening/Wallet.sol";`.

0 commit comments

Comments
 (0)