Skip to content

Commit

Permalink
merge foundry imporvments changes
Browse files Browse the repository at this point in the history
  • Loading branch information
technophile-04 committed Dec 16, 2024
1 parent dacb14b commit 311f7ce
Show file tree
Hide file tree
Showing 9 changed files with 514 additions and 279 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
//SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "../contracts/YourContract.sol";
import "./DeployHelpers.s.sol";
import "../contracts/YourContract.sol";

/**
* @notice Deploy script for YourContract contract
* @dev Inherits ScaffoldETHDeploy which:
* - Includes forge-std/Script.sol for deployment
* - Includes ScaffoldEthDeployerRunner modifier
* - Provides `deployer` variable
* Example:
* yarn deploy --file DeployYourContract.s.sol # local anvil chain
* yarn deploy --file DeployYourContract.s.sol --network optimism # live network (requires keystore)
*/
contract DeployYourContract is ScaffoldETHDeploy {
// use `deployer` from `ScaffoldETHDeploy`
function run() external ScaffoldEthDeployerRunner {
YourContract yourContract = new YourContract(deployer);
console.logString(string.concat("YourContract deployed at: ", vm.toString(address(yourContract))));
}
/**
* @dev Deployer setup based on `ETH_KEYSTORE_ACCOUNT` in `.env`:
* - "scaffold-eth-default": Uses Anvil's account #9 (0xa0Ee7A142d267C1f36714E4a8F75612F20a79720), no password prompt
* - "scaffold-eth-custom": requires password used while creating keystore
*
* Note: Must use ScaffoldEthDeployerRunner modifier to:
* - Setup correct `deployer` account and fund it
* - Export contract addresses & ABIs to `nextjs` packages
*/
function run() external ScaffoldEthDeployerRunner {
new YourContract(deployer);
}
}
39 changes: 27 additions & 12 deletions templates/solidity-frameworks/foundry/packages/foundry/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
.PHONY: build deploy generate-abis verify-keystore account chain compile deploy-verify flatten fork format lint test verify

DEPLOY_SCRIPT ?= script/Deploy.s.sol

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

# Start local chain
Expand All @@ -15,14 +18,22 @@ fork: setup-anvil-wallet

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

# Deploy the project
# Deploy the contracts
deploy:
@if [ ! -f "$(DEPLOY_SCRIPT)" ]; then \
echo "Error: Deploy script '$(DEPLOY_SCRIPT)' not found"; \
exit 1; \
fi
@if [ "$(RPC_URL)" = "localhost" ]; then \
forge script script/Deploy.s.sol --rpc-url localhost --password localhost --broadcast --legacy --ffi; \
if [ "$(ETH_KEYSTORE_ACCOUNT)" = "scaffold-eth-default" ]; then \
forge script $(DEPLOY_SCRIPT) --rpc-url localhost --password localhost --broadcast --legacy --ffi; \
else \
forge script $(DEPLOY_SCRIPT) --rpc-url localhost --broadcast --legacy --ffi; \
fi \
else \
forge script script/Deploy.s.sol --rpc-url $(RPC_URL) --broadcast --legacy --ffi; \
forge script $(DEPLOY_SCRIPT) --rpc-url $(RPC_URL) --broadcast --legacy --ffi; \
fi

# Build and deploy target
Expand All @@ -35,9 +46,9 @@ generate-abis:
verify-keystore:
if grep -q "scaffold-eth-default" .env; then \
cast wallet address --password localhost; \
else \
else \
cast wallet address; \
fi
fi

# List account
account:
Expand All @@ -58,10 +69,18 @@ compile:

# Deploy and verify
deploy-verify:
@if [ ! -f "$(DEPLOY_SCRIPT)" ]; then \
echo "Error: Deploy script '$(DEPLOY_SCRIPT)' not found"; \
exit 1; \
fi
@if [ "$(RPC_URL)" = "localhost" ]; then \
forge script script/Deploy.s.sol --rpc-url localhost --password localhost --broadcast --legacy --ffi --verify; \
if [ "$(ETH_KEYSTORE_ACCOUNT)" = "scaffold-eth-default" ]; then \
forge script $(DEPLOY_SCRIPT) --rpc-url localhost --password localhost --broadcast --legacy --ffi --verify; \
else \
forge script $(DEPLOY_SCRIPT) --rpc-url localhost --broadcast --legacy --ffi --verify; \
fi \
else \
forge script script/Deploy.s.sol --rpc-url $(RPC_URL) --broadcast --legacy --ffi --verify; \
forge script $(DEPLOY_SCRIPT) --rpc-url $(RPC_URL) --broadcast --legacy --ffi --verify; \
fi
node scripts-js/generateTsAbis.js

