From e400624352a05c56a5f2a35207ee1dc419cb6f1f Mon Sep 17 00:00:00 2001 From: andreivladbrg Date: Thu, 3 Oct 2024 18:57:48 +0300 Subject: [PATCH 1/5] feat: add table creator script contract build: add more chains in foundry toml build: add etherscan config --- .gitignore | 1 + foundry.toml | 30 +++++- script/Base.s.sol | 35 +++++- script/DeployDeterministicFlow.s.sol | 18 +++- script/DeployFlow.s.sol | 22 +++- script/TableCreator.s.sol | 155 +++++++++++++++++++++++++++ 6 files changed, 251 insertions(+), 10 deletions(-) create mode 100644 script/TableCreator.s.sol diff --git a/.gitignore b/.gitignore index dfe17c87..6edfdcf8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ artifacts broadcast cache coverage +deployments docs node_modules out diff --git a/foundry.toml b/foundry.toml index fa390cbd..6d37f134 100644 --- a/foundry.toml +++ b/foundry.toml @@ -5,7 +5,8 @@ fs_permissions = [ { access = "read", path = "./out-optimized" }, { access = "read", path = "package.json" }, - { access = "read-write", path = "./benchmark/results"} + { access = "read-write", path = "./benchmark/results"}, + { access = "read-write", path = "./deployments"} ] gas_limit = 9223372036854775807 gas_reports = ["SablierFlow"] @@ -62,6 +63,24 @@ out = "docs" repository = "https://github.com/sablier-labs/flow" +[etherscan] + arbitrum = { key = "${ARBISCAN_API_KEY}" } + arbitrum_sepolia = { key = "${ARBISCAN_API_KEY}" } + avalanche = { key = "${SNOWTRACE_API_KEY}" } + base = { key = "${BASESCAN_API_KEY}" } + base_sepolia = { key = "${BASESCAN_API_KEY}" } + bnb = { key = "${BSCSCAN_API_KEY}" } + gnosis = { key = "${GNOSISSCAN_API_KEY}" } + linea = { key = "${LINEASCAN_API_KEY}" } + linea_sepolia = { key = "${LINEASCAN_API_KEY}" } + mainnet = { key = "${ETHERSCAN_API_KEY}" } + optimism = { key = "${OPTIMISTIC_API_KEY}" } + optimism_sepolia = { key = "${OPTIMISTIC_API_KEY}" } + polygon = { key = "${POLYGONSCAN_API_KEY}" } + scroll = { key = "${SCROLLSCAN_API_KEY}" } + sepolia = { key = "${SEPOLIASCAN_KEY}" } + taiko_mainnet = { key = "${TAIKO_MAINNET_API_KEY}" } + [fmt] bracket_spacing = true int_types = "long" @@ -78,12 +97,21 @@ avalanche = "${AVALANCHE_RPC_URL}" base = "https://mainnet.base.org" base_sepolia = "https://sepolia.base.org" + berachain_artio = "https://bartio.rpc.berachain.com/" bnb = "https://bsc-dataseed.binance.org" gnosis = "https://rpc.gnosischain.com" + linea = "https://rpc.linea.build" + linea_sepolia = "https://rpc.sepolia.linea.build" localhost = "http://localhost:8545" mainnet = "${MAINNET_RPC_URL}" + mode = "https://mainnet.mode.network/" + mode_sepolia = "https://sepolia.mode.network/" optimism = "${OPTIMISM_RPC_URL}" optimism_sepolia = "https://sepolia.optimism.io" polygon = "${POLYGON_RPC_URL}" scroll = "https://rpc.scroll.io/" + sei = "https://evm-rpc.sei-apis.com" + sei_testnet = "https://evm-rpc.arctic-1.seinetwork.io" sepolia = "${SEPOLIA_RPC_URL}" + taiko_hekla = "https://rpc.hekla.taiko.xyz" + taiko_mainnet = "https://rpc.mainnet.taiko.xyz" \ No newline at end of file diff --git a/script/Base.s.sol b/script/Base.s.sol index 3b551b38..ef83a37c 100644 --- a/script/Base.s.sol +++ b/script/Base.s.sol @@ -12,12 +12,18 @@ abstract contract BaseScript is Script { using Strings for uint256; using stdJson for string; + /// @dev The address of the Sablier deployer. + address internal constant SABLIER_DEPLOYER = 0xb1bEF51ebCA01EB12001a639bDBbFF6eEcA12B9F; + /// @dev Included to enable compilation of the script without a $MNEMONIC environment variable. string internal constant TEST_MNEMONIC = "test test test test test test test test test test test junk"; /// @dev Needed for the deterministic deployments. bytes32 internal constant ZERO_SALT = bytes32(0); + /// @dev Admin address mapped by the chain Id. + mapping(uint256 chainId => address admin) internal adminMap; + /// @dev The address of the transaction broadcaster. address internal broadcaster; @@ -39,6 +45,11 @@ abstract contract BaseScript is Script { mnemonic = vm.envOr({ name: "MNEMONIC", defaultValue: TEST_MNEMONIC }); (broadcaster,) = deriveRememberKey({ mnemonic: mnemonic, index: 0 }); } + + // If there is no admin set for a specific chain, use the Sablier deployer. + if (adminMap[block.chainid] == address(0)) { + adminMap[block.chainid] = SABLIER_DEPLOYER; + } } modifier broadcast() { @@ -53,12 +64,30 @@ abstract contract BaseScript is Script { /// Notes: /// - The salt format is "ChainID , Version ". /// - The version is obtained from `package.json`. - function constructCreate2Salt() public view returns (bytes32) { + function constructCreate2Salt() internal view returns (bytes32) { string memory chainId = block.chainid.toString(); - string memory json = vm.readFile("package.json"); - string memory version = json.readString(".version"); + string memory version = getVersion(); string memory create2Salt = string.concat("ChainID ", chainId, ", Version ", version); console2.log("The CREATE2 salt is %s", create2Salt); return bytes32(abi.encodePacked(create2Salt)); } + + function getVersion() internal view returns (string memory) { + string memory json = vm.readFile("package.json"); + return json.readString(".version"); + } + + /// @dev Populates the admin map. + function populateAdminMap() internal { + adminMap[42_161] = 0xF34E41a6f6Ce5A45559B1D3Ee92E141a3De96376; // Arbitrum + adminMap[43_114] = 0x4735517616373c5137dE8bcCDc887637B8ac85Ce; // Avalanche + adminMap[8453] = 0x83A6fA8c04420B3F9C7A4CF1c040b63Fbbc89B66; // Base + adminMap[56] = 0x6666cA940D2f4B65883b454b7Bc7EEB039f64fa3; // BNB + adminMap[100] = 0x72ACB57fa6a8fa768bE44Db453B1CDBa8B12A399; // Gnosis + adminMap[1] = 0x79Fb3e81aAc012c08501f41296CCC145a1E15844; // Mainnet + adminMap[59_144] = 0x72dCfa0483d5Ef91562817C6f20E8Ce07A81319D; // Linea + adminMap[10] = 0x43c76FE8Aec91F63EbEfb4f5d2a4ba88ef880350; // Optimism + adminMap[137] = 0x40A518C5B9c1d3D6d62Ba789501CE4D526C9d9C6; // Polygon + adminMap[534_352] = 0x0F7Ad835235Ede685180A5c611111610813457a9; // Scroll + } } diff --git a/script/DeployDeterministicFlow.s.sol b/script/DeployDeterministicFlow.s.sol index 70d70be7..1b153947 100644 --- a/script/DeployDeterministicFlow.s.sol +++ b/script/DeployDeterministicFlow.s.sol @@ -3,14 +3,26 @@ pragma solidity >=0.8.22; import { FlowNFTDescriptor } from "src/FlowNFTDescriptor.sol"; import { SablierFlow } from "src/SablierFlow.sol"; -import { BaseScript } from "./Base.s.sol"; +import { FlowNFTDescriptor } from "src/FlowNFTDescriptor.sol"; + +import { TableCreator } from "./TableCreator.s.sol"; /// @notice Deploys {SablierFlow} at a deterministic address across chains. /// @dev Reverts if the contract has already been deployed. -contract DeployDeterministicFlow is BaseScript { - function run(address initialAdmin) public broadcast returns (SablierFlow flow, FlowNFTDescriptor nftDescriptor) { +contract DeployDeterministicFlow is TableCreator("deterministic") { + function run() public returns (SablierFlow flow, FlowNFTDescriptor nftDescriptor) { + (flow, nftDescriptor) = _run(adminMap[block.chainid]); + } + + function run(address initialAdmin) public returns (SablierFlow flow, FlowNFTDescriptor nftDescriptor) { + (flow, nftDescriptor) = _run(initialAdmin); + } + + function _run(address initialAdmin) public broadcast returns (SablierFlow flow, FlowNFTDescriptor nftDescriptor) { bytes32 salt = constructCreate2Salt(); nftDescriptor = new FlowNFTDescriptor{ salt: salt }(); flow = new SablierFlow{ salt: salt }(initialAdmin, nftDescriptor); + + appendToFileDeployedAddresses(address(flow), address(nftDescriptor)); } } diff --git a/script/DeployFlow.s.sol b/script/DeployFlow.s.sol index 53594ca5..7e02ea9b 100644 --- a/script/DeployFlow.s.sol +++ b/script/DeployFlow.s.sol @@ -3,12 +3,28 @@ pragma solidity >=0.8.22; import { FlowNFTDescriptor } from "src/FlowNFTDescriptor.sol"; import { SablierFlow } from "src/SablierFlow.sol"; -import { BaseScript } from "./Base.s.sol"; +import { FlowNFTDescriptor } from "src/FlowNFTDescriptor.sol"; + +import { TableCreator } from "./TableCreator.s.sol"; /// @notice Deploys {SablierFlow}. -contract DeployFlow is BaseScript { - function run(address initialAdmin) public broadcast returns (SablierFlow flow, FlowNFTDescriptor nftDescriptor) { +contract DeployFlow is TableCreator("not-deterministic") { + function run() public returns (SablierFlow flow, FlowNFTDescriptor nftDescriptor) { + (flow, nftDescriptor) = _run(adminMap[block.chainid]); + } + + function run(address initialAdmin) public returns (SablierFlow flow, FlowNFTDescriptor nftDescriptor) { + (flow, nftDescriptor) = _run(initialAdmin); + } + + function _run(address initialAdmin) + internal + broadcast + returns (SablierFlow flow, FlowNFTDescriptor nftDescriptor) + { nftDescriptor = new FlowNFTDescriptor(); flow = new SablierFlow(initialAdmin, nftDescriptor); + + appendToFileDeployedAddresses(address(flow), address(nftDescriptor)); } } diff --git a/script/TableCreator.s.sol b/script/TableCreator.s.sol new file mode 100644 index 00000000..a82a8ce5 --- /dev/null +++ b/script/TableCreator.s.sol @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >=0.8.22; + +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; +import { stdJson } from "forge-std/src/StdJson.sol"; + +import { BaseScript } from "./Base.s.sol"; + +contract TableCreator is BaseScript { + using stdJson for string; + using Strings for address; + using Strings for string; + using Strings for uint256; + + /// @dev The path to the file where the deployment addresses are stored. + string internal deploymentFile; + + /// @dev Explorer URL mapped by the chain Id. + mapping(uint256 chainId => string explorerUrl) internal explorerMap; + + /// @dev Chain names mapped by the chain Id. + mapping(uint256 chainId => string name) internal nameMap; + + constructor(string memory deterministicOrNot) { + // Populate the chain name map. + populateChainNameMap(); + + // Populate the explorer URLs. + populateExplorerMap(); + + // If there is no admin set for a specific chain, use the Sablier deployer. + if (adminMap[block.chainid] == address(0)) { + adminMap[block.chainid] = SABLIER_DEPLOYER; + } + + // If there is no explorer URL set for a specific chain, use a placeholder. + if (explorerMap[block.chainid].equal("")) { + explorerMap[block.chainid] = ""; + } + + // If there is no chain name set for a specific chain, use the chain ID. + if (nameMap[block.chainid].equal("")) { + nameMap[block.chainid] = block.chainid.toString(); + } + + // Set the deployment file path. + deploymentFile = string.concat("deployments/", deterministicOrNot, ".md"); + + // Append the chain name to the deployment file. + _appendToFile(string.concat("## ", nameMap[block.chainid], "\n\n")); + } + + /// @dev Function to append the deployed addresses to the deployment file. + function appendToFileDeployedAddresses(address flow, address flowNFTDescriptor) internal { + string memory firstTwoLines = "| Contract | Address | Deployment |\n | :------- | :------ | :----------|"; + _appendToFile(firstTwoLines); + + string memory flowLine = _getContractLine({ contractName: "SablierFlow", contractAddress: flow.toHexString() }); + _appendToFile(flowLine); + + string memory flowNFTDescriptorLine = + _getContractLine({ contractName: "FlowNFTDescriptor", contractAddress: flowNFTDescriptor.toHexString() }); + _appendToFile(flowNFTDescriptorLine); + } + + /// @dev Populates the chain name map. + function populateChainNameMap() internal { + nameMap[42_161] = "Arbitrum"; + nameMap[43_114] = "Avalanche"; + nameMap[8453] = "Base"; + nameMap[84_532] = "Base Sepolia"; + nameMap[80_084] = "Berachain Bartio"; + nameMap[81_457] = "Blast"; + nameMap[168_587_773] = "Blast Sepolia"; + nameMap[56] = "BNB Smart Chain"; + nameMap[100] = "Gnosis"; + nameMap[1890] = "Lightlink"; + nameMap[59_144] = "Linea"; + nameMap[59_141] = "Linea Sepolia"; + nameMap[1] = "Mainnet"; + nameMap[333_000_333] = "Meld"; + nameMap[34_443] = "Mode"; + nameMap[919] = "Mode Sepolia"; + nameMap[2810] = "Morph Holesky"; + nameMap[10] = "Optimism"; + nameMap[11_155_420] = "Optimism Sepolia"; + nameMap[137] = "Polygon"; + nameMap[534_352] = "Scroll"; + nameMap[11_155_111] = "Sepolia"; + nameMap[53_302] = "Superseed Sepolia"; + nameMap[167_009] = "Taiko Hekla"; + nameMap[167_000] = "Taiko Mainnet"; + } + + /// @dev Populates the explorer map. + function populateExplorerMap() internal { + explorerMap[42_161] = "https://arbiscan.io/address/"; + explorerMap[43_114] = "https://snowtrace.io/address/"; + explorerMap[8453] = "https://basescan.org/address/"; + explorerMap[84_532] = "https://sepolia.basescan.org/address/"; + explorerMap[80_084] = "https://bartio.beratrail.io/address/"; + explorerMap[81_457] = "https://blastscan.io/address/"; + explorerMap[168_587_773] = "https://sepolia.blastscan.io/address/"; + explorerMap[56] = "https://bscscan.com/address/"; + explorerMap[1] = "https://etherscan.io/address/"; + explorerMap[100] = "https://gnosisscan.io/address/"; + explorerMap[59_144] = "https://lineascan.build/address/"; + explorerMap[59_141] = "https://sepolia.lineascan.build/address/"; + explorerMap[1890] = "https://phoenix.lightlink.io/address/"; + explorerMap[34_443] = "https://explorer.mode.network/address/"; + explorerMap[919] = "https://sepolia.explorer.mode.network/address/"; + explorerMap[2810] = "https://explorer-holesky.morphl2.io/address/"; + explorerMap[333_000_333] = "https://meldscan.io/address/"; + explorerMap[10] = "https://optimistic.etherscan.io/address/"; + explorerMap[11_155_420] = "https://sepolia-optimistic.etherscan.io/address/"; + explorerMap[137] = "https://polygonscan.com/address/"; + explorerMap[534_352] = "https://scrollscan.com/address/"; + explorerMap[11_155_111] = "https://sepolia.etherscan.io/address/"; + explorerMap[53_302] = "https://sepolia-explorer.superseed.xyz/address/"; + explorerMap[167_009] = "https://explorer.hekla.taiko.xyz/address/"; + explorerMap[167_000] = "https://taikoscan.io/address/"; + } + + /// @dev Append a line to the deployment file path. + function _appendToFile(string memory line) private { + vm.writeLine({ path: deploymentFile, data: line }); + } + + /// @dev Returns a string for a single contract line formatted according to the docs. + function _getContractLine( + string memory contractName, + string memory contractAddress + ) + private + view + returns (string memory) + { + string memory version = getVersion(); + version = string.concat("v", version); + + return string.concat( + "| ", + contractName, + " | [", + contractAddress, + "](", + explorerMap[block.chainid], + contractAddress, + ") | [", + version, + "](https://github.com/sablier-labs/v2-deployments/tree/main/", + ") |" + ); + } +} From d39ac7590610bb96e835faf6cf17fee43fa455ac Mon Sep 17 00:00:00 2001 From: andreivladbrg Date: Tue, 8 Oct 2024 14:46:22 +0300 Subject: [PATCH 2/5] shub feedback --- script/Base.s.sol | 27 +----- script/DeployDeterministicFlow.s.sol | 7 +- script/DeployFlow.s.sol | 7 +- ...leCreator.s.sol => DeploymentLogger.s.sol} | 97 ++++++++++++------- 4 files changed, 69 insertions(+), 69 deletions(-) rename script/{TableCreator.s.sol => DeploymentLogger.s.sol} (62%) diff --git a/script/Base.s.sol b/script/Base.s.sol index ef83a37c..ea1becf8 100644 --- a/script/Base.s.sol +++ b/script/Base.s.sol @@ -12,18 +12,12 @@ abstract contract BaseScript is Script { using Strings for uint256; using stdJson for string; - /// @dev The address of the Sablier deployer. - address internal constant SABLIER_DEPLOYER = 0xb1bEF51ebCA01EB12001a639bDBbFF6eEcA12B9F; - /// @dev Included to enable compilation of the script without a $MNEMONIC environment variable. string internal constant TEST_MNEMONIC = "test test test test test test test test test test test junk"; /// @dev Needed for the deterministic deployments. bytes32 internal constant ZERO_SALT = bytes32(0); - /// @dev Admin address mapped by the chain Id. - mapping(uint256 chainId => address admin) internal adminMap; - /// @dev The address of the transaction broadcaster. address internal broadcaster; @@ -45,11 +39,6 @@ abstract contract BaseScript is Script { mnemonic = vm.envOr({ name: "MNEMONIC", defaultValue: TEST_MNEMONIC }); (broadcaster,) = deriveRememberKey({ mnemonic: mnemonic, index: 0 }); } - - // If there is no admin set for a specific chain, use the Sablier deployer. - if (adminMap[block.chainid] == address(0)) { - adminMap[block.chainid] = SABLIER_DEPLOYER; - } } modifier broadcast() { @@ -63,7 +52,6 @@ abstract contract BaseScript is Script { /// /// Notes: /// - The salt format is "ChainID , Version ". - /// - The version is obtained from `package.json`. function constructCreate2Salt() internal view returns (bytes32) { string memory chainId = block.chainid.toString(); string memory version = getVersion(); @@ -72,22 +60,9 @@ abstract contract BaseScript is Script { return bytes32(abi.encodePacked(create2Salt)); } + /// @dev The version is obtained from `package.json`. function getVersion() internal view returns (string memory) { string memory json = vm.readFile("package.json"); return json.readString(".version"); } - - /// @dev Populates the admin map. - function populateAdminMap() internal { - adminMap[42_161] = 0xF34E41a6f6Ce5A45559B1D3Ee92E141a3De96376; // Arbitrum - adminMap[43_114] = 0x4735517616373c5137dE8bcCDc887637B8ac85Ce; // Avalanche - adminMap[8453] = 0x83A6fA8c04420B3F9C7A4CF1c040b63Fbbc89B66; // Base - adminMap[56] = 0x6666cA940D2f4B65883b454b7Bc7EEB039f64fa3; // BNB - adminMap[100] = 0x72ACB57fa6a8fa768bE44Db453B1CDBa8B12A399; // Gnosis - adminMap[1] = 0x79Fb3e81aAc012c08501f41296CCC145a1E15844; // Mainnet - adminMap[59_144] = 0x72dCfa0483d5Ef91562817C6f20E8Ce07A81319D; // Linea - adminMap[10] = 0x43c76FE8Aec91F63EbEfb4f5d2a4ba88ef880350; // Optimism - adminMap[137] = 0x40A518C5B9c1d3D6d62Ba789501CE4D526C9d9C6; // Polygon - adminMap[534_352] = 0x0F7Ad835235Ede685180A5c611111610813457a9; // Scroll - } } diff --git a/script/DeployDeterministicFlow.s.sol b/script/DeployDeterministicFlow.s.sol index 1b153947..f05918e8 100644 --- a/script/DeployDeterministicFlow.s.sol +++ b/script/DeployDeterministicFlow.s.sol @@ -2,14 +2,13 @@ pragma solidity >=0.8.22; import { FlowNFTDescriptor } from "src/FlowNFTDescriptor.sol"; -import { SablierFlow } from "src/SablierFlow.sol"; import { FlowNFTDescriptor } from "src/FlowNFTDescriptor.sol"; - -import { TableCreator } from "./TableCreator.s.sol"; +import { SablierFlow } from "src/SablierFlow.sol"; +import { DeploymentLogger } from "./DeploymentLogger.s.sol"; /// @notice Deploys {SablierFlow} at a deterministic address across chains. /// @dev Reverts if the contract has already been deployed. -contract DeployDeterministicFlow is TableCreator("deterministic") { +contract DeployDeterministicFlow is DeploymentLogger("deterministic") { function run() public returns (SablierFlow flow, FlowNFTDescriptor nftDescriptor) { (flow, nftDescriptor) = _run(adminMap[block.chainid]); } diff --git a/script/DeployFlow.s.sol b/script/DeployFlow.s.sol index 7e02ea9b..8cd8093b 100644 --- a/script/DeployFlow.s.sol +++ b/script/DeployFlow.s.sol @@ -2,13 +2,12 @@ pragma solidity >=0.8.22; import { FlowNFTDescriptor } from "src/FlowNFTDescriptor.sol"; -import { SablierFlow } from "src/SablierFlow.sol"; import { FlowNFTDescriptor } from "src/FlowNFTDescriptor.sol"; - -import { TableCreator } from "./TableCreator.s.sol"; +import { SablierFlow } from "src/SablierFlow.sol"; +import { DeploymentLogger } from "./DeploymentLogger.s.sol"; /// @notice Deploys {SablierFlow}. -contract DeployFlow is TableCreator("not-deterministic") { +contract DeployFlow is DeploymentLogger("not-deterministic") { function run() public returns (SablierFlow flow, FlowNFTDescriptor nftDescriptor) { (flow, nftDescriptor) = _run(adminMap[block.chainid]); } diff --git a/script/TableCreator.s.sol b/script/DeploymentLogger.s.sol similarity index 62% rename from script/TableCreator.s.sol rename to script/DeploymentLogger.s.sol index a82a8ce5..14b3fed1 100644 --- a/script/TableCreator.s.sol +++ b/script/DeploymentLogger.s.sol @@ -6,48 +6,59 @@ import { stdJson } from "forge-std/src/StdJson.sol"; import { BaseScript } from "./Base.s.sol"; -contract TableCreator is BaseScript { +/// @dev This contract appends to the `deployments` directory, which is assumed to be already created before running the +/// deployment script. +contract DeploymentLogger is BaseScript { using stdJson for string; using Strings for address; using Strings for string; using Strings for uint256; + /// @dev The address of the default Sablier admin. + address internal constant DEFAULT_SABLIER_ADMIN = 0xb1bEF51ebCA01EB12001a639bDBbFF6eEcA12B9F; + + /// @dev Admin address mapped by the chain Id. + mapping(uint256 chainId => address admin) internal adminMap; + + /// @dev Chain names mapped by the chain Id. + mapping(uint256 chainId => string name) internal chainNameMap; + /// @dev The path to the file where the deployment addresses are stored. string internal deploymentFile; /// @dev Explorer URL mapped by the chain Id. mapping(uint256 chainId => string explorerUrl) internal explorerMap; - /// @dev Chain names mapped by the chain Id. - mapping(uint256 chainId => string name) internal nameMap; - constructor(string memory deterministicOrNot) { + // Populate the admin map. + populateAdminMap(); + // Populate the chain name map. populateChainNameMap(); // Populate the explorer URLs. populateExplorerMap(); - // If there is no admin set for a specific chain, use the Sablier deployer. + // If there is no admin set for a specific chain, use the default Sablier admin. if (adminMap[block.chainid] == address(0)) { - adminMap[block.chainid] = SABLIER_DEPLOYER; + adminMap[block.chainid] = DEFAULT_SABLIER_ADMIN; } // If there is no explorer URL set for a specific chain, use a placeholder. if (explorerMap[block.chainid].equal("")) { - explorerMap[block.chainid] = ""; + explorerMap[block.chainid] = "N/A"; } // If there is no chain name set for a specific chain, use the chain ID. - if (nameMap[block.chainid].equal("")) { - nameMap[block.chainid] = block.chainid.toString(); + if (chainNameMap[block.chainid].equal("")) { + chainNameMap[block.chainid] = string.concat("Chain ID: ", block.chainid.toString()); } // Set the deployment file path. deploymentFile = string.concat("deployments/", deterministicOrNot, ".md"); // Append the chain name to the deployment file. - _appendToFile(string.concat("## ", nameMap[block.chainid], "\n\n")); + _appendToFile(string.concat("## ", chainNameMap[block.chainid], "\n")); } /// @dev Function to append the deployed addresses to the deployment file. @@ -61,35 +72,51 @@ contract TableCreator is BaseScript { string memory flowNFTDescriptorLine = _getContractLine({ contractName: "FlowNFTDescriptor", contractAddress: flowNFTDescriptor.toHexString() }); _appendToFile(flowNFTDescriptorLine); + + _appendToFile("\n"); + } + + /// @dev Populates the admin map. + function populateAdminMap() internal { + adminMap[42_161] = 0xF34E41a6f6Ce5A45559B1D3Ee92E141a3De96376; // Arbitrum + adminMap[43_114] = 0x4735517616373c5137dE8bcCDc887637B8ac85Ce; // Avalanche + adminMap[8453] = 0x83A6fA8c04420B3F9C7A4CF1c040b63Fbbc89B66; // Base + adminMap[56] = 0x6666cA940D2f4B65883b454b7Bc7EEB039f64fa3; // BNB + adminMap[100] = 0x72ACB57fa6a8fa768bE44Db453B1CDBa8B12A399; // Gnosis + adminMap[1] = 0x79Fb3e81aAc012c08501f41296CCC145a1E15844; // Mainnet + adminMap[59_144] = 0x72dCfa0483d5Ef91562817C6f20E8Ce07A81319D; // Linea + adminMap[10] = 0x43c76FE8Aec91F63EbEfb4f5d2a4ba88ef880350; // Optimism + adminMap[137] = 0x40A518C5B9c1d3D6d62Ba789501CE4D526C9d9C6; // Polygon + adminMap[534_352] = 0x0F7Ad835235Ede685180A5c611111610813457a9; // Scroll } /// @dev Populates the chain name map. function populateChainNameMap() internal { - nameMap[42_161] = "Arbitrum"; - nameMap[43_114] = "Avalanche"; - nameMap[8453] = "Base"; - nameMap[84_532] = "Base Sepolia"; - nameMap[80_084] = "Berachain Bartio"; - nameMap[81_457] = "Blast"; - nameMap[168_587_773] = "Blast Sepolia"; - nameMap[56] = "BNB Smart Chain"; - nameMap[100] = "Gnosis"; - nameMap[1890] = "Lightlink"; - nameMap[59_144] = "Linea"; - nameMap[59_141] = "Linea Sepolia"; - nameMap[1] = "Mainnet"; - nameMap[333_000_333] = "Meld"; - nameMap[34_443] = "Mode"; - nameMap[919] = "Mode Sepolia"; - nameMap[2810] = "Morph Holesky"; - nameMap[10] = "Optimism"; - nameMap[11_155_420] = "Optimism Sepolia"; - nameMap[137] = "Polygon"; - nameMap[534_352] = "Scroll"; - nameMap[11_155_111] = "Sepolia"; - nameMap[53_302] = "Superseed Sepolia"; - nameMap[167_009] = "Taiko Hekla"; - nameMap[167_000] = "Taiko Mainnet"; + chainNameMap[42_161] = "Arbitrum"; + chainNameMap[43_114] = "Avalanche"; + chainNameMap[8453] = "Base"; + chainNameMap[84_532] = "Base Sepolia"; + chainNameMap[80_084] = "Berachain Bartio"; + chainNameMap[81_457] = "Blast"; + chainNameMap[168_587_773] = "Blast Sepolia"; + chainNameMap[56] = "BNB Smart Chain"; + chainNameMap[100] = "Gnosis"; + chainNameMap[1890] = "Lightlink"; + chainNameMap[59_144] = "Linea"; + chainNameMap[59_141] = "Linea Sepolia"; + chainNameMap[1] = "Mainnet"; + chainNameMap[333_000_333] = "Meld"; + chainNameMap[34_443] = "Mode"; + chainNameMap[919] = "Mode Sepolia"; + chainNameMap[2810] = "Morph Holesky"; + chainNameMap[10] = "Optimism"; + chainNameMap[11_155_420] = "Optimism Sepolia"; + chainNameMap[137] = "Polygon"; + chainNameMap[534_352] = "Scroll"; + chainNameMap[11_155_111] = "Sepolia"; + chainNameMap[53_302] = "Superseed Sepolia"; + chainNameMap[167_009] = "Taiko Hekla"; + chainNameMap[167_000] = "Taiko Mainnet"; } /// @dev Populates the explorer map. From a18a624ecbdfd576ebedfa5968e245fc2a538b3a Mon Sep 17 00:00:00 2001 From: andreivladbrg Date: Wed, 9 Oct 2024 16:34:20 +0300 Subject: [PATCH 3/5] refactor: append to the script dir instead --- .gitignore | 1 + foundry.toml | 20 +------------------- script/DeploymentLogger.s.sol | 5 ++--- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 6edfdcf8..aabd66f6 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ out-svg lcov.info package-lock.json pnpm-lock.yaml +script/*.md yarn.lock diff --git a/foundry.toml b/foundry.toml index 6d37f134..6ff145a8 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,7 +6,7 @@ { access = "read", path = "./out-optimized" }, { access = "read", path = "package.json" }, { access = "read-write", path = "./benchmark/results"}, - { access = "read-write", path = "./deployments"} + { access = "read-write", path = "./script"} ] gas_limit = 9223372036854775807 gas_reports = ["SablierFlow"] @@ -63,24 +63,6 @@ out = "docs" repository = "https://github.com/sablier-labs/flow" -[etherscan] - arbitrum = { key = "${ARBISCAN_API_KEY}" } - arbitrum_sepolia = { key = "${ARBISCAN_API_KEY}" } - avalanche = { key = "${SNOWTRACE_API_KEY}" } - base = { key = "${BASESCAN_API_KEY}" } - base_sepolia = { key = "${BASESCAN_API_KEY}" } - bnb = { key = "${BSCSCAN_API_KEY}" } - gnosis = { key = "${GNOSISSCAN_API_KEY}" } - linea = { key = "${LINEASCAN_API_KEY}" } - linea_sepolia = { key = "${LINEASCAN_API_KEY}" } - mainnet = { key = "${ETHERSCAN_API_KEY}" } - optimism = { key = "${OPTIMISTIC_API_KEY}" } - optimism_sepolia = { key = "${OPTIMISTIC_API_KEY}" } - polygon = { key = "${POLYGONSCAN_API_KEY}" } - scroll = { key = "${SCROLLSCAN_API_KEY}" } - sepolia = { key = "${SEPOLIASCAN_KEY}" } - taiko_mainnet = { key = "${TAIKO_MAINNET_API_KEY}" } - [fmt] bracket_spacing = true int_types = "long" diff --git a/script/DeploymentLogger.s.sol b/script/DeploymentLogger.s.sol index 14b3fed1..597ecebb 100644 --- a/script/DeploymentLogger.s.sol +++ b/script/DeploymentLogger.s.sol @@ -6,8 +6,7 @@ import { stdJson } from "forge-std/src/StdJson.sol"; import { BaseScript } from "./Base.s.sol"; -/// @dev This contract appends to the `deployments` directory, which is assumed to be already created before running the -/// deployment script. +/// @dev This contract appends to the `script` directory a markdown file with the deployed addresses. contract DeploymentLogger is BaseScript { using stdJson for string; using Strings for address; @@ -55,7 +54,7 @@ contract DeploymentLogger is BaseScript { } // Set the deployment file path. - deploymentFile = string.concat("deployments/", deterministicOrNot, ".md"); + deploymentFile = string.concat("script/", deterministicOrNot, ".md"); // Append the chain name to the deployment file. _appendToFile(string.concat("## ", chainNameMap[block.chainid], "\n")); From a903b13d06ce7ceb4b03000a92d147617559e0eb Mon Sep 17 00:00:00 2001 From: andreivladbrg Date: Wed, 9 Oct 2024 16:43:11 +0300 Subject: [PATCH 4/5] docs: polish populateAdminMap natspec --- script/DeploymentLogger.s.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/script/DeploymentLogger.s.sol b/script/DeploymentLogger.s.sol index 597ecebb..e0a7c4b8 100644 --- a/script/DeploymentLogger.s.sol +++ b/script/DeploymentLogger.s.sol @@ -75,7 +75,8 @@ contract DeploymentLogger is BaseScript { _appendToFile("\n"); } - /// @dev Populates the admin map. + /// @dev Populates the admin map. The reason the chain IDs configured for the admin map do not match the other + /// maps is that we only have multisigs for the chains listed below, otherwise, the default admin is used.​ function populateAdminMap() internal { adminMap[42_161] = 0xF34E41a6f6Ce5A45559B1D3Ee92E141a3De96376; // Arbitrum adminMap[43_114] = 0x4735517616373c5137dE8bcCDc887637B8ac85Ce; // Avalanche From 27a845cfe39fe07390a34909f7c95fd388bbecf9 Mon Sep 17 00:00:00 2001 From: smol-ninja Date: Wed, 9 Oct 2024 14:48:23 +0100 Subject: [PATCH 5/5] chore: remove deployments from gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index aabd66f6..13a236df 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ artifacts broadcast cache coverage -deployments docs node_modules out