Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to foundry #867

Merged
merged 27 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1a7a131
add foundry changes without submodules
technophile-04 Jun 19, 2024
f0c14ec
forge install: forge-std
technophile-04 Jun 19, 2024
2b6a766
forge install: openzeppelin-contracts
technophile-04 Jun 19, 2024
f15c6d1
forge install: solidity-bytes-utils
technophile-04 Jun 19, 2024
941797a
update gh workflow file
technophile-04 Jun 19, 2024
5247608
fix gh-actions: unignore deployments 31337.json
technophile-04 Jun 19, 2024
ae36666
Revert "fix gh-actions: unignore deployments 31337.json"
technophile-04 Jun 19, 2024
d0755b9
add .gitignore inside deployemnts folder
technophile-04 Jun 19, 2024
b272a98
remove workflow file from foundry package
technophile-04 Jun 19, 2024
bc0323b
update .env.example
technophile-04 Jun 24, 2024
e68e0a7
use node es modules
technophile-04 Jun 24, 2024
72dc85d
move all js files inder scripts-js dir
technophile-04 Jun 24, 2024
96e9f18
update README
technophile-04 Jun 24, 2024
dac5c05
configure basic lint/formatting code
technophile-04 Jun 24, 2024
b8cc2d6
remove types devDependencies from foundry package
technophile-04 Jun 24, 2024
ad9b88c
minor tweak to README
technophile-04 Jun 24, 2024
40e0107
minor tweak to .env.example
technophile-04 Jun 24, 2024
3c1659a
Merge branch 'main' into foundry-main
carletex Jun 24, 2024
caff159
yarn.lock regenerate
carletex Jun 24, 2024
951f733
Use cpy-cli to create .env on postinstall
carletex Jun 24, 2024
5e43708
update .env.example
technophile-04 Jun 25, 2024
3257010
remove console.log from generateAccount.js
technophile-04 Jun 25, 2024
52882e7
update YourContract comment
technophile-04 Jun 26, 2024
46443fb
use shx instead of cpy-cli
carletex Jun 26, 2024
abf1e81
Merge remote-tracking branch 'origin/foundry-main--cp-env' into found…
technophile-04 Jun 27, 2024
b2d0cfc
remove cp command from readme
technophile-04 Jun 27, 2024
a126be9
Add installation note for windows users
Pabl0cks Jun 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,18 @@ jobs:
- name: Install dependencies
run: yarn install --immutable

- name: Run hardhat node, deploy contracts (& generate contracts typescript output)
- name: Install foundry-toolchain
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Run foundry node, deploy contracts (& generate contracts typescript output)
env:
ETHERSCAN_API_KEY: ${{ secrets.ETHERSCAN_API_KEY }}
run: yarn chain & yarn deploy

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

- name: Check typings on nextjs
run: yarn next:check-types

- name: Run hardhat lint
run: yarn hardhat:lint --max-warnings=0
9 changes: 9 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[submodule "packages/foundry/lib/forge-std"]
path = packages/foundry/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "packages/foundry/lib/openzeppelin-contracts"]
path = packages/foundry/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "packages/foundry/lib/solidity-bytes-utils"]
path = packages/foundry/lib/solidity-bytes-utils
url = https://github.com/gnsps/solidity-bytes-utils
8 changes: 2 additions & 6 deletions .lintstagedrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@ const buildNextEslintCommand = (filenames) =>

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

const buildHardhatEslintCommand = (filenames) =>
`yarn hardhat:lint-staged --fix ${filenames
.map((f) => path.relative(path.join("packages", "hardhat"), f))
.join(" ")}`;

module.exports = {
"packages/nextjs/**/*.{ts,tsx}": [
buildNextEslintCommand,
checkTypesNextCommand,
],
"packages/hardhat/**/*.{ts,tsx}": [buildHardhatEslintCommand],
"packages/foundry/**/*.sol": ["forge fmt --root packages/foundry"],
"packages/foundry/**/*.js": ["yarn workspace @se-2/foundry prettier --write"],
};
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

🧪 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.

⚙️ Built using NextJS, RainbowKit, Hardhat, Wagmi, Viem, and Typescript.
⚙️ Built using NextJS, RainbowKit, Foundry, Wagmi, Viem, and Typescript.