Expand All @@ -77,10 +96,6 @@ format:
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ sepolia = { key = "${ETHERSCAN_API_KEY}" }


[fmt]
multiline_func_header = "params_first"
line_length = 80
tab_width = 2
line_length = 120
tab_width = 4
quote_style = "double"
bracket_spacing = true
int_types = "long"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"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}",
"deploy": "node scripts-js/parseArgs.js",
"deploy:verify": "node scripts/parseArgs.js --verify",
"flatten": "make flatten",
"fork": "make fork FORK_URL=${1:-mainnet}",
"format": "make format",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@ pragma solidity ^0.8.19;
import "./DeployHelpers.s.sol";
${deploymentsScriptsImports.filter(Boolean).join("\n")}
/**
* @notice Main deployment script for all contracts
* @dev Run this when you want to deploy multiple contracts at once
*
* Example: yarn deploy # runs this script(without\`--file\` flag)
*/
contract DeployScript is ScaffoldETHDeploy {
function run() external {
// Deploys all your contracts sequentially
// Add new deployments here when needed
${deploymentsLogic.filter(Boolean).join("\n")}
// deploy more contracts here
// DeployMyContract deployMyContract = new DeployMyContract();
// deployMyContract.run();
// Deploy another contract
// DeployMyContract myContract = new DeployMyContract();
// myContract.run();
}
}`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,123 +5,117 @@ 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;
address addr;
}

string root;
string path;
Deployment[] public deployments;
uint256 constant ANVIL_BASE_BALANCE = 10000 ether;

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

/// @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");
error InvalidChain();
error DeployerHasNoBalance();
error InvalidPrivateKey(string);

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

struct Deployment {
string name;
address addr;
}
_;
_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();
}

string root;
string path;
Deployment[] public deployments;
uint256 constant ANVIL_BASE_BALANCE = 10000 ether;

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

/// @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();
}
return _deployer;
}

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

function exportDeployments() internal {
// fetch already existing contracts
root = vm.projectRoot();
path = string.concat(root, "/deployments/");
string memory chainIdStr = vm.toString(block.chainid);
path = string.concat(path, string.concat(chainIdStr, ".json"));
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;
}

string memory jsonWrite;
function _stopBroadcast() internal {
vm.stopBroadcast();
}

uint256 len = deployments.length;
function exportDeployments() internal {
// fetch already existing contracts
root = vm.projectRoot();
path = string.concat(root, "/deployments/");
string memory chainIdStr = vm.toString(block.chainid);
path = string.concat(path, string.concat(chainIdStr, ".json"));

for (uint256 i = 0; i < len; i++) {
vm.serializeString(
jsonWrite, vm.toString(deployments[i].addr), deployments[i].name
);
string memory jsonWrite;

uint256 len = deployments.length;

for (uint256 i = 0; i < len; i++) {
vm.serializeString(jsonWrite, vm.toString(deployments[i].addr), deployments[i].name);
}

string memory chainName;

try this.getChain() returns (Chain memory chain) {
chainName = chain.name;
} catch {
chainName = findChainName();
}
jsonWrite = vm.serializeString(jsonWrite, "networkName", chainName);
vm.writeJson(jsonWrite, path);
}

string memory chainName;
function getChain() public returns (Chain memory) {
return getChain(block.chainid);
}

try this.getChain() returns (Chain memory chain) {
chainName = chain.name;
} catch {
chainName = findChainName();
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);
}
jsonWrite = vm.serializeString(jsonWrite, "networkName", chainName);
vm.writeJson(jsonWrite, path);
}

function getChain() public returns (Chain memory) {
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();
for (uint256 i = 0; i < allRpcUrls.length; i++) {
try vm.createSelectFork(allRpcUrls[i][1]) {
if (block.chainid == thisChainId) {
return allRpcUrls[i][0];

function findChainName() public returns (string memory) {
uint256 thisChainId = block.chainid;
string[2][] memory allRpcUrls = vm.rpcUrls();
for (uint256 i = 0; i < allRpcUrls.length; i++) {
try vm.createSelectFork(allRpcUrls[i][1]) {
if (block.chainid == thisChainId) {
return allRpcUrls[i][0];
}
} catch {
continue;
}
}
} catch {
continue;
}
revert InvalidChain();
}
revert InvalidChain();
}
}
Loading

0 comments on commit 311f7ce

Please sign in to comment.