diff --git a/README.md b/README.md index 165093d..ebfb3d3 100644 --- a/README.md +++ b/README.md @@ -14,16 +14,44 @@ The protocol is described in detail in the [Morpho Blue Whitepaper](./morpho-blu ## Getting Started > [!IMPORTANT] -> It is advised to use a dedicated address whose only purpose is to deploy all contracts associated with Blue on each EVM-compatible chain, so that addresses are common across chains. +> It is advised to use a dedicated account whose only **lifetime** purpose is to deploy all contracts associated with Blue on each EVM-compatible chain so that deployed contract addresses are common across chains. + +### Installation - `yarn` +- `cp .env.example .env` + +### Deployment + - Add the desired network key and its corresponding RPC url to `foundry.toml` - `yarn deploy:{component} {network} --broadcast --slow --sender {sender}` followed with appropriate private key management parameters +> [!NOTE] +> If the provided network's RPC url uses a variable environment (such as `ALCHEMY_KEY`), it should be defined in your `.env` + For example: `yarn deploy:morpho goerli --broadcast --slow --ledger --sender 0x7Ef4174aFdF4514F556439fa2822212278151Db6` All deployments that require an instance of Morpho expects that instance to have previously been deployed on the same network using `yarn deploy:morpho {network} --broadcast`, so that Morpho's address is saved and committed to this repository in [broadcast logs](./broadcast/DeployMorpho.sol/1/run-latest.json). +> [!NOTE] +> Broadcast run logs are to be committed to this repository for future reference. + + +### Etherscan verification + +> [!NOTE] +> Your `.env` should contain a valid `ETHERSCAN_API_KEY`. + +After each contract deployed, a verification command is automatically added to the verify script associated to the component deployed (for example: [`script/morpho/verify.sh`](script/morpho/verify.sh)). + +- Verify all contracts deployed for a component: `yarn verify:{component}` + +For example: `yarn verify:morpho` + +> [!NOTE] +> Verify scripts are **NOT** to be committed to this repository because they are expected to be run only once. + + ## License All scripts are licensed under [`GPL-2.0-or-later`](./LICENSE). diff --git a/foundry.toml b/foundry.toml index 3190b03..72bf6eb 100644 --- a/foundry.toml +++ b/foundry.toml @@ -3,7 +3,14 @@ via-ir = false libs = ["lib"] fs_permissions = [ { access = "read", path = "./broadcast/DeployMorpho.sol/"}, - { access = "read", path = "./script/config/"}, + { access = "read", path = "./script/morpho/config/"}, + { access = "read", path = "./script/oracles/config/"}, + { access = "read", path = "./script/bundlers/config/"}, + { access = "read", path = "./script/metamorpho-factory/config/"}, + { access = "write", path = "./script/morpho/verify.sh"}, + { access = "write", path = "./script/oracles/verify.sh"}, + { access = "write", path = "./script/bundlers/verify.sh"}, + { access = "write", path = "./script/metamorpho-factory/verify.sh"}, { access = "read", path = "./lib/morpho-blue/out/"}, { access = "read", path = "./lib/morpho-blue-irm/out/"}, { access = "read", path = "./lib/morpho-blue-oracles/out/"}, diff --git a/package.json b/package.json index 1161e06..7b59a94 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,14 @@ "scripts": { "prepare": "husky install && forge install", "script": "FOUNDRY_PROFILE=script forge script", - "deploy:morpho": "yarn build:blue && yarn build:irm && yarn script script/DeployMorpho.sol --sig \"run(string memory)\"", - "deploy:bundlers": "yarn build:bundlers && yarn script script/DeployBundlers.sol --sig \"run(string memory)\"", - "deploy:metamorpho-factory": "yarn build:metamorpho && yarn script script/DeployMetaMorphoFactory.sol --sig \"run(string memory)\"", - "deploy:oracles": "yarn build:oracles && yarn script script/DeployOracles.sol --sig \"run(string memory)\"", + "deploy:morpho": "yarn build:blue && yarn build:irm && yarn script script/morpho/DeployMorpho.sol --sig \"run(string memory)\"", + "deploy:bundlers": "yarn build:bundlers && yarn script script/bundlers/DeployBundlers.sol --sig \"run(string memory)\"", + "deploy:metamorpho-factory": "yarn build:metamorpho && yarn script script/metamorpho-factory/DeployMetaMorphoFactory.sol --sig \"run(string memory)\"", + "deploy:oracles": "yarn build:oracles && yarn script script/oracles/DeployOracles.sol --sig \"run(string memory)\"", + "verify:morpho": "./script/morpho/verify.sh", + "verify:bundlers": "./script/bundlers/verify.sh", + "verify:metamorpho-factory": "./script/metamorpho-factory/verify.sh", + "verify:oracles": "./script/oracles/verify.sh", "build": "yarn build:blue && yarn build:irm && yarn build:oracles && yarn build:metamorpho", "build:blue": "cd lib/morpho-blue/ && yarn build:forge", "build:irm": "cd lib/morpho-blue-irm/ && forge build", diff --git a/script/config/ConfiguredScript.sol b/script/ConfiguredScript.sol similarity index 61% rename from script/config/ConfiguredScript.sol rename to script/ConfiguredScript.sol index 9b6036a..8740cf7 100644 --- a/script/config/ConfiguredScript.sol +++ b/script/ConfiguredScript.sol @@ -1,21 +1,23 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; -import {IMorpho} from "../../lib/morpho-blue/src/interfaces/IMorpho.sol"; -import {IAdaptiveCurveIrm} from "../../lib/morpho-blue-irm/src/interfaces/IAdaptiveCurveIrm.sol"; +import {IMorpho} from "../lib/morpho-blue/src/interfaces/IMorpho.sol"; +import {IAdaptiveCurveIrm} from "../lib/morpho-blue-irm/src/interfaces/IAdaptiveCurveIrm.sol"; -import "../../lib/forge-std/src/Script.sol"; -import "../../lib/forge-std/src/console2.sol"; +import "../lib/forge-std/src/Script.sol"; +import "../lib/forge-std/src/console2.sol"; abstract contract ConfiguredScript is Script { using stdJson for string; + bool internal immutable SAVE_VERIFY = true; + string internal configPath; IMorpho internal morpho; IAdaptiveCurveIrm internal irm; - function _configDir() internal view virtual returns (string memory); + function _scriptDir() internal view virtual returns (string memory); function _init(string memory network, bool requireMorpho) internal returns (bytes memory) { vm.createSelectFork(vm.rpcUrl(network)); @@ -26,7 +28,7 @@ abstract contract ConfiguredScript is Script { } function _loadConfig(string memory network, bool requireMorpho) internal returns (bytes memory) { - configPath = string.concat("script/config/", _configDir(), "/", network, ".json"); + configPath = string.concat("script/", _scriptDir(), "/config/", network, ".json"); string memory latestRunPath = string.concat("broadcast/DeployMorpho.sol/", vm.toString(block.chainid), "/run-latest.json"); @@ -69,22 +71,32 @@ abstract contract ConfiguredScript is Script { _logDeployment(submodule, what, args, addr); } - function _logDeployment(string memory submodule, string memory what, bytes memory args, address addr) - internal - view - { + function _logDeployment(string memory submodule, string memory what, bytes memory args, address addr) internal { console2.log("Deployed %s at: %s", what, addr); - - console2.log(""); - console2.log("Verify %s using:", what); - console2.log(" > cd %s/", submodule); - console2.log( - " > forge verify-contract --chain-id %s --constructor-args %s", - vm.toString(block.chainid), - vm.toString(args), - string.concat(vm.toString(addr), " src/", what, ".sol:", what) + console2.log("Verify %s using: > yarn verify:%s", _scriptDir()); + + if (!SAVE_VERIFY) return; + + string memory verifyPath = string.concat("script/", _scriptDir(), "/verify.sh"); + vm.writeLine(verifyPath, ""); + vm.writeLine(verifyPath, string.concat("if cd lib/", submodule, "/;")); + vm.writeLine(verifyPath, "then"); + vm.writeLine( + verifyPath, + string.concat( + " forge verify-contract --chain-id ", + vm.toString(block.chainid), + " --constructor-args ", + vm.toString(args), + " ", + vm.toString(addr), + " src/", + what, + ".sol:", + what + ) ); - console2.log(" > cd ../../"); - console2.log(""); + vm.writeLine(verifyPath, " cd ../../"); + vm.writeLine(verifyPath, "fi"); } } diff --git a/script/DeployBundlers.sol b/script/bundlers/DeployBundlers.sol similarity index 90% rename from script/DeployBundlers.sol rename to script/bundlers/DeployBundlers.sol index 999f3b0..3e7f4bc 100644 --- a/script/DeployBundlers.sol +++ b/script/bundlers/DeployBundlers.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; -import "./config/ConfiguredScript.sol"; +import "../ConfiguredScript.sol"; /// @dev Warning: keys must be ordered alphabetically. struct BundlerConfig { @@ -10,7 +10,7 @@ struct BundlerConfig { } contract DeployBundlers is ConfiguredScript { - function _configDir() internal pure override returns (string memory) { + function _scriptDir() internal pure override returns (string memory) { return "bundlers"; } diff --git a/script/config/bundlers/ethereum.json b/script/bundlers/config/ethereum.json similarity index 100% rename from script/config/bundlers/ethereum.json rename to script/bundlers/config/ethereum.json diff --git a/script/config/bundlers/goerli.json b/script/bundlers/config/goerli.json similarity index 100% rename from script/config/bundlers/goerli.json rename to script/bundlers/config/goerli.json diff --git a/script/bundlers/verify.sh b/script/bundlers/verify.sh new file mode 100755 index 0000000..7492ea2 --- /dev/null +++ b/script/bundlers/verify.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +if [ -f .env ] +then + export $(grep -v '#.*' .env | xargs) +fi diff --git a/script/DeployMetaMorphoFactory.sol b/script/metamorpho-factory/DeployMetaMorphoFactory.sol similarity index 79% rename from script/DeployMetaMorphoFactory.sol rename to script/metamorpho-factory/DeployMetaMorphoFactory.sol index 4aea66e..5636bf7 100644 --- a/script/DeployMetaMorphoFactory.sol +++ b/script/metamorpho-factory/DeployMetaMorphoFactory.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; -import {IMetaMorphoFactory} from "../lib/metamorpho/src/interfaces/IMetaMorphoFactory.sol"; +import {IMetaMorphoFactory} from "../../lib/metamorpho/src/interfaces/IMetaMorphoFactory.sol"; -import "./config/ConfiguredScript.sol"; +import "../ConfiguredScript.sol"; /// @dev Warning: keys must be ordered alphabetically. struct DeployMetaMorphoFactoryConfig { @@ -13,7 +13,7 @@ struct DeployMetaMorphoFactoryConfig { contract DeployMetaMorphoFactory is ConfiguredScript { IMetaMorphoFactory internal metaMorphoFactory; - function _configDir() internal pure override returns (string memory) { + function _scriptDir() internal pure override returns (string memory) { return "metamorpho-factory"; } diff --git a/script/config/metamorpho-factory/ethereum.json b/script/metamorpho-factory/config/ethereum.json similarity index 100% rename from script/config/metamorpho-factory/ethereum.json rename to script/metamorpho-factory/config/ethereum.json diff --git a/script/config/metamorpho-factory/goerli.json b/script/metamorpho-factory/config/goerli.json similarity index 100% rename from script/config/metamorpho-factory/goerli.json rename to script/metamorpho-factory/config/goerli.json diff --git a/script/metamorpho-factory/verify.sh b/script/metamorpho-factory/verify.sh new file mode 100755 index 0000000..7492ea2 --- /dev/null +++ b/script/metamorpho-factory/verify.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +if [ -f .env ] +then + export $(grep -v '#.*' .env | xargs) +fi diff --git a/script/DeployMorpho.sol b/script/morpho/DeployMorpho.sol similarity index 85% rename from script/DeployMorpho.sol rename to script/morpho/DeployMorpho.sol index f4d0754..1937aa0 100644 --- a/script/DeployMorpho.sol +++ b/script/morpho/DeployMorpho.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; -import {IMorpho, MarketParams} from "../lib/morpho-blue/src/interfaces/IMorpho.sol"; -import {MarketParamsLib} from "../lib/morpho-blue/src/libraries/MarketParamsLib.sol"; +import {IMorpho, MarketParams} from "../../lib/morpho-blue/src/interfaces/IMorpho.sol"; +import {MarketParamsLib} from "../../lib/morpho-blue/src/libraries/MarketParamsLib.sol"; -import "./config/ConfiguredScript.sol"; +import "../ConfiguredScript.sol"; /// @dev Warning: keys must be ordered alphabetically. struct DeployMorphoConfig { @@ -16,7 +16,7 @@ struct DeployMorphoConfig { contract DeployMorpho is ConfiguredScript { using MarketParamsLib for MarketParams; - function _configDir() internal pure override returns (string memory) { + function _scriptDir() internal pure override returns (string memory) { return "morpho"; } diff --git a/script/config/morpho/ethereum.json b/script/morpho/config/ethereum.json similarity index 100% rename from script/config/morpho/ethereum.json rename to script/morpho/config/ethereum.json diff --git a/script/config/morpho/goerli.json b/script/morpho/config/goerli.json similarity index 100% rename from script/config/morpho/goerli.json rename to script/morpho/config/goerli.json diff --git a/script/morpho/verify.sh b/script/morpho/verify.sh new file mode 100755 index 0000000..7492ea2 --- /dev/null +++ b/script/morpho/verify.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +if [ -f .env ] +then + export $(grep -v '#.*' .env | xargs) +fi diff --git a/script/DeployOracles.sol b/script/oracles/DeployOracles.sol similarity index 90% rename from script/DeployOracles.sol rename to script/oracles/DeployOracles.sol index 2e5bd03..022020e 100644 --- a/script/DeployOracles.sol +++ b/script/oracles/DeployOracles.sol @@ -1,11 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; -import {IERC20} from "../lib/forge-std/src/interfaces/IERC20.sol"; +import {IERC20} from "../../lib/forge-std/src/interfaces/IERC20.sol"; +import {IChainlinkOracle} from "../../lib/morpho-blue-oracles/src/interfaces/IChainlinkOracle.sol"; -import {IChainlinkOracle} from "../lib/morpho-blue-oracles/src/interfaces/IChainlinkOracle.sol"; - -import "./config/ConfiguredScript.sol"; +import "../ConfiguredScript.sol"; /// @dev Warning: keys must be ordered alphabetically. struct OracleConfig { @@ -22,7 +21,7 @@ struct OracleConfig { } contract DeployOracle is ConfiguredScript { - function _configDir() internal pure override returns (string memory) { + function _scriptDir() internal pure override returns (string memory) { return "oracles"; } diff --git a/script/config/oracles/ethereum.json b/script/oracles/config/ethereum.json similarity index 100% rename from script/config/oracles/ethereum.json rename to script/oracles/config/ethereum.json diff --git a/script/config/oracles/goerli.json b/script/oracles/config/goerli.json similarity index 100% rename from script/config/oracles/goerli.json rename to script/oracles/config/goerli.json diff --git a/script/oracles/verify.sh b/script/oracles/verify.sh new file mode 100755 index 0000000..7492ea2 --- /dev/null +++ b/script/oracles/verify.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +if [ -f .env ] +then + export $(grep -v '#.*' .env | xargs) +fi diff --git a/test/DeployMorphoEthereumTest.sol b/test/morpho/DeployMorphoEthereumTest.sol similarity index 89% rename from test/DeployMorphoEthereumTest.sol rename to test/morpho/DeployMorphoEthereumTest.sol index f41de31..cf5a312 100644 --- a/test/DeployMorphoEthereumTest.sol +++ b/test/morpho/DeployMorphoEthereumTest.sol @@ -1,13 +1,17 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.0; -import "../script/DeployMorpho.sol"; +import "../../script/morpho/DeployMorpho.sol"; -import "../lib/forge-std/src/Test.sol"; +import "../../lib/forge-std/src/Test.sol"; contract DeployMorphoEthereumTest is DeployMorpho, Test { DeployMorphoConfig internal config; + constructor() { + SAVE_VERIFY = false; + } + function setUp() public { config = run("ethereum"); }