Skip to content

Commit e1b39d0

Browse files
technophile-04carletexPabl0cks
authored
Migrate to foundry (#867)
Co-authored-by: Carlos Sánchez <[email protected]> Co-authored-by: Pablo Alayeto <[email protected]>
1 parent 35b4c67 commit e1b39d0

39 files changed

+947
-4940
lines changed

.github/workflows/lint.yaml

+8-4
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,18 @@ jobs:
3030
- name: Install dependencies
3131
run: yarn install --immutable
3232

33-
- name: Run hardhat node, deploy contracts (& generate contracts typescript output)
33+
- name: Install foundry-toolchain
34+
uses: foundry-rs/foundry-toolchain@v1
35+
with:
36+
version: nightly
37+
38+
- name: Run foundry node, deploy contracts (& generate contracts typescript output)
39+
env:
40+
ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }}
3441
run: yarn chain & yarn deploy
3542

3643
- name: Run nextjs lint
3744
run: yarn next:lint --max-warnings=0
3845

3946
- name: Check typings on nextjs
4047
run: yarn next:check-types
41-
42-
- name: Run hardhat lint
43-
run: yarn hardhat:lint --max-warnings=0

.gitmodules

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[submodule "packages/foundry/lib/forge-std"]
2+
path = packages/foundry/lib/forge-std
3+
url = https://github.com/foundry-rs/forge-std
4+
[submodule "packages/foundry/lib/openzeppelin-contracts"]
5+
path = packages/foundry/lib/openzeppelin-contracts
6+
url = https://github.com/OpenZeppelin/openzeppelin-contracts
7+
[submodule "packages/foundry/lib/solidity-bytes-utils"]
8+
path = packages/foundry/lib/solidity-bytes-utils
9+
url = https://github.com/gnsps/solidity-bytes-utils

.lintstagedrc.js

+2-6
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@ const buildNextEslintCommand = (filenames) =>
77

88
const checkTypesNextCommand = () => "yarn next:check-types";
99

10-
const buildHardhatEslintCommand = (filenames) =>
11-
`yarn hardhat:lint-staged --fix ${filenames
12-
.map((f) => path.relative(path.join("packages", "hardhat"), f))
13-
.join(" ")}`;
14-
1510
module.exports = {
1611
"packages/nextjs/**/*.{ts,tsx}": [
1712
buildNextEslintCommand,
1813
checkTypesNextCommand,
1914
],
20-
"packages/hardhat/**/*.{ts,tsx}": [buildHardhatEslintCommand],
15+
"packages/foundry/**/*.sol": ["forge fmt --root packages/foundry"],
16+
"packages/foundry/**/*.js": ["yarn workspace @se-2/foundry prettier --write"],
2117
};

README.md

+10-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
🧪 An open-source, up-to-date toolkit for building decentralized applications (dapps) on the Ethereum blockchain. It's designed to make it easier for developers to create and deploy smart contracts and build user interfaces that interact with those contracts.
99

10-
⚙️ Built using NextJS, RainbowKit, Hardhat, Wagmi, Viem, and Typescript.
10+
⚙️ Built using NextJS, RainbowKit, Foundry, Wagmi, Viem, and Typescript.
1111