- ✅ **Contract Hot Reload**: Your frontend auto-adapts to your smart contract as you edit it.
- 🪝 **[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.
Expand All @@ -24,6 +24,7 @@ Before you begin, you need to install the following tools:
- [Node (>= v18.17)](https://nodejs.org/en/download/)
- Yarn ([v1](https://classic.yarnpkg.com/en/docs/install/) or [v2+](https://yarnpkg.com/getting-started/install))
- [Git](https://git-scm.com/downloads)
- [Foundryup](https://book.getfoundry.sh/getting-started/installation)

## Quickstart

Expand All @@ -34,24 +35,32 @@ To get started with Scaffold-ETH 2, follow the steps below:
```
git clone https://github.com/scaffold-eth/scaffold-eth-2.git
cd scaffold-eth-2
yarn install
yarn install && forge install --root packages/foundry
```

2. Run a local network in the first terminal:
2. Create `packages/foundry/.env` file based of on `packages/foundry/.env.example`

```
cp packages/foundry/.env.example packages/foundry/.env
```

> NOTE: If you are using windows and not using git bash or wsl, use `copy packages\foundry\.env.example packages\foundry\.env`

3. Run a local network in the first terminal:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that you already commented about this in the PR comment. Having to do this is a PITA (the 3 magic commands don't work out of the box), so I've been trying some options (postinstall as you mentioned)

branch: https://github.com/scaffold-eth/scaffold-eth-2/commits/foundry-main--cp-env/
commit: 951f733

Using the smallest copy lib that I could find (even tho it installs a few other deps, maybe we can explore other options), which should work on any OS.

I remember that we had some issues with the postinstall script (not running at all in some OS? Or running after every time you run yarn install? Added the --no-overwrite in case it's the latter).

What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we take this path, this can help to decide about the lib to use. https://pkg-size.dev/

eg. https://pkg-size.dev/cpy-cli => 1.3MB vs the 5 KB advertised (which doesn't count the deps)

Copy link
Collaborator Author

@technophile-04 technophile-04 Jun 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After researching for a while I think postinstall seems a safe option.

Some notes on `postinstall` script:
  1. Postinstall in yarn will run only when something in root node_modules changes(which means some package is added in dependency or devDependency of root package.json) or node_moduels is initialized

    example image :

    Screenshot 2024-06-25 at 1 55 55 PM

  2. Postinstall in yarn does not log output to stdout, which means If you do postinstall: echo 'hello world' it won't log hello world. It will only show output on error (example this image )

  3. Running yarn install multiple times won't run postinstall multiple times until you add any package to root pacakage.json. If you add npm package in nextjs it won't run.

So considering all the above points, I think postinstall seems a fine options for us

not running at all in some OS?

Even I had the same feeling, but went through SE-2 issues throughly and could only found this : #275

The above issue was not related too much related to postinstall(since postinstall ran) but it was related to node js script not resolving proper path on windows.

So yeah 951f733 seems good if it works nicely on windows (hopefully it resolves path correctly internally)

Another options we could also put our own node script at root of monorepo and call it in postinstall: node startUp.js but we need to make sure it works properly on windows the path resolution thing.

Copy link
Collaborator Author

@technophile-04 technophile-04 Jun 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was just trying https://github.com/scaffold-eth/scaffold-eth-2/tree/foundry-main--cp-env and found a minor disadvantage that:

  1. First you clone above repo and yarn install this creates .env.example nicely in pacakge/foundry
  2. If you try to install node dependency in foundry package cd packages/foundry and yarn add viem it will fail :
    Screenshot 2024-06-26 at 2 31 44 PM

basically you won't be able to install any node / js dependency in foundry package because it will fail since we are using ---no-overwrite it throwing error

An alternatie solution will be finding a library which doesn't throw error or writting our own node script which doesn't throw error if .env is already present. The only reason I am afraid of writing our own script is because of #275 where isn't properly able to get the path but maybe we should give it another shot?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is what we need: https://www.npmjs.com/package/shx (we can use commands from linux, and we could copy... or even test if the file exist before copying)

And it takes less space https://pkg-size.dev/shx

I'll give it a shot

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about this (using shx): 46443fb

I pushed it to https://github.com/scaffold-eth/scaffold-eth-2/commits/foundry-main--cp-env/

If we like it, we can have Pablo to test on Windows.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noiicee, just tried it out and works great!! Tysm!!, I think this works great!! Will merge in this changes!


```
yarn chain
```

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`.
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`.

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

```
yarn deploy
```

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.
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.

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

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

**What's next**:

- Edit your smart contract `YourContract.sol` in `packages/hardhat/contracts`
- Edit your smart contract `YourContract.sol` in `packages/foundry/contracts`
- 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.
- Edit your deployment scripts in `packages/hardhat/deploy`
- Edit your smart contract test in: `packages/hardhat/test`. To run test use `yarn hardhat:test`
- Edit your deployment scripts in `packages/script/deploy/Deploy.s.sol`
- Edit your smart contract test in: `packages/foundry/test`. To run test use `yarn foundry:test`

## Documentation

Expand Down
31 changes: 15 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,25 @@
"private": true,
"workspaces": {
"packages": [
"packages/hardhat",
"packages/foundry",
"packages/nextjs"
]
},
"scripts": {
"account": "yarn workspace @se-2/hardhat account",
"chain": "yarn workspace @se-2/hardhat chain",
"fork": "yarn workspace @se-2/hardhat fork",
"deploy": "yarn workspace @se-2/hardhat deploy",
"verify": "yarn workspace @se-2/hardhat verify",
"hardhat-verify": "yarn workspace @se-2/hardhat hardhat-verify",
"compile": "yarn workspace @se-2/hardhat compile",
"generate": "yarn workspace @se-2/hardhat generate",
"flatten": "yarn workspace @se-2/hardhat flatten",
"hardhat:lint": "yarn workspace @se-2/hardhat lint",
"hardhat:lint-staged": "yarn workspace @se-2/hardhat lint-staged",
"hardhat:format": "yarn workspace @se-2/hardhat format",
"hardhat:test": "yarn workspace @se-2/hardhat test",
"test": "yarn hardhat:test",
"format": "yarn next:format && yarn hardhat:format",
"account": "yarn workspace @se-2/foundry account",
"chain": "yarn workspace @se-2/foundry chain",
"fork": "yarn workspace @se-2/foundry fork",
"deploy": "yarn workspace @se-2/foundry deploy",
"verify": "yarn workspace @se-2/foundry verify",
"deploy:verify": "yarn workspace @se-2/foundry deploy:verify",
"compile": "yarn workspace @se-2/foundry compile",
"generate": "yarn workspace @se-2/foundry generate",
"flatten": "yarn workspace @se-2/foundry flatten",
"foundry:format": "yarn workspace @se-2/foundry format",
"foundry:lint": "yarn workspace @se-2/foundry lint",
"foundry:test": "yarn workspace @se-2/foundry test",
"test": "yarn foundry:test",
"format": "yarn next:format && yarn foundry:format",
"start": "yarn workspace @se-2/nextjs dev",
"next:lint": "yarn workspace @se-2/nextjs lint",
"next:format": "yarn workspace @se-2/nextjs format",
Expand Down
21 changes: 21 additions & 0 deletions packages/foundry/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Template for foundry environment variables.

# For local development, copy this file, rename it to .env, and fill in the values.

# We provide default values so developers can start prototyping out of the box,
# but we recommend getting your own API Keys for Production Apps.

# DEPLOYER_PRIVATE_KEY is used while deploying contract, while deploying contract.
technophile-04 marked this conversation as resolved.
Show resolved Hide resolved
# On anvil chain the value of it can be empty and we will use the prefunded account
# which comes with anvil chain to deploy contract.
# NOTE: You don't need to manually change the value of DEPLOYER_PRIVATE_KEY manually, it should
technophile-04 marked this conversation as resolved.
Show resolved Hide resolved
# be auto filled when run `yarn generate`.
# Although `.env` is ignored by git, it's still important that you don't paste your
# actual account private key and use the generated one.
DEPLOYER_PRIVATE_KEY=

# Alchemy rpc URL is used while deploying the contracts to some testnets/mainnets, checkout `foundry.toml` for it's use.
ALCHEMY_API_KEY=oKxs-03sij-U_N0iOlrSsZFr29-IqbuF

# Etherscan API key is used to verify the contract on etherscan.
ETHERSCAN_API_KEY=DNXJA8RX2Q3VZ4URQIWP7Z68CJXQZSC6AW
14 changes: 14 additions & 0 deletions packages/foundry/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Compiler files
cache/
out/

# Ignores development broadcast logs
/broadcast/*/31337/
/broadcast/**/dry-run/

# Docs
docs/

# Dotenv file
.env
localhost.json
6 changes: 6 additions & 0 deletions packages/foundry/.prettier.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"arrowParens": "avoid",
"printWidth": 120,
"tabWidth": 2,
"trailingComma": "all"
}
84 changes: 84 additions & 0 deletions packages/foundry/contracts/YourContract.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

// Useful for debugging. Remove when deploying to a live network.
import "forge-std/console.sol";

// Use openzeppelin to inherit battle-tested implementations (ERC20, ERC721, etc)
// import "@openzeppelin/contracts/access/Ownable.sol";

/**
* A smart contract that allows changing a state variable of the contract and tracking the changes
* It also allows the owner to withdraw the Ether in the contract
rin-st marked this conversation as resolved.
Show resolved Hide resolved
* @author BuidlGuidl
*/
contract YourContract {
// State Variables
address public immutable owner;
string public greeting = "Building Unstoppable Apps!!!";
bool public premium = false;
uint256 public totalCounter = 0;
mapping(address => uint256) public userGreetingCounter;

// Events: a way to emit log statements from smart contract that can be listened to by external parties
event GreetingChange(
address indexed greetingSetter,
string newGreeting,
bool premium,
uint256 value
);

// Constructor: Called once on contract deployment
// Check packages/foundry/deploy/Deploy.s.sol
constructor(address _owner) {
owner = _owner;
}

// Modifier: used to define a set of rules that must be met before or after a function is executed
// Check the withdraw() function
modifier isOwner() {
// msg.sender: predefined variable that represents address of the account that called the current function
require(msg.sender == owner, "Not the Owner");
_;
}

/**
* Function that allows anyone to change the state variable "greeting" of the contract and increase the counters
*
* @param _newGreeting (string memory) - new greeting to save on the contract
*/
function setGreeting(string memory _newGreeting) public payable {
// Print data to the anvil chain console. Remove when deploying to a live network.

console.logString("Setting new greeting");
console.logString(_newGreeting);

greeting = _newGreeting;
totalCounter += 1;
userGreetingCounter[msg.sender] += 1;

// msg.value: built-in global variable that represents the amount of ether sent with the transaction
if (msg.value > 0) {
premium = true;
} else {
premium = false;
}

// emit: keyword used to trigger an event
emit GreetingChange(msg.sender, _newGreeting, msg.value > 0, msg.value);
}

/**
* Function that allows the owner to withdraw all the Ether in the contract
* The function can only be called by the owner of the contract as defined by the isOwner modifier
*/
function withdraw() public isOwner {
(bool success,) = owner.call{ value: address(this).balance }("");
require(success, "Failed to send Ether");
}

/**
* Function that allows the contract to receive ETH
*/
receive() external payable { }
}
2 changes: 2 additions & 0 deletions packages/foundry/deployments/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ignore 31337 deployments
31337.json
44 changes: 44 additions & 0 deletions packages/foundry/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
[profile.default]
src = 'contracts'
out = 'out'
libs = ['lib']
fs_permissions = [{ access = "read-write", path = "./"}]

[rpc_endpoints]
default_network = "http://127.0.0.1:8545"
localhost = "http://127.0.0.1:8545"

mainnet = "https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_API_KEY}"
sepolia = "https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
arbitrum = "https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
arbitrumSepolia = "https://arb-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
optimism = "https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
optimismSepolia = "https://opt-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
polygon = "https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
polygonMumbai = "https://polygon-mumbai.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
gnosis = "https://rpc.gnosischain.com"
chiado = "https://rpc.chiadochain.net"
base = "https://mainnet.base.org"
baseGoerli = "https://goerli.base.org"
baseSepolia = "https://sepolia.base.org"
polygonZkEvm = "https://polygonzkevm-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
polygonZkEvmTestnet = "https://polygonzkevm-testnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
zkSyncTestnet = "https://testnet.era.zksync.dev"
zkSync = "https://mainnet.era.zksync.io"
scrollSepolia = "https://sepolia-rpc.scroll.io"
scroll = "https://rpc.scroll.io"

[etherscan]
polygonMumbai = { key = "${ETHERSCAN_API_KEY}" }
sepolia = { key = "${ETHERSCAN_API_KEY}" }


[fmt]
multiline_func_header = "params_first"
line_length = 80
tab_width = 2
quote_style = "double"
bracket_spacing = true
int_types = "long"

# See more config options https://github.com/foundry-rs/foundry/tree/master/config
1 change: 1 addition & 0 deletions packages/foundry/lib/forge-std
Submodule forge-std added at 978ac6
1 change: 1 addition & 0 deletions packages/foundry/lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at dbb610
1 change: 1 addition & 0 deletions packages/foundry/lib/solidity-bytes-utils
Submodule solidity-bytes-utils added at e0115c
27 changes: 27 additions & 0 deletions packages/foundry/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "@se-2/foundry",
"version": "0.0.1",
"type": "module",
"scripts": {
"account": "node scripts-js/ListAccount.js",
"chain": "anvil --config-out localhost.json",
"compile": "forge compile",
"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",
"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",
"flatten": "forge flatten",
"fork": "anvil --fork-url ${0:-mainnet} --chain-id 31337 --config-out localhost.json",
"format": "forge fmt && prettier --write ./script/**/*.js",
"generate": "node scripts-js/generateAccount.js",
"lint": "forge fmt --check && prettier --check ./script/**/*.js",
"test": "forge test",
"verify": "forge build --build-info --build-info-path out/build-info/ && forge script script/VerifyAll.s.sol --ffi --rpc-url ${1:-default_network}"
},
"dependencies": {
"dotenv": "~16.3.1",
"envfile": "~6.18.0",
"ethers": "~5.7.1",
"prettier": "~2.8.8",
"qrcode": "~1.5.3",
"toml": "~3.0.0"
}
}
1 change: 1 addition & 0 deletions packages/foundry/remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts
Loading
Loading