diff --git a/package.json b/package.json index 172d5e1..75209ec 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "bin": "bin/create-dapp-se2.js", "scripts": { "build": "rollup -c rollup.config.js", + "build-run": "yarn build && yarn cli", "dev": "rollup -c rollup.config.js --watch", "cli": "node bin/create-dapp-se2.js", "test": "echo \"Error: no test specified\" && exit 1", @@ -22,7 +23,6 @@ "scaffold-eth 2", "wagmi", "hardhat", - "foundry", "viem", "rainbowkit" ], diff --git a/src/config.ts b/src/config.ts index a6f281e..dcf66a9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -6,7 +6,7 @@ const config: Config = { type: "single-select", name: "solidity-framework", message: "What solidity framework do you want to use?", - extensions: ["hardhat", "foundry", null], + extensions: ["hardhat", null], default: "hardhat", }), ], diff --git a/src/main.ts b/src/main.ts index 0341184..7ceacaf 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,16 +1,16 @@ +import chalk from "chalk"; +import Listr from "listr"; +import path from "path"; +import { fileURLToPath } from "url"; import { copyTemplateFiles, + createFirstGitCommit, createProjectDirectory, installPackages, - createFirstGitCommit, prettierFormat, } from "./tasks"; import type { Options } from "./types"; import { renderOutroMessage } from "./utils/render-outro-message"; -import chalk from "chalk"; -import Listr from "listr"; -import path from "path"; -import { fileURLToPath } from "url"; export async function createProject(options: Options) { console.log(`\n`); @@ -55,9 +55,7 @@ export async function createProject(options: Options) { }, }, { - title: `📡 Initializing Git repository ${ - options.extensions.includes("foundry") ? "and submodules" : "" - }`, + title: `📡 Initializing Git repository`, task: () => createFirstGitCommit(targetDirectory, options), }, ]); diff --git a/src/tasks/create-first-git-commit.ts b/src/tasks/create-first-git-commit.ts index 97ba1f0..7faa427 100644 --- a/src/tasks/create-first-git-commit.ts +++ b/src/tasks/create-first-git-commit.ts @@ -1,6 +1,5 @@ import { execa } from "execa"; import { Options } from "../types"; -import path from "path"; // Checkout the latest release tag in a git submodule async function checkoutLatestTag(submodulePath: string): Promise { @@ -26,73 +25,13 @@ export async function createFirstGitCommit( options: Options ) { try { - // TODO: Move the logic for adding submodules to tempaltes - if (options.extensions?.includes("foundry")) { - const foundryWorkSpacePath = path.resolve( - targetDir, - "packages", - "foundry" - ); - await execa( - "git", - [ - "submodule", - "add", - "https://github.com/foundry-rs/forge-std", - "lib/forge-std", - ], - { - cwd: foundryWorkSpacePath, - } - ); - await execa( - "git", - [ - "submodule", - "add", - "https://github.com/OpenZeppelin/openzeppelin-contracts", - "lib/openzeppelin-contracts", - ], - { - cwd: foundryWorkSpacePath, - } - ); - await execa( - "git", - [ - "submodule", - "add", - "https://github.com/gnsps/solidity-bytes-utils", - "lib/solidity-bytes-utils", - ], - { - cwd: foundryWorkSpacePath, - } - ); - await execa("git", ["submodule", "update", "--init", "--recursive"], { - cwd: foundryWorkSpacePath, - }); - await checkoutLatestTag( - path.resolve(foundryWorkSpacePath, "lib", "forge-std") - ); - await checkoutLatestTag( - path.resolve(foundryWorkSpacePath, "lib", "openzeppelin-contracts") - ); - } - + // TODO: Move the logic for adding submodules to templates await execa("git", ["add", "-A"], { cwd: targetDir }); await execa( "git", ["commit", "-m", "Initial commit with 🏗️ Scaffold-ETH 2", "--no-verify"], { cwd: targetDir } ); - - // Update the submodule, since we have checked out the latest tag in the previous step of foundry - if (options.extensions?.includes("foundry")) { - await execa("git", ["submodule", "update", "--init", "--recursive"], { - cwd: path.resolve(targetDir, "packages", "foundry"), - }); - } } catch (e: any) { // cast error as ExecaError to get stderr diff --git a/src/types.ts b/src/types.ts index 20ee48a..58135af 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,7 +17,7 @@ export type Options = NonNullableRawOptions; export type Extension = | "hardhat" - | "foundry" + type NullExtension = null; export type ExtensionOrNull = Extension | NullExtension; // corresponds to inquirer question types: diff --git a/src/utils/render-intro-message.ts b/src/utils/render-intro-message.ts index def4838..fc180fd 100644 --- a/src/utils/render-intro-message.ts +++ b/src/utils/render-intro-message.ts @@ -2,7 +2,7 @@ import chalk from "chalk"; export const TITLE_TEXT = ` ${chalk.bold.blue("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+")} - ${chalk.bold.blue("| Create Scaffold-ETH 2 app |")} + ${chalk.bold.blue("| Create Fhenix DApp |")} ${chalk.bold.blue("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+")} `; diff --git a/src/utils/render-outro-message.ts b/src/utils/render-outro-message.ts index 58c83a1..9890385 100644 --- a/src/utils/render-outro-message.ts +++ b/src/utils/render-outro-message.ts @@ -1,6 +1,5 @@ -import type { Options } from "../types"; import chalk from "chalk"; -import { execa } from "execa"; +import type { Options } from "../types"; export async function renderOutroMessage(options: Options) { let message = ` @@ -12,28 +11,12 @@ export async function renderOutroMessage(options: Options) { ${chalk.dim("cd")} ${options.project} `; - if ( - options.extensions.includes("hardhat") || - options.extensions.includes("foundry") - ) { + if (options.extensions.includes("hardhat")) { message += ` \t${chalk.bold("Start the local development node")} \t${chalk.dim("yarn")} chain `; - if (options.extensions.includes("foundry")) { - try { - await execa("foundryup", ["-h"]); - } catch (error) { - message += ` - \t${chalk.bold.yellow( - "(NOTE: Foundryup is not installed in your system)" - )} - \t${chalk.dim("Checkout: https://getfoundry.sh")} - `; - } - } - message += ` \t${chalk.bold("In a new terminal window, deploy your contracts")} \t${chalk.dim("yarn")} deploy diff --git a/templates/extensions/foundry/.vercelignore.args.mjs b/templates/extensions/foundry/.vercelignore.args.mjs deleted file mode 100644 index dc52e76..0000000 --- a/templates/extensions/foundry/.vercelignore.args.mjs +++ /dev/null @@ -1,15 +0,0 @@ -export const packageVercelIgnoreContent = `# --- Foundry files --- - -# Compiler files -packages/foundry/cache -packages/foundry/out - -# Ignores development broadcast logs -packages/foundry/broadcast - -# Docs -packages/foundry/docs - -# Dotenv file -packages/foundry/.env -packages/foundry/localhost.json`; diff --git a/templates/extensions/foundry/README.md.args.mjs b/templates/extensions/foundry/README.md.args.mjs deleted file mode 100644 index 750d91a..0000000 --- a/templates/extensions/foundry/README.md.args.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export const solidityFramework = "Foundry"; -export const networkConfigPath = `\`packages/foundry/foundry.toml\``; -export const contractsPath = `\`packages/foundry/contracts\``; -export const scriptsPath = `\`packages/foundry/script\``; -export const testCommand = `\`yarn foundry:test\``; diff --git a/templates/extensions/foundry/package.json b/templates/extensions/foundry/package.json deleted file mode 100644 index 53be852..0000000 --- a/templates/extensions/foundry/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "scripts": { - "account": "yarn workspace @se-2/foundry account", - "fork": "yarn workspace @se-2/foundry fork", - "compile": "yarn workspace @se-2/foundry compile", - "chain": "yarn workspace @se-2/foundry chain", - "deploy": "yarn workspace @se-2/foundry deploy", - "deploy:verify": "yarn workspace @se-2/foundry deploy:verify", - "foundry:lint": "yarn workspace @se-2/foundry lint", - "foundry:test": "yarn workspace @se-2/foundry test", - "foundry:format": "yarn workspace @se-2/foundry format", - "test": "yarn foundry:test", - "verify": "yarn workspace @se-2/foundry verify", - "generate": "yarn workspace @se-2/foundry generate", - "flatten": "yarn workspace @se-2/foundry flatten", - "format": "yarn next:format && yarn foundry:format" - } -} diff --git a/templates/extensions/foundry/packages/foundry/.env.example b/templates/extensions/foundry/packages/foundry/.env.example deleted file mode 100644 index 7fe93e3..0000000 --- a/templates/extensions/foundry/packages/foundry/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -DEPLOYER_PRIVATE_KEY= -ETHERSCAN_API_KEY= -ALCHEMY_API_KEY= \ No newline at end of file diff --git a/templates/extensions/foundry/packages/foundry/.env.template.mjs b/templates/extensions/foundry/packages/foundry/.env.template.mjs deleted file mode 100644 index 62fd71d..0000000 --- a/templates/extensions/foundry/packages/foundry/.env.template.mjs +++ /dev/null @@ -1,7 +0,0 @@ -const contents = () => -`DEPLOYER_PRIVATE_KEY= -ALCHEMY_API_KEY=oKxs-03sij-U_N0iOlrSsZFr29-IqbuF -ETHERSCAN_API_KEY=DNXJA8RX2Q3VZ4URQIWP7Z68CJXQZSC6AW -` - -export default contents diff --git a/templates/extensions/foundry/packages/foundry/.github/workflows/test.yml b/templates/extensions/foundry/packages/foundry/.github/workflows/test.yml deleted file mode 100644 index 09880b1..0000000 --- a/templates/extensions/foundry/packages/foundry/.github/workflows/test.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: test - -on: workflow_dispatch - -env: - FOUNDRY_PROFILE: ci - -jobs: - check: - strategy: - fail-fast: true - - name: Foundry project - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - - - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 - with: - version: nightly - - - name: Run Forge build - run: | - forge --version - forge build --sizes - id: build - - - name: Run Forge tests - run: | - forge test -vvv - id: test diff --git a/templates/extensions/foundry/packages/foundry/.gitignore.template.mjs b/templates/extensions/foundry/packages/foundry/.gitignore.template.mjs deleted file mode 100644 index c3e93ad..0000000 --- a/templates/extensions/foundry/packages/foundry/.gitignore.template.mjs +++ /dev/null @@ -1,19 +0,0 @@ -const contents = () => -`# Compiler files -cache/ -out/ - -# Ignores development broadcast logs - -/broadcast/*/31337/ -/broadcast/**/dry-run/ - -# Docs -docs/ - -# Dotenv file -.env -localhost.json -` - -export default contents \ No newline at end of file diff --git a/templates/extensions/foundry/packages/foundry/.prettier.json b/templates/extensions/foundry/packages/foundry/.prettier.json deleted file mode 100644 index 7eef1ab..0000000 --- a/templates/extensions/foundry/packages/foundry/.prettier.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "arrowParens": "avoid", - "printWidth": 120, - "tabWidth": 2, - "trailingComma": "all" -} diff --git a/templates/extensions/foundry/packages/foundry/contracts/YourContract.sol b/templates/extensions/foundry/packages/foundry/contracts/YourContract.sol deleted file mode 100644 index 631b8b1..0000000 --- a/templates/extensions/foundry/packages/foundry/contracts/YourContract.sol +++ /dev/null @@ -1,84 +0,0 @@ -//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 - * @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 {} -} diff --git a/templates/extensions/foundry/packages/foundry/deployments/.gitignore b/templates/extensions/foundry/packages/foundry/deployments/.gitignore deleted file mode 100644 index c96a04f..0000000 --- a/templates/extensions/foundry/packages/foundry/deployments/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/templates/extensions/foundry/packages/foundry/foundry.toml b/templates/extensions/foundry/packages/foundry/foundry.toml deleted file mode 100644 index c35fb35..0000000 --- a/templates/extensions/foundry/packages/foundry/foundry.toml +++ /dev/null @@ -1,41 +0,0 @@ -[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}" -goerli = "https://eth-goerli.alchemyapi.io/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}" } -goerli = { key = "${ETHERSCAN_API_KEY}" } - - -[fmt] -line_length = 80 -multiline_func_header = "params_first" - -# See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/templates/extensions/foundry/packages/foundry/package.json b/templates/extensions/foundry/packages/foundry/package.json deleted file mode 100644 index 81dddfa..0000000 --- a/templates/extensions/foundry/packages/foundry/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "@se-2/foundry", - "version": "0.0.1", - "scripts": { - "account": "node script/ListAccount.js", - "chain": "anvil --config-out localhost.json", - "fork": "anvil --fork-url ${0:-mainnet} --chain-id 31337 --config-out localhost.json", - "compile": "forge compile", - "generate": "node script/generateAccount.js", - "flatten": "forge flatten", - "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 script/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 script/generateTsAbis.js", - "verify": "forge build --build-info --build-info-path out/build-info/ && forge script script/VerifyAll.s.sol --ffi --rpc-url ${1:-default_network}", - "lint": "forge fmt --check && prettier --check ./script/**/*.js", - "format": "forge fmt && prettier --write ./script/**/*.js", - "test": "forge test" - }, - "devDependencies": { - "@types/prettier": "2", - "@types/qrcode": "1" - }, - "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" - } -} diff --git a/templates/extensions/foundry/packages/foundry/remappings.txt b/templates/extensions/foundry/packages/foundry/remappings.txt deleted file mode 100644 index df3cb81..0000000 --- a/templates/extensions/foundry/packages/foundry/remappings.txt +++ /dev/null @@ -1 +0,0 @@ -@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts diff --git a/templates/extensions/foundry/packages/foundry/script/Deploy.s.sol b/templates/extensions/foundry/packages/foundry/script/Deploy.s.sol deleted file mode 100644 index 15b0b10..0000000 --- a/templates/extensions/foundry/packages/foundry/script/Deploy.s.sol +++ /dev/null @@ -1,36 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import "../contracts/YourContract.sol"; -import "./DeployHelpers.s.sol"; - -contract DeployScript is ScaffoldETHDeploy { - error InvalidPrivateKey(string); - - function run() external { - uint256 deployerPrivateKey = setupLocalhostEnv(); - 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" - ); - } - vm.startBroadcast(deployerPrivateKey); - YourContract yourContract = - new YourContract(vm.addr(deployerPrivateKey)); - console.logString( - string.concat( - "YourContract deployed at: ", vm.toString(address(yourContract)) - ) - ); - vm.stopBroadcast(); - - /** - * This function generates the file containing the contracts Abi definitions. - * These definitions are used to derive the types needed in the custom scaffold-eth hooks, for example. - * This function should be called last. - */ - exportDeployments(); - } - - function test() public {} -} diff --git a/templates/extensions/foundry/packages/foundry/script/DeployHelpers.s.sol b/templates/extensions/foundry/packages/foundry/script/DeployHelpers.s.sol deleted file mode 100644 index b7d6620..0000000 --- a/templates/extensions/foundry/packages/foundry/script/DeployHelpers.s.sol +++ /dev/null @@ -1,81 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import "forge-std/Script.sol"; -import "forge-std/Vm.sol"; - -contract ScaffoldETHDeploy is Script { - error InvalidChain(); - - struct Deployment { - string name; - address addr; - } - - string root; - string path; - Deployment[] public deployments; - - 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"); - } - } - - 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")); - - 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); - } - - function getChain() public returns (Chain memory) { - return getChain(block.chainid); - } - - 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; - } - } - revert InvalidChain(); - } -} diff --git a/templates/extensions/foundry/packages/foundry/script/ListAccount.js b/templates/extensions/foundry/packages/foundry/script/ListAccount.js deleted file mode 100644 index 20493b3..0000000 --- a/templates/extensions/foundry/packages/foundry/script/ListAccount.js +++ /dev/null @@ -1,77 +0,0 @@ -const dotenv = require("dotenv"); -dotenv.config(); -const path = require("path"); -const { ethers, Wallet } = require("ethers"); -const QRCode = require("qrcode"); -const fs = require("fs"); -const toml = require("toml"); - -const ALCHEMY_API_KEY = - process.env.ALCHEMY_API_KEY || "oKxs-03sij-U_N0iOlrSsZFr29-IqbuF"; - -async function getBalanceForEachNetwork(address) { - try { - // Read the foundry.toml file - const foundryTomlPath = path.join(__dirname, "..", "foundry.toml"); - const tomlString = fs.readFileSync(foundryTomlPath, "utf-8"); - - // Parse the tomlString to get the JS object representation - const parsedToml = toml.parse(tomlString); - - // Extract rpc_endpoints from parsedToml - const rpcEndpoints = parsedToml.rpc_endpoints; - - // Replace placeholders in the rpc_endpoints section - function replaceENVAlchemyKey(input) { - return input.replace("${ALCHEMY_API_KEY}", ALCHEMY_API_KEY); - } - - for (const networkName in rpcEndpoints) { - if (networkName === "localhost" || networkName === "default_network") - continue; - - const networkUrl = replaceENVAlchemyKey(rpcEndpoints[networkName]); - - try { - const provider = new ethers.providers.JsonRpcProvider(networkUrl); - const balance = await provider.getBalance(address); - console.log("--", networkName, "-- 📡"); - console.log(" balance:", +ethers.utils.formatEther(balance)); - console.log( - " nonce:", - +(await provider.getTransactionCount(address)) - ); - } catch (e) { - console.log("Can't connect to network", networkName); - console.log(); - } - } - } catch (error) { - console.error("Error reading foundry.toml:", error); - } -} -async function main() { - const privateKey = process.env.DEPLOYER_PRIVATE_KEY; - - if (!privateKey) { - console.log( - "🚫️ You don't have a deployer account. Run `yarn generate` first" - ); - return; - } - - // Get account from private key. - const wallet = new Wallet(privateKey); - const address = wallet.address; - console.log( - await QRCode.toString(address, { type: "terminal", small: true }) - ); - console.log("Public address:", address, "\n"); - - await getBalanceForEachNetwork(address); -} - -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); diff --git a/templates/extensions/foundry/packages/foundry/script/VerifyAll.s.sol b/templates/extensions/foundry/packages/foundry/script/VerifyAll.s.sol deleted file mode 100644 index 9990f9c..0000000 --- a/templates/extensions/foundry/packages/foundry/script/VerifyAll.s.sol +++ /dev/null @@ -1,146 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import "forge-std/Script.sol"; -import "forge-std/Vm.sol"; -import "solidity-bytes-utils/BytesLib.sol"; - -/** - * @dev Temp Vm implementation - * @notice calls the tryffi function on the Vm contract - * @notice will be deleted once the forge/std is updated - */ -struct FfiResult { - int32 exit_code; - bytes stdout; - bytes stderr; -} - -interface tempVm { - function tryFfi(string[] calldata) external returns (FfiResult memory); -} - -contract VerifyAll is Script { - uint96 currTransactionIdx; - - function run() external { - string memory root = vm.projectRoot(); - string memory path = string.concat( - root, - "/broadcast/Deploy.s.sol/", - vm.toString(block.chainid), - "/run-latest.json" - ); - string memory content = vm.readFile(path); - - while (this.nextTransaction(content)) { - _verifyIfContractDeployment(content); - currTransactionIdx++; - } - } - - function _verifyIfContractDeployment(string memory content) internal { - string memory txType = abi.decode( - vm.parseJson( - content, searchStr(currTransactionIdx, "transactionType") - ), - (string) - ); - if (keccak256(bytes(txType)) == keccak256(bytes("CREATE"))) { - _verifyContract(content); - } - } - - function _verifyContract(string memory content) internal { - string memory contractName = abi.decode( - vm.parseJson(content, searchStr(currTransactionIdx, "contractName")), - (string) - ); - address contractAddr = abi.decode( - vm.parseJson( - content, searchStr(currTransactionIdx, "contractAddress") - ), - (address) - ); - bytes memory deployedBytecode = abi.decode( - vm.parseJson( - content, searchStr(currTransactionIdx, "transaction.data") - ), - (bytes) - ); - bytes memory compiledBytecode = abi.decode( - vm.parseJson(_getCompiledBytecode(contractName), ".bytecode.object"), - (bytes) - ); - bytes memory constructorArgs = BytesLib.slice( - deployedBytecode, - compiledBytecode.length, - deployedBytecode.length - compiledBytecode.length - ); - - string[] memory inputs = new string[](9); - inputs[0] = "forge"; - inputs[1] = "verify-contract"; - inputs[2] = vm.toString(contractAddr); - inputs[3] = contractName; - inputs[4] = "--chain"; - inputs[5] = vm.toString(block.chainid); - inputs[6] = "--constructor-args"; - inputs[7] = vm.toString(constructorArgs); - inputs[8] = "--watch"; - - FfiResult memory f = tempVm(address(vm)).tryFfi(inputs); - - if (f.stderr.length != 0) { - console.logString( - string.concat( - "Submitting verification for contract: ", - vm.toString(contractAddr) - ) - ); - console.logString(string(f.stderr)); - } else { - console.logString(string(f.stdout)); - } - return; - } - - function nextTransaction(string memory content) - external - view - returns (bool) - { - try this.getTransactionFromRaw(content, currTransactionIdx) { - return true; - } catch { - return false; - } - } - - 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" - ); - compiledBytecode = vm.readFile(path); - } - - function getTransactionFromRaw( - string memory content, - uint96 idx - ) external pure { - abi.decode(vm.parseJson(content, searchStr(idx, "hash")), (bytes32)); - } - - function searchStr( - uint96 idx, - string memory searchKey - ) internal pure returns (string memory) { - return - string.concat(".transactions[", vm.toString(idx), "].", searchKey); - } -} diff --git a/templates/extensions/foundry/packages/foundry/script/generateAccount.js b/templates/extensions/foundry/packages/foundry/script/generateAccount.js deleted file mode 100644 index d6b2be3..0000000 --- a/templates/extensions/foundry/packages/foundry/script/generateAccount.js +++ /dev/null @@ -1,49 +0,0 @@ -const ethers = require("ethers"); -const { parse, stringify } = require("envfile"); -const fs = require("fs"); - -const envFilePath = "./.env"; - -/** - * Generate a new random private key and write it to the .env file - * @param existingEnvConfig - */ -const setNewEnvConfig = (existingEnvConfig = {}) => { - console.log("👛 Generating new Wallet"); - const randomWallet = ethers.Wallet.createRandom(); - - const newEnvConfig = { - ...existingEnvConfig, - DEPLOYER_PRIVATE_KEY: randomWallet.privateKey, - }; - - // Store in .env - fs.writeFileSync(envFilePath, stringify(newEnvConfig)); - console.log("📄 Private Key saved to packages/foundry/.env file"); - console.log("🪄 Generated wallet address:", randomWallet.address); -}; - -async function main() { - if (!fs.existsSync(envFilePath)) { - console.log("entered here"); - // No .env file yet. - setNewEnvConfig(); - return; - } - - // .env file exists - const existingEnvConfig = parse(fs.readFileSync(envFilePath).toString()); - if (existingEnvConfig.DEPLOYER_PRIVATE_KEY) { - console.log( - "⚠️ You already have a deployer account. Check the packages/foundry/.env file" - ); - return; - } - - setNewEnvConfig(existingEnvConfig); -} - -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); diff --git a/templates/extensions/foundry/packages/foundry/script/generateTsAbis.js b/templates/extensions/foundry/packages/foundry/script/generateTsAbis.js deleted file mode 100644 index dcea507..0000000 --- a/templates/extensions/foundry/packages/foundry/script/generateTsAbis.js +++ /dev/null @@ -1,146 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -//@ts-expect-error This script runs after `forge deploy` therefore its deterministic that it will present -// const deployments = require("../deployments.json"); -const prettier = require("prettier"); - -const generatedContractComment = ` -/** - * This file is autogenerated by Scaffold-ETH. - * You should not edit it manually or your changes might be overwritten. - */ -`; - -function getDirectories(path) { - return fs.readdirSync(path).filter(function (file) { - return fs.statSync(path + "/" + file).isDirectory(); - }); -} -function getFiles(path) { - return fs.readdirSync(path).filter(function (file) { - return fs.statSync(path + "/" + file).isFile(); - }); -} -function getArtifactOfContract(contractName) { - const current_path_to_artifacts = path.join( - __dirname, - "..", - `out/${contractName}.sol` - ); - const artifactJson = JSON.parse( - fs.readFileSync(`${current_path_to_artifacts}/${contractName}.json`) - ); - - return artifactJson; -} - -function getInheritedFromContracts(artifact) { - let inheritedFromContracts = []; - for (const astNode of artifact.ast.nodes) { - if (astNode.nodeType == "ContractDefinition") { - if (astNode.baseContracts.length > 0) { - inheritedFromContracts = astNode.baseContracts.map( - ({ baseName }) => baseName.name - ); - } - } - } - return inheritedFromContracts; -} - -function getInheritedFunctions(mainArtifact) { - const inheritedFromContracts = getInheritedFromContracts(mainArtifact); - const inheritedFunctions = {}; - for (const inheritanceContractName of inheritedFromContracts) { - const { - abi, - ast: { absolutePath }, - } = getArtifactOfContract(inheritanceContractName); - for (const abiEntry of abi) { - if (abiEntry.type == "function") { - inheritedFunctions[abiEntry.name] = absolutePath; - } - } - } - return inheritedFunctions; -} - -function main() { - const current_path_to_broadcast = path.join( - __dirname, - "..", - "broadcast/Deploy.s.sol" - ); - const current_path_to_deployments = path.join(__dirname, "..", "deployments"); - - const chains = getDirectories(current_path_to_broadcast); - const Deploymentchains = getFiles(current_path_to_deployments); - - const deployments = {}; - - Deploymentchains.forEach((chain) => { - if (!chain.endsWith(".json")) return; - chain = chain.slice(0, -5); - var deploymentObject = JSON.parse( - fs.readFileSync(`${current_path_to_deployments}/${chain}.json`) - ); - deployments[chain] = deploymentObject; - }); - - const allGeneratedContracts = {}; - - chains.forEach((chain) => { - allGeneratedContracts[chain] = {}; - const broadCastObject = JSON.parse( - fs.readFileSync(`${current_path_to_broadcast}/${chain}/run-latest.json`) - ); - const transactionsCreate = broadCastObject.transactions.filter( - (transaction) => transaction.transactionType == "CREATE" - ); - transactionsCreate.forEach((transaction) => { - const artifact = getArtifactOfContract(transaction.contractName); - allGeneratedContracts[chain][ - deployments[chain][transaction.contractAddress] || - transaction.contractName - ] = { - address: transaction.contractAddress, - abi: artifact.abi, - inheritedFunctions: getInheritedFunctions(artifact), - }; - }); - }); - - const TARGET_DIR = "../nextjs/contracts/"; - - const fileContent = Object.entries(allGeneratedContracts).reduce( - (content, [chainId, chainConfig]) => { - return `${content}${parseInt(chainId).toFixed(0)}:${JSON.stringify( - chainConfig, - null, - 2 - )},`; - }, - "" - ); - - if (!fs.existsSync(TARGET_DIR)) { - fs.mkdirSync(TARGET_DIR); - } - fs.writeFileSync( - `${TARGET_DIR}deployedContracts.ts`, - prettier.format( - `${generatedContractComment} import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract"; \n\n - const deployedContracts = {${fileContent}} as const; \n\n export default deployedContracts satisfies GenericContractsDeclaration`, - { - parser: "typescript", - } - ) - ); -} - -try { - main(); -} catch (error) { - console.error(error); - process.exitCode = 1; -} diff --git a/templates/extensions/foundry/packages/foundry/test/YourContract.t.sol b/templates/extensions/foundry/packages/foundry/test/YourContract.t.sol deleted file mode 100644 index 2bb348e..0000000 --- a/templates/extensions/foundry/packages/foundry/test/YourContract.t.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "forge-std/Test.sol"; -import "../contracts/YourContract.sol"; - -contract YourContractTest is Test { - YourContract public yourContract; - - function setUp() public { - yourContract = new YourContract(vm.addr(1)); - } - - function testMessageOnDeployment() public view { - require( - keccak256(bytes(yourContract.greeting())) - == keccak256("Building Unstoppable Apps!!!") - ); - } - - function testSetNewMessage() public { - yourContract.setGreeting("Learn Scaffold-ETH 2! :)"); - require( - keccak256(bytes(yourContract.greeting())) - == keccak256("Learn Scaffold-ETH 2! :)") - ); - } -} diff --git a/templates/extensions/foundry/packages/nextjs/app/blockexplorer/address/[address]/page.tsx.args.mjs b/templates/extensions/foundry/packages/nextjs/app/blockexplorer/address/[address]/page.tsx.args.mjs deleted file mode 100644 index c3a608a..0000000 --- a/templates/extensions/foundry/packages/nextjs/app/blockexplorer/address/[address]/page.tsx.args.mjs +++ /dev/null @@ -1,2 +0,0 @@ -export const chainName = "foundry"; -export const artifactsDirName = "out"; diff --git a/templates/extensions/foundry/packages/nextjs/scaffold.config.ts.args.mjs b/templates/extensions/foundry/packages/nextjs/scaffold.config.ts.args.mjs deleted file mode 100644 index 6893922..0000000 --- a/templates/extensions/foundry/packages/nextjs/scaffold.config.ts.args.mjs +++ /dev/null @@ -1 +0,0 @@ -export const chainName = 'foundry' \ No newline at end of file