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

Use keystores in Scaffold-Eth #878

Merged
merged 35 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5a59463
feat : use keystore as account
jrcarlos2000 Jul 1, 2024
47a74b5
fix: add setup on yarn chain
jrcarlos2000 Jul 2, 2024
552001a
fix : remove redundant space
jrcarlos2000 Jul 3, 2024
b84a7cf
fix : warning on deploy helper
jrcarlos2000 Jul 3, 2024
e2d4a58
fix : add scaffold-eth-custom keystore on yarn:generate | import
jrcarlos2000 Jul 3, 2024
5735429
fix : update scripts
jrcarlos2000 Jul 3, 2024
fc459aa
feat : allows for custom nmaes through --name on account:import and a…
jrcarlos2000 Jul 3, 2024
aa91883
feat: list accounts using keystore and cast wallet address
jrcarlos2000 Jul 3, 2024
43cd3da
fix : script for account
jrcarlos2000 Jul 3, 2024
24da39d
fix : simplify logic
jrcarlos2000 Jul 3, 2024
996a761
commit package.json changes on yarn install
technophile-04 Jul 9, 2024
960d592
fix verify script
technophile-04 Jul 9, 2024
0949365
chor : reset anvil account to previous balance
jrcarlos2000 Jul 10, 2024
5381eaa
chor : simple logic on script
jrcarlos2000 Jul 10, 2024
243d1b4
fix : typo
jrcarlos2000 Jul 11, 2024
9930073
fix : ether balance
jrcarlos2000 Jul 11, 2024
4c8c6da
chor : dont revert on anvil call fail
jrcarlos2000 Jul 11, 2024
e5c741a
fix : fund deployer at once
jrcarlos2000 Jul 11, 2024
7e90c13
chore : update scripts
jrcarlos2000 Jul 28, 2024
b6cfa29
chore: update scripts
jrcarlos2000 Jul 28, 2024
01fed55
chore: update scripts
jrcarlos2000 Jul 28, 2024
cf8cbd9
enh : update branch and cleanup
jrcarlos2000 Aug 19, 2024
8195dff
fix: double broadcast
jrcarlos2000 Aug 19, 2024
aee94c4
chor: remove unused file
jrcarlos2000 Aug 19, 2024
7337861
fix: remove unused variable
jrcarlos2000 Aug 19, 2024
c90e80c
enh: improve scripts:
jrcarlos2000 Aug 19, 2024
d30c085
format foundry/package.json on yarn install
technophile-04 Aug 20, 2024
23b283e
foundry keystore makefile (#912)
technophile-04 Aug 26, 2024
b90fab5
update verify-keystore and account script, require password for both …
technophile-04 Aug 27, 2024
19b2a54
use flag while passing address to ListAccoutn
technophile-04 Aug 29, 2024
3e82a45
crawl through args to find address in ListAccount.json
technophile-04 Aug 29, 2024
f0ab123
use process.argsv
technophile-04 Aug 29, 2024
aa5e957
Dont require password on localhost
carletex Aug 30, 2024
cbc3ac9
fix forking command
technophile-04 Sep 4, 2024
d9ffad2
setup anvil wallet for fork too(same as yarn chain)
technophile-04 Sep 4, 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
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"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",
"generate": "yarn account:generate",
"account:generate": "yarn workspace @se-2/foundry account:generate",
"account:import": "yarn workspace @se-2/foundry account:import",
"flatten": "yarn workspace @se-2/foundry flatten",
"foundry:format": "yarn workspace @se-2/foundry format",
"foundry:lint": "yarn workspace @se-2/foundry lint",
Expand Down
4 changes: 2 additions & 2 deletions packages/foundry/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
# 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
# Default account for localhost / use "scaffold-eth-custom" if you wish to use a generated account or imported account
ETH_KEYSTORE_ACCOUNT=scaffold-eth-default
3 changes: 1 addition & 2 deletions packages/foundry/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ out/
docs/

# Dotenv file
.env
localhost.json
.env
89 changes: 89 additions & 0 deletions packages/foundry/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
.PHONY: build deploy generate-abis verify-keystore account chain compile deploy-verify flatten fork format lint test verify

# setup wallet for anvil
setup-anvil-wallet:
shx rm ~/.foundry/keystores/scaffold-eth-default 2>/dev/null; \
cast wallet import --private-key 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6 --unsafe-password 'localhost' scaffold-eth-default

# Start local chain
chain: setup-anvil-wallet
anvil

# Start a fork
fork: setup-anvil-wallet
anvil --fork-url ${FORK_URL} --chain-id 31337

# Build the project
build:
forge build --build-info --build-info-path out/build-info/

# Deploy the project
deploy:
@if [ "$(RPC_URL)" = "localhost" ]; then \
forge script script/Deploy.s.sol --rpc-url localhost --password localhost --broadcast --legacy --ffi; \
else \
forge script script/Deploy.s.sol --rpc-url $(RPC_URL) --broadcast --legacy --ffi; \
fi

# Build and deploy target
build-and-deploy: build deploy generate-abis

# Generate TypeScript ABIs
generate-abis:
node scripts-js/generateTsAbis.js

verify-keystore:
if grep -q "scaffold-eth-default" .env; then \
cast wallet address --password localhost; \
else \
cast wallet address; \
fi

# List account
account:
@node scripts-js/ListAccount.js $$(make verify-keystore)

# Generate a new account
account-generate:
@cast wallet import $(ACCOUNT_NAME) --private-key $$(cast wallet new | grep 'Private key:' | awk '{print $$3}')
@echo "Please update .env file with ETH_KEYSTORE_ACCOUNT=$(ACCOUNT_NAME)"

# Import an existing account
account-import:
@cast wallet import ${ACCOUNT_NAME} --interactive

# Compile contracts
compile:
forge compile

# Deploy and verify
deploy-verify:
@if [ "$(RPC_URL)" = "localhost" ]; then \
forge script script/Deploy.s.sol --rpc-url localhost --password localhost --broadcast --legacy --ffi --verify; \
else \
forge script script/Deploy.s.sol --rpc-url $(RPC_URL) --broadcast --legacy --ffi --verify; \
fi
node scripts-js/generateTsAbis.js

# Flatten contracts
flatten:
forge flatten

# Format code
format:
forge fmt && prettier --write ./script/**/*.js

# Lint code
lint:
forge fmt --check && prettier --check ./script/**/*.js

# Run tests
test:
forge test

# Verify contracts
verify:
forge script script/VerifyAll.s.sol --ffi --rpc-url $(RPC_URL)

build-and-verify: build verify

1 change: 0 additions & 1 deletion packages/foundry/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ 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}"
Expand Down
28 changes: 15 additions & 13 deletions packages/foundry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@
"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",
"postinstall": "shx cp -n .env.example .env",
"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}"
"verify-keystore": "make verify-keystore",
"account": "make account",
"account:generate": "make account-generate ACCOUNT_NAME=${1:-scaffold-eth-custom}",
"account:import": "make account-import ACCOUNT_NAME=${1:-scaffold-eth-custom}",
"chain": "make chain",
"compile": "make compile",
"deploy": "make build-and-deploy RPC_URL=${1:-localhost}",
"deploy:verify": "make deploy-verify RPC_URL=${1:-localhost}",
"flatten": "make flatten",
"fork": "make fork FORK_URL=${1:-mainnet}",
"format": "make format",
"lint": "make lint",
"test": "make test",
"verify": "make build-and-verify RPC_URL=${1:-localhost}",
"postinstall": "shx cp -n .env.example .env"
},
"dependencies": {
"dotenv": "~16.3.1",
Expand Down
10 changes: 3 additions & 7 deletions packages/foundry/script/00_deploy_your_contract.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@ import "../contracts/YourContract.sol";
import "./DeployHelpers.s.sol";

contract DeployYourContract is ScaffoldETHDeploy {
function run() external {
uint256 deployerPrivateKey = setupLocalhostEnv();
vm.startBroadcast(deployerPrivateKey);

YourContract yourContract = new YourContract(vm.addr(deployerPrivateKey));
// use `deployer` from `ScaffoldETHDeploy`
function run() external ScaffoldEthDeployerRunner {
YourContract yourContract = new YourContract(deployer);
console.logString(
string.concat(
"YourContract deployed at: ", vm.toString(address(yourContract))
)
);

vm.stopBroadcast();
}
}
20 changes: 1 addition & 19 deletions packages/foundry/script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,12 @@ import "./DeployHelpers.s.sol";
import { DeployYourContract } from "./00_deploy_your_contract.s.sol";

contract DeployScript is ScaffoldETHDeploy {
uint256 deployerPrivateKey;

error InvalidPrivateKey(string);

constructor() {
deployerPrivateKey = setupLocalhostEnv();
}

function run() external ScaffoldEthDeployerRunner {
function run() external {
DeployYourContract deployYourContract = new DeployYourContract();
deployYourContract.run();

// deploy more contracts here
// DeployMyContract deployMyContract = new DeployMyContract();
// deployMyContract.run();
}

modifier ScaffoldEthDeployerRunner() {
if (deployerPrivateKey == 0) {
revert InvalidPrivateKey(
"You don't have a deployer account. Make sure you have set DEPLOYER_PRIVATE_KEY in .env or use `yarn generate` to generate a new random account"
);
}
_;
exportDeployments();
}
}
73 changes: 61 additions & 12 deletions packages/foundry/script/DeployHelpers.s.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "forge-std/Script.sol";
import "forge-std/Vm.sol";
import { Script, console } from "forge-std/Script.sol";
import { Vm } from "forge-std/Vm.sol";

contract ScaffoldETHDeploy is Script {
error InvalidChain();
error DeployerHasNoBalance();
error InvalidPrivateKey(string);

event AnvilSetBalance(address account, uint256 amount);
event FailedAnvilRequest();

struct Deployment {
string name;
Expand All @@ -15,18 +20,38 @@ contract ScaffoldETHDeploy is Script {
string root;
string path;
Deployment[] public deployments;
uint256 constant ANVIL_BASE_BALANCE = 10000 ether;

/// @notice The deployer address for every run
address deployer;

function setupLocalhostEnv() internal returns (uint256 localhostPrivateKey) {
if (block.chainid == 31337) {
root = vm.projectRoot();
path = string.concat(root, "/localhost.json");
string memory json = vm.readFile(path);
bytes memory mnemonicBytes = vm.parseJson(json, ".wallet.mnemonic");
string memory mnemonic = abi.decode(mnemonicBytes, (string));
return vm.deriveKey(mnemonic, 0);
} else {
return vm.envUint("DEPLOYER_PRIVATE_KEY");
/// @notice Use this modifier on your run() function on your deploy scripts
modifier ScaffoldEthDeployerRunner() {
deployer = _startBroadcast();
if (deployer == address(0)) {
revert InvalidPrivateKey("Invalid private key");
}
_;
_stopBroadcast();
exportDeployments();
}

function _startBroadcast() internal returns (address) {
vm.startBroadcast();
(, address _deployer,) = vm.readCallers();

if (block.chainid == 31337 && _deployer.balance == 0) {
try this.anvil_setBalance(_deployer, ANVIL_BASE_BALANCE) {
emit AnvilSetBalance(_deployer, ANVIL_BASE_BALANCE);
} catch {
emit FailedAnvilRequest();
}
}
return _deployer;
}

function _stopBroadcast() internal {
vm.stopBroadcast();
}

function exportDeployments() internal {
Expand Down Expand Up @@ -61,6 +86,30 @@ contract ScaffoldETHDeploy is Script {
return getChain(block.chainid);
}

function anvil_setBalance(address addr, uint256 amount) public {
string memory addressString = vm.toString(addr);
string memory amountString = vm.toString(amount);
string memory requestPayload = string.concat(
'{"method":"anvil_setBalance","params":["',
addressString,
'","',
amountString,
'"],"id":1,"jsonrpc":"2.0"}'
);

string[] memory inputs = new string[](8);
inputs[0] = "curl";
inputs[1] = "-X";
inputs[2] = "POST";
inputs[3] = "http://localhost:8545";
inputs[4] = "-H";
inputs[5] = "Content-Type: application/json";
inputs[6] = "--data";
inputs[7] = requestPayload;

vm.ffi(inputs);
}

function findChainName() public returns (string memory) {
uint256 thisChainId = block.chainid;
string[2][] memory allRpcUrls = vm.rpcUrls();
Expand Down
10 changes: 4 additions & 6 deletions packages/foundry/script/VerifyAll.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ contract VerifyAll is Script {
(address)
);
bytes memory deployedBytecode = abi.decode(
vm.parseJson(content, searchStr(currTransactionIdx, "transaction.data")),
vm.parseJson(content, searchStr(currTransactionIdx, "transaction.input")),
(bytes)
);
bytes memory compiledBytecode = abi.decode(
Expand Down Expand Up @@ -106,11 +106,9 @@ contract VerifyAll is Script {
}
}

function _getCompiledBytecode(string memory contractName)
internal
view
returns (string memory compiledBytecode)
{
function _getCompiledBytecode(
string memory contractName
) internal view returns (string memory compiledBytecode) {
string memory root = vm.projectRoot();
string memory path =
string.concat(root, "/out/", contractName, ".sol/", contractName, ".json");
Expand Down
Loading