1
+ name : Foundry
2
+
3
+ on :
4
+ workflow_dispatch :
5
+ push :
6
+ branches :
7
+ - master
8
+ - mainnet
9
+ - testnet-goerli
10
+ - dev
11
+ pull_request :
12
+
13
+ env :
14
+ FOUNDRY_PROFILE : ci
15
+ RPC_MAINNET : ${{ secrets.RPC_MAINNET }}
16
+ RPC_HOLESKY : ${{ secrets.RPC_HOLESKY }}
17
+ CHAIN_ID : ${{ secrets.CHAIN_ID }}
18
+
19
+ jobs :
20
+ # -----------------------------------------------------------------------
21
+ # Forge Test
22
+ # -----------------------------------------------------------------------
23
+
24
+ test :
25
+ name : Test
26
+ runs-on : ubuntu-latest
27
+ strategy :
28
+ fail-fast : true
29
+ steps :
30
+ # Check out repository with all submodules for complete codebase access.
31
+ - uses : actions/checkout@v4
32
+ with :
33
+ submodules : recursive
34
+
35
+ # Install the Foundry toolchain.
36
+ - name : " Install Foundry"
37
+ uses : foundry-rs/foundry-toolchain@v1
38
+ with :
39
+ version : stable
40
+
41
+ # Run Forge's formatting checker to ensure consistent code style.
42
+ - name : " Forge Fmt"
43
+ run : |
44
+ forge fmt --check
45
+ id : fmt
46
+
47
+ # Install Bun package manager for JavaScript dependencies (faster than npm).
48
+ - name : " Install Bun"
49
+ uses : " oven-sh/setup-bun@v1"
50
+
51
+ # Install NPM packages.
52
+ - name : " Install NPM Packages"
53
+ run : bun install
54
+
55
+ # Run Solhint linter to check for Solidity code quality issues.
56
+ - name : " Solhint"
57
+ run : bun run hint
58
+
59
+ # Build the project and display contract sizes.
60
+ - name : " Forge Build"
61
+ run : |
62
+ forge --version
63
+ forge build --sizes
64
+ id : build
65
+
66
+ # Run local tests (unit and integration).
67
+ - name : " Forge Test (Local)"
68
+ run : forge test -vvv
69
+
70
+ # Run integration tests using a mainnet fork.
71
+ - name : " Forge Test Integration (Fork)"
72
+ run : FOUNDRY_PROFILE=forktest forge test --match-contract Integration -vvv
73
+
74
+ # -----------------------------------------------------------------------
75
+ # Forge Test (Intense)
76
+ # -----------------------------------------------------------------------
77
+
78
+ continuous-fuzzing :
79
+ name : Test (Intense)
80
+ runs-on : ubuntu-latest
81
+ strategy :
82
+ fail-fast : true
83
+ steps :
84
+ # Check out repository with all submodules for complete codebase access.
85
+ - uses : actions/checkout@v4
86
+ with :
87
+ submodules : recursive
88
+
89
+ # Install the Foundry toolchain.
90
+ - name : " Install Foundry"
91
+ uses : foundry-rs/foundry-toolchain@v1
92
+ with :
93
+ version : stable
94
+
95
+ # Build the project and display contract sizes.
96
+ - name : " Forge Build"
97
+ run : |
98
+ forge --version
99
+ forge build --sizes
100
+ id : build
101
+
102
+ # Run Forge Test (Intense)
103
+ - name : Forge Test (Intense)
104
+ run : |
105
+ echo -e "\033[1;33mWarning: This workflow may take several hours to complete.\033[0m"
106
+ echo -e "\033[1;33mThis intense fuzzing workflow is optional but helps catch edge cases through extended testing.\033[0m"
107
+ FOUNDRY_PROFILE=intense forge test -vvv
108
+
109
+ # -----------------------------------------------------------------------
110
+ # Forge Coverage
111
+ # -----------------------------------------------------------------------
112
+
113
+ run-coverage :
114
+ name : Coverage
115
+ runs-on : ubuntu-latest
116
+ # Only run coverage checks on dev, testnet-holesky, and mainnet branches, or PRs targeting these branches
117
+ if : |
118
+ github.ref == 'refs/heads/dev' ||
119
+ github.ref == 'refs/heads/testnet-holesky' ||
120
+ github.ref == 'refs/heads/mainnet' ||
121
+ github.base_ref == 'dev' ||
122
+ github.base_ref == 'testnet-holesky' ||
123
+ github.base_ref == 'mainnet'
124
+ strategy :
125
+ fail-fast : true
126
+ steps :
127
+ # Check out repository with all submodules for complete codebase access.
128
+ - uses : actions/checkout@v4
129
+ with :
130
+ submodules : recursive
131
+
132
+ # Install the Foundry toolchain.
133
+ - name : " Install Foundry"
134
+ uses : foundry-rs/foundry-toolchain@v1
135
+ with :
136
+ version : stable
137
+
138
+ # Install LCOV for coverage report generation.
139
+ - name : Install LCOV
140
+ run : |
141
+ sudo apt-get install lcov
142
+ id : lcov
143
+
144
+ # Build the project and display contract sizes.
145
+ - name : " Forge Build"
146
+ run : |
147
+ forge --version
148
+ forge build --sizes
149
+ id : build
150
+
151
+ # Run Forge coverage with LCOV report format, excluding test and script files
152
+ - name : Forge Coverage
153
+ run : |
154
+ FOUNDRY_DENY_WARNINGS=false FOUNDRY_PROFILE=ci forge coverage --report lcov --report summary --no-match-coverage "script|test"
155
+ genhtml -q -o report ./lcov.info
156
+
157
+ # Upload coverage report as artifact before potential failure
158
+ - name : Upload Coverage Report
159
+ uses : actions/upload-artifact@v4
160
+ with :
161
+ name : code-coverage-report
162
+ path : report/*
163
+
164
+ # Check coverage threshold after uploading report
165
+ - name : Check Coverage Threshold
166
+ run : |
167
+ LINES_PCT=$(lcov --summary lcov.info | grep "lines" | cut -d ':' -f 2 | cut -d '%' -f 1 | tr -d '[:space:]')
168
+ FUNCTIONS_PCT=$(lcov --summary lcov.info | grep "functions" | cut -d ':' -f 2 | cut -d '%' -f 1 | tr -d '[:space:]')
169
+ FAILED=0
170
+
171
+ if (( $(echo "$LINES_PCT < 90" | bc -l) )); then
172
+ echo -e "\033[1;31mβ Lines coverage ($LINES_PCT%) is below minimum threshold of 90%\033[0m"
173
+ FAILED=1
174
+ else
175
+ echo -e "\033[1;32mβ
Lines coverage ($LINES_PCT%) meets minimum threshold of 90%\033[0m"
176
+ fi
177
+
178
+ if (( $(echo "$FUNCTIONS_PCT < 90" | bc -l) )); then
179
+ echo -e "\033[1;31mβ Functions coverage ($FUNCTIONS_PCT%) is below minimum threshold of 90%\033[0m"
180
+ FAILED=1
181
+ else
182
+ echo -e "\033[1;32mβ
Functions coverage ($FUNCTIONS_PCT%) meets minimum threshold of 90%\033[0m"
183
+ fi
184
+
185
+ if [ $FAILED -eq 1 ]; then
186
+ exit 1
187
+ fi
188
+
189
+ # -----------------------------------------------------------------------
190
+ # Forge Size Diff
191
+ # -----------------------------------------------------------------------
192
+
193
+ compare-contract-sizes :
194
+ name : Size Diff
195
+ runs-on : ubuntu-latest
196
+ steps :
197
+ # Check out repository with all submodules for complete codebase access.
198
+ - uses : actions/checkout@v4
199
+ with :
200
+ submodules : recursive
201
+
202
+ # Install the Foundry toolchain.
203
+ - name : " Install Foundry"
204
+ uses : foundry-rs/foundry-toolchain@v1
205
+ with :
206
+ version : stable
207
+
208
+ - name : Build contracts on PR branch
209
+ run : |
210
+ forge build --json --sizes | jq '.' > pr_sizes.json
211
+
212
+ - name : Checkout target branch
213
+ run : |
214
+ git fetch origin ${{ github.base_ref }}
215
+ git checkout ${{ github.base_ref }}
216
+
217
+ - name : Build contracts on target branch
218
+ run : |
219
+ forge build --json --sizes | jq '.' > target_sizes.json
220
+
221
+ - name : Compare contract sizes using Bash
222
+ run : |
223
+ # Extract contract names
224
+ contracts=$(jq -r 'keys[]' pr_sizes.json)
225
+
226
+ # Track if there are any differences
227
+ has_differences=0
228
+
229
+ echo -e "\nπ \033[1;34mContract Size Comparison Report\033[0m π\n"
230
+
231
+ # Iterate through contracts and compare sizes
232
+ for contract in $contracts; do
233
+ pr_runtime=$(jq -r --arg contract "$contract" '.[$contract].runtime_size // 0' pr_sizes.json)
234
+ pr_init=$(jq -r --arg contract "$contract" '.[$contract].init_size // 0' pr_sizes.json)
235
+
236
+ target_runtime=$(jq -r --arg contract "$contract" '.[$contract].runtime_size // 0' target_sizes.json)
237
+ target_init=$(jq -r --arg contract "$contract" '.[$contract].init_size // 0' target_sizes.json)
238
+
239
+ runtime_diff=$((pr_runtime - target_runtime))
240
+ init_diff=$((pr_init - target_init))
241
+
242
+ if [ "$runtime_diff" -ne 0 ] || [ "$init_diff" -ne 0 ]; then
243
+ echo -e "\033[1;36mπ $contract:\033[0m"
244
+ if [ "$runtime_diff" -ne 0 ]; then
245
+ if [ "$runtime_diff" -gt 0 ]; then
246
+ echo -e " Runtime: \033[1;31m+$runtime_diff bytes\033[0m π"
247
+ else
248
+ echo -e " Runtime: \033[1;32m$runtime_diff bytes\033[0m π"
249
+ fi
250
+ fi
251
+ if [ "$init_diff" -ne 0 ]; then
252
+ if [ "$init_diff" -gt 0 ]; then
253
+ echo -e " Init: \033[1;31m+$init_diff bytes\033[0m π"
254
+ else
255
+ echo -e " Init: \033[1;32m$init_diff bytes\033[0m π"
256
+ fi
257
+ fi
258
+ has_differences=1
259
+ fi
260
+ done
261
+
262
+ if [ "$has_differences" -eq 0 ]; then
263
+ echo -e "\033[1;32mβ¨ No contract size changes detected β¨\033[0m"
264
+ fi
0 commit comments