Skip to content

Commit ebf7e29

Browse files
authored
Merge pull request #712 from OpenZeppelin/foundry
✨ Port all contracts to Foundry
2 parents c8860dc + 3432dca commit ebf7e29

File tree

492 files changed

+9969
-11644
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

492 files changed

+9969
-11644
lines changed

.github/workflows/test.yml

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
11
name: Test
2-
32
on:
43
push:
54
branches: [master]
65
pull_request: {}
76

87
jobs:
9-
test:
8+
tests:
9+
name: Foundry tests
1010
runs-on: ubuntu-latest
11+
defaults:
12+
run:
13+
working-directory: ./contracts
14+
1115
steps:
12-
- uses: actions/checkout@v3
13-
- uses: actions/setup-node@v3
14-
with:
15-
node-version: 16.x
16-
- run: yarn
17-
- run: yarn test:contracts
16+
- uses: actions/checkout@v3
17+
with:
18+
submodules: true
19+
20+
- name: Install Foundry
21+
uses: foundry-rs/foundry-toolchain@v1
22+
with:
23+
version: nightly
24+
25+
- name: Install dependencies
26+
run: forge install
27+
28+
- name: Check contract sizes
29+
run: forge build --sizes --skip test
30+
id: build
31+
32+
- name: Run tests
33+
run: forge test -v
34+
id: test

.gitignore

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@ node_modules/
55
client/.env
66
contracts/.env
77

8-
# Contracts
9-
contracts/build/
10-
contracts/cache/
11-
contracts/node_modules/
12-
contracts/.openzeppelin/
13-
148
# Client
159
client/build/
1610
client/node_modules/
1711
client/src/gamedata/deploy.local.json
1812
.env
13+
14+
# Local Netlify folder
15+
.netlify

.gitmodules

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[submodule "contracts/lib/forge-std"]
2+
path = contracts/lib/forge-std
3+
url = https://github.com/foundry-rs/forge-std
4+
[submodule "contracts/lib/openzeppelin-contracts-06"]
5+
path = contracts/lib/openzeppelin-contracts-06
6+
url = https://github.com/openzeppelin/openzeppelin-contracts
7+
[submodule "contracts/lib/openzeppelin-contracts-08"]
8+
path = contracts/lib/openzeppelin-contracts-08
9+
url = https://github.com/openzeppelin/openzeppelin-contracts
10+
[submodule "contracts/lib/openzeppelin-contracts-upgradeable"]
11+
path = contracts/lib/openzeppelin-contracts-upgradeable
12+
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## March 2024
2+
- Updated all contracts (challenges, tests, etc.) to use Foundry instead of Hardhat
3+
14
## August 2021
25
- Filter out repeated log messages for mined transactions
36
- Increased Sidebar width

CONTRIBUTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ If you would like to contribute in another way, please reach out to us via email
4444

4545
*A level is composed of the following elements:*
4646