1212
-**Contract Hot Reload**: Your frontend auto-adapts to your smart contract as you edit it.
1313
- 🪝 **[Custom hooks](https://docs.scaffoldeth.io/hooks/)**: Collection of React hooks wrapper around [wagmi](https://wagmi.sh/) to simplify interactions with smart contracts with typescript autocompletion.
@@ -24,6 +24,9 @@ Before you begin, you need to install the following tools:
2424
- [Node (>= v18.17)](https://nodejs.org/en/download/)
2525
- Yarn ([v1](https://classic.yarnpkg.com/en/docs/install/) or [v2+](https://yarnpkg.com/getting-started/install))
2626
- [Git](https://git-scm.com/downloads)
27+
- [Foundryup](https://book.getfoundry.sh/getting-started/installation)
28+
29+
> **Note for Windows users**. Foundryup is not currently supported by Powershell or Cmd. You will need to use [Git BASH](https://gitforwindows.org/) or [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) as your terminal.
2730
2831
## Quickstart
2932

@@ -34,7 +37,7 @@ To get started with Scaffold-ETH 2, follow the steps below:
3437
```
3538
git clone https://github.com/scaffold-eth/scaffold-eth-2.git
3639
cd scaffold-eth-2
37-
yarn install
40+
yarn install && forge install --root packages/foundry
3841
```
3942

4043
2. Run a local network in the first terminal:
@@ -43,15 +46,15 @@ yarn install
4346
yarn chain
4447
```
4548

46-
This command starts a local Ethereum network using Hardhat. The network runs on your local machine and can be used for testing and development. You can customize the network configuration in `hardhat.config.ts`.
49+
This command starts a local Ethereum network using anvil. The network runs on your local machine and can be used for testing and development. You can customize the network configuration in `packages/foundry/foundry.toml`.
4750

4851
3. On a second terminal, deploy the test contract:
4952

5053
```
5154
yarn deploy
5255
```
5356

54-
This command deploys a test smart contract to the local network. The contract is located in `packages/hardhat/contracts` and can be modified to suit your needs. The `yarn deploy` command uses the deploy script located in `packages/hardhat/deploy` to deploy the contract to the network. You can also customize the deploy script.
57+
This command deploys a test smart contract to the local network. The contract is located in `packages/foundry/contracts` and can be modified to suit your needs. The `yarn deploy` command uses the deploy script located in `packages/foundry/script/Deploy.s.sol` to deploy the contract to the network. You can also customize the deploy script.
5558

5659
4. On a third terminal, start your NextJS app:
5760

@@ -63,10 +66,10 @@ Visit your app on: `http://localhost:3000`. You can interact with your smart con
6366

6467
**What's next**:
6568

66-
- Edit your smart contract `YourContract.sol` in `packages/hardhat/contracts`
69+
- Edit your smart contract `YourContract.sol` in `packages/foundry/contracts`
6770
- Edit your frontend homepage at `packages/nextjs/app/page.tsx`. For guidance on [routing](https://nextjs.org/docs/app/building-your-application/routing/defining-routes) and configuring [pages/layouts](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts) checkout the Next.js documentation.
68-
- Edit your deployment scripts in `packages/hardhat/deploy`
69-
- Edit your smart contract test in: `packages/hardhat/test`. To run test use `yarn hardhat:test`
71+
- Edit your deployment scripts in `packages/script/deploy/Deploy.s.sol`
72+
- Edit your smart contract test in: `packages/foundry/test`. To run test use `yarn foundry:test`
7073

7174
## Documentation
7275

package.json

+15-16
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,25 @@
44
"private": true,
55
"workspaces": {
66
"packages": [
7-
"packages/hardhat",
7+
"packages/foundry",
88
"packages/nextjs"
99
]
1010
},
1111
"scripts": {
12-
"account": "yarn workspace @se-2/hardhat account",
13-
"chain": "yarn workspace @se-2/hardhat chain",
14-
"fork": "yarn workspace @se-2/hardhat fork",
15-
"deploy": "yarn workspace @se-2/hardhat deploy",
16-
"verify": "yarn workspace @se-2/hardhat verify",
17-
"hardhat-verify": "yarn workspace @se-2/hardhat hardhat-verify",
18-
"compile": "yarn workspace @se-2/hardhat compile",
19-
"generate": "yarn workspace @se-2/hardhat generate",
20-
"flatten": "yarn workspace @se-2/hardhat flatten",
21-
"hardhat:lint": "yarn workspace @se-2/hardhat lint",
22-
"hardhat:lint-staged": "yarn workspace @se-2/hardhat lint-staged",
23-
"hardhat:format": "yarn workspace @se-2/hardhat format",
24-
"hardhat:test": "yarn workspace @se-2/hardhat test",
25-
"test": "yarn hardhat:test",
26-
"format": "yarn next:format && yarn hardhat:format",
12+
"account": "yarn workspace @se-2/foundry account",
13+
"chain": "yarn workspace @se-2/foundry chain",
14+
"fork": "yarn workspace @se-2/foundry fork",
15+
"deploy": "yarn workspace @se-2/foundry deploy",
16+
"verify": "yarn workspace @se-2/foundry verify",
17+
"deploy:verify": "yarn workspace @se-2/foundry deploy:verify",
18+
"compile": "yarn workspace @se-2/foundry compile",
19+
"generate": "yarn workspace @se-2/foundry generate",
20+
"flatten": "yarn workspace @se-2/foundry flatten",
21+
"foundry:format": "yarn workspace @se-2/foundry format",
22+
"foundry:lint": "yarn workspace @se-2/foundry lint",
23+
"foundry:test": "yarn workspace @se-2/foundry test",
24+
"test": "yarn foundry:test",
25+
"format": "yarn next:format && yarn foundry:format",
2726
"start": "yarn workspace @se-2/nextjs dev",
2827
"next:lint": "yarn workspace @se-2/nextjs lint",
2928
"next:format": "yarn workspace @se-2/nextjs format",

packages/foundry/.env.example

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Template for foundry environment variables.
2+
3+
# For local development, copy this file, rename it to .env, and fill in the values.
4+
5+
# We provide default values so developers can start prototyping out of the box,
6+
# but we recommend getting your own API Keys for Production Apps.
7+
8+
# DEPLOYER_PRIVATE_KEY is used while deploying contract.
9+
# On anvil chain the value of it can be empty since we use the prefunded account
10+
# which comes with anvil chain to deploy contract.
11+
# NOTE: You don't need to manually change the value of DEPLOYER_PRIVATE_KEY, it should
12+
# be auto filled when run `yarn generate`.
13+
# Although `.env` is ignored by git, it's still important that you don't paste your
14+
# actual account private key and use the generated one.
15+
DEPLOYER_PRIVATE_KEY=
16+
17+
# Alchemy rpc URL is used while deploying the contracts to some testnets/mainnets, checkout `foundry.toml` for it's use.
18+
ALCHEMY_API_KEY=oKxs-03sij-U_N0iOlrSsZFr29-IqbuF
19+
20+
# Etherscan API key is used to verify the contract on etherscan.
21+
ETHERSCAN_API_KEY=DNXJA8RX2Q3VZ4URQIWP7Z68CJXQZSC6AW

packages/foundry/.gitignore

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Compiler files
2+
cache/
3+
out/
4+
5+
# Ignores development broadcast logs
6+
/broadcast/*/31337/
7+
/broadcast/**/dry-run/
8+
9+
# Docs
10+
docs/
11+
12+
# Dotenv file
13+
.env
14+
localhost.json

packages/foundry/.prettier.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"arrowParens": "avoid",
3+
"printWidth": 120,
4+
"tabWidth": 2,
5+
"trailingComma": "all"
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//SPDX-License-Identifier: MIT
2+
pragma solidity >=0.8.0 <0.9.0;
3+
4+
// Useful for debugging. Remove when deploying to a live network.
5+
import "forge-std/console.sol";
6+
7+
// Use openzeppelin to inherit battle-tested implementations (ERC20, ERC721, etc)
8+
// import "@openzeppelin/contracts/access/Ownable.sol";
9+
10+
/**
11+
* A smart contract that allows changing a state variable of the contract and tracking the changes
12+
* It also allows the owner to withdraw the Ether from the contract
13+
* @author BuidlGuidl
14+
*/
15+
contract YourContract {
16+
// State Variables
17+
address public immutable owner;
18+
string public greeting = "Building Unstoppable Apps!!!";
19+
bool public premium = false;
20+
uint256 public totalCounter = 0;
21+
mapping(address => uint256) public userGreetingCounter;
22+
23+
// Events: a way to emit log statements from smart contract that can be listened to by external parties
24+
event GreetingChange(
25+
address indexed greetingSetter,
26+
string newGreeting,
27+
bool premium,
28+
uint256 value
29+
);
30+
31+
// Constructor: Called once on contract deployment
32+
// Check packages/foundry/deploy/Deploy.s.sol
33+
constructor(address _owner) {
34+
owner = _owner;
35+
}
36+
37+
// Modifier: used to define a set of rules that must be met before or after a function is executed
38+
// Check the withdraw() function
39+
modifier isOwner() {
40+
// msg.sender: predefined variable that represents address of the account that called the current function
41+
require(msg.sender == owner, "Not the Owner");
42+
_;
43+
}
44+
45+
/**
46+
* Function that allows anyone to change the state variable "greeting" of the contract and increase the counters
47+
*
48+
* @param _newGreeting (string memory) - new greeting to save on the contract
49+
*/
50+
function setGreeting(string memory _newGreeting) public payable {
51+
// Print data to the anvil chain console. Remove when deploying to a live network.
52+
53+
console.logString("Setting new greeting");
54+
console.logString(_newGreeting);
55+
56+
greeting = _newGreeting;
57+
totalCounter += 1;
58+
userGreetingCounter[msg.sender] += 1;
59+
60+
// msg.value: built-in global variable that represents the amount of ether sent with the transaction
61+
if (msg.value > 0) {
62+
premium = true;
63+
} else {
64+
premium = false;
65+
}
66+
67+
// emit: keyword used to trigger an event
68+
emit GreetingChange(msg.sender, _newGreeting, msg.value > 0, msg.value);
69+
}
70+
71+
/**
72+
* Function that allows the owner to withdraw all the Ether in the contract
73+
* The function can only be called by the owner of the contract as defined by the isOwner modifier
74+
*/
75+
function withdraw() public isOwner {
76+
(bool success,) = owner.call{ value: address(this).balance }("");
77+
require(success, "Failed to send Ether");
78+
}
79+
80+
/**
81+
* Function that allows the contract to receive ETH
82+
*/
83+
receive() external payable { }
84+
}
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Ignore 31337 deployments
2+
31337.json

packages/foundry/foundry.toml

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
[profile.default]
2+
src = 'contracts'
3+
out = 'out'
4+
libs = ['lib']
5+
fs_permissions = [{ access = "read-write", path = "./"}]
6+
7+
[rpc_endpoints]
8+
default_network = "http://127.0.0.1:8545"
9+
localhost = "http://127.0.0.1:8545"
10+
11+
mainnet = "https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_API_KEY}"
12+
sepolia = "https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
13+
arbitrum = "https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
14+
arbitrumSepolia = "https://arb-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
15+
optimism = "https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
16+
optimismSepolia = "https://opt-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
17+
polygon = "https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
18+
polygonMumbai = "https://polygon-mumbai.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
19+
gnosis = "https://rpc.gnosischain.com"
20+
chiado = "https://rpc.chiadochain.net"
21+
base = "https://mainnet.base.org"
22+
baseGoerli = "https://goerli.base.org"
23+
baseSepolia = "https://sepolia.base.org"
24+
polygonZkEvm = "https://polygonzkevm-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
25+
polygonZkEvmTestnet = "https://polygonzkevm-testnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
26+
zkSyncTestnet = "https://testnet.era.zksync.dev"
27+
zkSync = "https://mainnet.era.zksync.io"
28+
scrollSepolia = "https://sepolia-rpc.scroll.io"
29+
scroll = "https://rpc.scroll.io"
30+
31+
[etherscan]
32+
polygonMumbai = { key = "${ETHERSCAN_API_KEY}" }
33+
sepolia = { key = "${ETHERSCAN_API_KEY}" }
34+
35+
36+
[fmt]
37+
multiline_func_header = "params_first"
38+
line_length = 80
39+
tab_width = 2
40+
quote_style = "double"
41+
bracket_spacing = true
42+
int_types = "long"
43+
44+
# See more config options https://github.com/foundry-rs/foundry/tree/master/config

packages/foundry/lib/forge-std

Submodule forge-std added at 978ac6f

packages/foundry/package.json

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "@se-2/foundry",
3+
"version": "0.0.1",
4+
"type": "module",
5+
"scripts": {
6+
"account": "node scripts-js/ListAccount.js",
7+
"chain": "anvil --config-out localhost.json",
8+
"compile": "forge compile",
9+
"deploy": "forge build --build-info --build-info-path out/build-info/ && forge script script/Deploy.s.sol --rpc-url ${1:-default_network} --broadcast --legacy && node scripts-js/generateTsAbis.js",
10+
"deploy:verify": "forge build --build-info --build-info-path out/build-info/ && forge script script/Deploy.s.sol --rpc-url ${1:-default_network} --broadcast --legacy --verify ; node scripts-js/generateTsAbis.js",
11+
"flatten": "forge flatten",
12+
"fork": "anvil --fork-url ${0:-mainnet} --chain-id 31337 --config-out localhost.json",
13+
"format": "forge fmt && prettier --write ./script/**/*.js",
14+
"generate": "node scripts-js/generateAccount.js",
15+
"lint": "forge fmt --check && prettier --check ./script/**/*.js",
16+
"postinstall": "shx cp -n .env.example .env",
17+
"test": "forge test",
18+
"verify": "forge build --build-info --build-info-path out/build-info/ && forge script script/VerifyAll.s.sol --ffi --rpc-url ${1:-default_network}"
19+
},
20+
"dependencies": {
21+
"dotenv": "~16.3.1",
22+
"envfile": "~6.18.0",
23+
"ethers": "~5.7.1",
24+
"prettier": "~2.8.8",
25+
"qrcode": "~1.5.3",
26+
"toml": "~3.0.0"
27+
},
28+
"devDependencies": {
29+
"shx": "^0.3.4"
30+
}
31+
}

packages/foundry/remappings.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts

0 commit comments

Comments
 (0)