47-
- A `<Level>Factory.sol` contract, where `<Level>` is replaced by the name of the level, that needs to extend [`Level.sol`](./contracts/contracts/levels/base/Level.sol). This factory contract will be deployed only once and registered on Ethernaut.sol by Ethernaut's owner. Players never interact with the factory directly. The factory is in charge of creating level instances for players to use (1 instance per player) and to check these instances to verify if the player has passed the level. Factories should not have state that can be changed by the player.
47+
- A `<Level>Factory.sol` contract, where `<Level>` is replaced by the name of the level, that needs to extend [`Level.sol`](./contracts/src/levels/base/Level.sol). This factory contract will be deployed only once and registered on Ethernaut.sol by Ethernaut's owner. Players never interact with the factory directly. The factory is in charge of creating level instances for players to use (1 instance per player) and to check these instances to verify if the player has passed the level. Factories should not have state that can be changed by the player.
4848
- A `level instance` contract named `<Level>.sol`, where `<Level>` is replaced by the name of the level, that is emitted by the factory for each player that requests it. Instances need to be completely decouppled from Ethernaut's architecture. Factories will emit them and verify them. That is, level instances don't know anything about their factories or Ethernaut. An instance's state can be completely demolished by players and even destroyed since they are not really part of the architecture, just a challenge for a player to use at will.
4949
- A `description file` in [the descriptions directory](./client/src/gamedata/en/descriptions/levels) that the UI presents to the player and describes the level's objectives with some narrative and tips.
5050
- A `description completion file` also located in [the descriptions directory](./client/src/gamedata/en/descriptions/levels) that the UI presents to the player when the level is passed, further information about the player, historical insights, further explanations or just a congrats message.
@@ -60,8 +60,8 @@ Let's suppose that we are creating the level "King" (which is already created an
6060
2. Use the other levels as a basis, eg. duplicate DummyFactory.sol and Dummy.sol.
6161
3. Rename and modify the contracts to KingFactory.sol and King.sol respectively.
6262
4. Implement the desired instance and factory logic in solidity. See current levels and notes to understand how the game mechanics work.
63-
5. Add the test file `contracts/test/levels/King.test.js`. Use other tests files as reference to see how tests might work.
64-
6. Run `yarn test:contracts` and once all tests pass, register the level in [gamedata.json](client/src/gamedata/gamedata.json).
63+
5. Add the test file `contracts/test/levels/King.t.sol`. Use other tests files as reference to see how tests might work.
64+
6. Run `forge test` and once all tests pass, register the level in [gamedata.json](client/src/gamedata/gamedata.json).
6565
7. The level should now show up in the ui. To start the UI, set the [ACTIVE_NETWORK](client/src/constants.js) to `NETWORKS.LOCAL` and run `yarn start`.
6666
8. Add a description markdown file, in this case client/src/gamedata/levels/king.md (make sure gamedata.json points to it). This content will now be displayed in the ui for the level.
6767
9. Add a completed description markdown file, in this case client/src/gamedata/levels/king_complete.md (make sure gamedata.json points to it). The level will display this as additional info once the level is solved, usually to include historical information related to the level.

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
"private": true,
66
"dependencies": {
77
"@sentry/react": "^7.0.0",
8+
"@sentry/tracing": "^7.108.0",
89
"@truffle/contract": "^4.3.15",
910
"alchemy-sdk": "^2.2.3",
1011
"axios": "^1.2.4",
1112
"bad-words": "^3.0.4",
1213
"bootstrap": "^5.0.0",
13-
"contracts": "0.1.0",
1414
"cross-env": "7.0.3",
1515
"devtools-detect": "^4.0.0",
1616
"dotenv": "^16.0.3",

client/public/contracts

Lines changed: 0 additions & 1 deletion
This file was deleted.

client/scripts/deploy_contracts.mjs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import * as ethutil from "../src/utils/ethutil.js";
77
import * as constants from "../src/constants.js";
88
import HDWalletProvider from "@truffle/hdwallet-provider";
99
import * as gamedata from "../src/gamedata/gamedata.json" assert { type: "json" };
10-
import * as EthernautABI from "contracts/build/contracts/Ethernaut.sol/Ethernaut.json" assert { type: "json" };
11-
import * as ProxyAdminABI from "contracts/build/contracts/proxy/ProxyAdmin.sol/ProxyAdmin.json" assert { type: "json" };
12-
import * as ImplementationABI from "contracts/build/contracts/metrics/Statistics.sol/Statistics.json" assert { type: "json" };
13-
import * as ProxyStatsABI from "contracts/build/contracts/proxy/ProxyStats.sol/ProxyStats.json" assert { type: "json" };
10+
import * as EthernautABI from "../src/contracts/out/Ethernaut.sol/Ethernaut.json" assert { type: "json" };
11+
import * as ProxyAdminABI from "../src/contracts/out/ProxyAdmin.sol/ProxyAdmin.json" assert { type: "json" };
12+
import * as ImplementationABI from "../src/contracts/out/Statistics.sol/Statistics.json" assert { type: "json" };
13+
import * as ProxyStatsABI from "../src/contracts/out/ProxyStats.sol/ProxyStats.json" assert { type: "json" };
1414

1515
let web3;
1616
let ethernaut;
@@ -127,7 +127,7 @@ async function deployContracts(deployData) {
127127
// Deploy contract
128128
const LevelABI = JSON.parse(
129129
fs.readFileSync(
130-
`contracts/build/contracts/levels/${
130+
`contracts/out/${
131131
level.levelContract
132132
}/${withoutExtension(level.levelContract)}.json`,
133133
"utf-8"

client/scripts/supersede_level.mjs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import HDWalletProvider from "@truffle/hdwallet-provider";
55
import Web3 from "web3";
66
import * as ethutil from "../src/utils/ethutil.js";
77
import * as constants from "../src/constants.js";
8-
import * as EthernautABI from "contracts/build/contracts/Ethernaut.sol/Ethernaut.json" assert { type: "json" };
9-
import * as ProxyStatsABI from "contracts/build/contracts/proxy/ProxyStats.sol/ProxyStats.json" assert { type: "json" };
10-
import * as ProxyAdminABI from "contracts/build/contracts/proxy/ProxyAdmin.sol/ProxyAdmin.json" assert { type: "json" };
11-
import * as ImplementationABI from "contracts/build/contracts/metrics/Statistics.sol/Statistics.json" assert { type: "json" };
12-
import * as SupersederImplementationABI from "contracts/build/contracts/metrics/StatisticsLevelSuperseder.sol/StatisticsLevelSuperseder.json" assert { type: "json" };
8+
import * as EthernautABI from "../src/contracts/out/Ethernaut.sol/Ethernaut.json" assert { type: "json" };
9+
import * as ProxyStatsABI from "../src/contracts/out/ProxyStats.sol/ProxyStats.json" assert { type: "json" };
10+
import * as ProxyAdminABI from "../src/contracts/out/ProxyAdmin.sol/ProxyAdmin.json" assert { type: "json" };
11+
import * as ImplementationABI from "../src/contracts/out/Statistics.sol/Statistics.json" assert { type: "json" };
12+
import * as SupersederImplementationABI from "../src/contracts/out/StatisticsLevelSuperseder.sol/StatisticsLevelSuperseder.json" assert { type: "json" };
1313

1414
import gamedata from "../src/gamedata/gamedata.json" assert { type: "json" };
1515
const levels = gamedata.levels;
@@ -201,7 +201,7 @@ async function deployAndUpgradeStatisticsToStatisticsSuperseder() {
201201

202202
const props = {
203203
gasPrice: parseInt(await web3.eth.getGasPrice() * 1.10),
204-
gas: 45000000,
204+
gas: 30000000,
205205
};
206206
let from = constants.ADDRESSES[constants.ACTIVE_NETWORK.name];
207207
if (!from) from = (await web3.eth.getAccounts())[0];
@@ -258,7 +258,7 @@ async function deployLevel(level) {
258258

259259
const LevelABI = JSON.parse(
260260
fs.readFileSync(
261-
`contracts/build/contracts/levels/${level.levelContract}/${
261+
`contracts/out/${level.levelContract}/${
262262
level.levelContract.split(".")[0]
263263
}.json`,
264264
"utf-8"

client/scripts/upgrade_proxy.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import fs from 'fs';
44
import * as ethutil from '../src/utils/ethutil.js';
55
import * as constants from '../src/constants.js';
66
import HDWalletProvider from '@truffle/hdwallet-provider';
7-
import * as ProxyAdminABI from 'contracts/build/contracts/proxy/ProxyAdmin.sol/ProxyAdmin.json' assert { type: 'json' };
8-
import * as ImplementationABI from 'contracts/build/contracts/metrics/Statistics.sol/Statistics.json' assert { type: 'json' };
7+
import * as ProxyAdminABI from '../src/contracts/out/ProxyAdmin.sol/ProxyAdmin.json' assert { type: 'json' };
8+
import * as ImplementationABI from '../src/contracts/out/Statistics.sol/Statistics.json' assert { type: 'json' };
99

1010
let web3;
1111

0 commit comments

Comments
 (0)