From 5b27a0bbdc97f09c79f62c6e629a0bd65d4f2ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Tue, 7 Nov 2023 11:30:06 +0100 Subject: [PATCH 01/13] feat(addresses): Get deployed addresses from mangrove-deployments package This is a first version that simply copies the latest primary addresses to the addressses/deployed folder. --- addresses/deployed/.gitignore | 7 +++ addresses/deployed/README.md | 7 +++ addresses/deployed/arbitrum.json | 14 ----- addresses/deployed/matic.json | 22 -------- addresses/deployed/maticmum.json | 30 ----------- copyDeploymentAddresses.js | 93 ++++++++++++++++++++++++++++++++ package.json | 4 +- yarn.lock | 12 ++++- 8 files changed, 121 insertions(+), 68 deletions(-) create mode 100644 addresses/deployed/.gitignore create mode 100644 addresses/deployed/README.md delete mode 100644 addresses/deployed/arbitrum.json delete mode 100644 addresses/deployed/matic.json delete mode 100644 addresses/deployed/maticmum.json create mode 100644 copyDeploymentAddresses.js diff --git a/addresses/deployed/.gitignore b/addresses/deployed/.gitignore new file mode 100644 index 000000000..d869bcf3c --- /dev/null +++ b/addresses/deployed/.gitignore @@ -0,0 +1,7 @@ +# Ignore files +* +# Ignore subdirectories +*/ +# Don't ignore the README nor this file +!.gitignore +!README.md diff --git a/addresses/deployed/README.md b/addresses/deployed/README.md new file mode 100644 index 000000000..e2ae7d328 --- /dev/null +++ b/addresses/deployed/README.md @@ -0,0 +1,7 @@ +# deployed directory + +The committed version of this directory should be empty (except for this README.md file). + +It will contain deployment addresses read by forge script. None of them will be committed. + +This directory must exist so forge script can write to it. diff --git a/addresses/deployed/arbitrum.json b/addresses/deployed/arbitrum.json deleted file mode 100644 index f0eff8a29..000000000 --- a/addresses/deployed/arbitrum.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "address": "0xb1a49C54192Ea59B233200eA38aB56650Dfb448C", - "name": "MgvOracle" - }, - { - "address": "0x1dbF9445A6c8Dc912AfAD8CCe48E40F2A8D9D227", - "name": "Mangrove" - }, - { - "address": "0x9204743121466F9de67eb058c9764b5A6608E418", - "name": "MgvReader" - } -] diff --git a/addresses/deployed/matic.json b/addresses/deployed/matic.json deleted file mode 100644 index a7936252d..000000000 --- a/addresses/deployed/matic.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "address": "0x9a58de548212F65c5406e46563372Ee6DcC0aC43", - "name": "Mangrove" - }, - { - "address": "0x692c15efcA8AABCda9511641F6ed9702d3f4cfb4", - "name": "MgvOracle" - }, - { - "address": "0x07e5a2DCf82D7b5b8ab684d9b40842E174e49908", - "name": "MgvReader" - }, - { - "address": "0xB70041dC246412E0DCE34bd788062E969276E737", - "name": "PxUSDC" - }, - { - "address": "0xba6fBacEeeE55D2d657Eb26023C64002e23Af5E8", - "name": "PxMATIC" - } -] diff --git a/addresses/deployed/maticmum.json b/addresses/deployed/maticmum.json deleted file mode 100644 index b0c82c541..000000000 --- a/addresses/deployed/maticmum.json +++ /dev/null @@ -1,30 +0,0 @@ -[ - { - "address": "0xd1805f6Fe12aFF69D4264aE3e49ef320895e2D8b", - "name": "Mangrove" - }, - { - "address": "0x82dA8C07b1E17eBDE8853405E11D89b410ec58E6", - "name": "MgvReader" - }, - { - "address": "0x8F8ff080cA0554b02BFC36A5aD465954416271eF", - "name": "MgvOracle" - }, - { - "address": "0x193163EeFfc795F9d573b171aB12cCDdE10392e8", - "name": "WMATIC" - }, - { - "address": "0xe8099699aa4A79d89dBD20A63C50b7d35ED3CD9e", - "name": "USDT" - }, - { - "address": "0xe9259C5B6936Ee6439654171AFd674b31a533985", - "name": "USDC" - }, - { - "address": "0x406bF0fcE108dD8864627EC6816AaFF8336f8231", - "name": "WETH" - } -] diff --git a/copyDeploymentAddresses.js b/copyDeploymentAddresses.js new file mode 100644 index 000000000..fc795fba7 --- /dev/null +++ b/copyDeploymentAddresses.js @@ -0,0 +1,93 @@ +const deployments = require("@mangrovedao/mangrove-deployments"); +const fs = require("fs"); +const path = require("path"); + +// FIXME: Move most of this logic into the mangrove-deployments package + +// FIXME: This is a hack to get the network names because the addresses files use non-canonical network names +const networkNames = { + 1: "mainnet", + 5: "goerli", + 137: "matic", + 42161: "arbitrum", + 80001: "maticmum", +}; + +// Get the latest deployments +// FIXME: It should be possible to choose other versions +const mangroveVersionDeployments = deployments.getMangroveVersionDeployments({ + released: undefined, +}); +const mgvOracleVersionDeployments = deployments.getMgvOracleVersionDeployments({ + released: undefined, +}); +const mgvReaderVersionDeployments = deployments.getMgvReaderVersionDeployments({ + released: undefined, +}); +// FIXME: Duplicated deployment/contract names should be removed from the token deployments +const allTestErc20VersionDeployments = + deployments.getAllTestErc20VersionDeployments({ + released: undefined, + }); + +// Construct the addresses object for each network +const contractsDeployments = [ + mangroveVersionDeployments, + mgvOracleVersionDeployments, + mgvReaderVersionDeployments, + ...allTestErc20VersionDeployments, +]; +const deployedAddresses = {}; // network name => { name: string, address: string }[] +// Iterate over each contract deployment and add the addresses to the deployedAddresses object +for (const contractDeployments of contractsDeployments) { + for (const key in contractDeployments.networkAddresses) { + let networkDeployments = contractDeployments.networkAddresses[key]; + const networkId = networkNames[key]; + let networkAddresses = deployedAddresses[networkId]; + if (networkAddresses === undefined) { + networkAddresses = []; + deployedAddresses[networkId] = networkAddresses; + } + networkAddresses.push({ + name: + contractDeployments.deploymentName ?? contractDeployments.contractName, + address: networkDeployments.primaryAddress, + }); + } +} + +// Merge two lists of addresses, letting the second list override the first for any duplicate names +function mergeAddressLists(list1, list2) { + // Create a copy of the second list + const mergedList = [...list2]; + + // Add items from the first list only if they don't exist in the second list + list1.forEach((obj1) => { + if (!list2.some((obj2) => obj2.name == obj1.name)) { + mergedList.push(obj1); + } + }); + + return mergedList; +} + +// Update the addresses files with the loaded deployment addresses +for (const networkName in deployedAddresses) { + let addressesToWrite = deployedAddresses[networkName]; + const networkAddressesFileName = `./addresses/deployed/${networkName}.json`; + const networkAddressesFilePath = path.join( + __dirname, + networkAddressesFileName, + ); + if (fs.existsSync(networkAddressesFilePath)) { + const existingNetworkAddresses = require(networkAddressesFileName); + addressesToWrite = mergeAddressLists( + existingNetworkAddresses, + addressesToWrite, + ); + } + fs.writeFileSync( + networkAddressesFilePath, + JSON.stringify(addressesToWrite, null, 2), + ); +} diff --git a/package.json b/package.json index ffe44e34b..b2440d51c 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,10 @@ "postpack": "pinst --enable", "postinstall": "husky install", "corecov": "forge coverage --match-path 'test/core/*'", - "build": "forge build && node copyArtifacts && node buildIndex && node checkNatspec", + "build": "yarn run copyDeploymentAddresses && forge build && node copyArtifacts && node buildIndex && node checkNatspec", "clean": "forge clean; rimraf index.js dist", "doc": "solcco -f doc/MgvDoc.html preprocessing/structs.ts lib/core/Constants.sol src/core/MgvLib.sol src/core/MgvCommon.sol src/core/MgvHasOffers.sol src/core/MgvOfferMaking.sol src/core/MgvOfferTaking.sol src/core/MgvOfferTakingWithPermit.sol src/core/MgvGovernable.sol src/core/MgvView.sol src/core/MgvAppendix.sol src/core/Mangrove.sol lib/core/DensityLib.sol lib/core/TickTreeLib.sol lib/core/TickLib.sol lib/core/BitLib.sol lib/core/OfferExtra.sol lib/core/OfferDetailExtra.sol lib/core/LocalExtra.sol", + "copyDeploymentAddresses": "node copyDeploymentAddresses", "preproc": "ts-node preprocessing/run.ts", "generate-ratios": "node test-ratios/generate_ratios.js", "gas-measurement": "GAS_MATCH_PATH='test/core/gas/*' bash gas-measurement.sh", @@ -41,6 +42,7 @@ "gas-measurement.sh" ], "devDependencies": { + "@mangrovedao/mangrove-deployments": "^0.0.2-0", "@types/node": "^20.9.0", "bn.js": "^5.2.1", "husky": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index 28a600a6e..68c88efc3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -108,6 +108,7 @@ __metadata: version: 0.0.0-use.local resolution: "@mangrovedao/mangrove-core@workspace:." dependencies: + "@mangrovedao/mangrove-deployments": ^0.0.2-0 "@types/node": ^20.9.0 bn.js: ^5.2.1 husky: ^8.0.3 @@ -126,6 +127,15 @@ __metadata: languageName: unknown linkType: soft +"@mangrovedao/mangrove-deployments@npm:^0.0.2-0": + version: 0.0.2-0 + resolution: "@mangrovedao/mangrove-deployments@npm:0.0.2-0" + dependencies: + semver: ^7.5.4 + checksum: 390701d2eba1a08753c318ca7dcb11f0c429b4d4392354c47f9538ed96385f72cdffc0fdd7ac21798a25d62956fabacd9e0ba5f263fca684b5a96cda5eb1d351 + languageName: node + linkType: hard + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -2088,7 +2098,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.7, semver@npm:^7.5.2": +"semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.4": version: 7.5.4 resolution: "semver@npm:7.5.4" dependencies: From 5185a395632f66312fe07a07e1575373aa469c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Tue, 7 Nov 2023 11:39:12 +0100 Subject: [PATCH 02/13] ci: Remove deployment addresses file guard --- .github/workflows/node.js.yml | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index ab475f39e..9a1938ac8 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -18,28 +18,6 @@ concurrency: env: NODE_ENV: test jobs: - file-guard: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - uses: dorny/paths-filter@v2 - id: changes - with: - filters: | - addresses: - - 'addresses/deployed/*.json' - - - name: Fail if addresses changed unless PR has 'update address' label - if: > - ( github.event_name == 'pull_request' - && !contains(github.event.pull_request.labels.*.name,'update address') - && steps.changes.outputs.addresses == 'true') - uses: actions/github-script@v7 - with: - script: core.setFailed('You have changed an address in mangrove-core (deployed/*.json). PR must be marked \'update address\' for CI to run') - # ==== Job: Build and test mangrove-core mangrove-core: runs-on: ubuntu-22.0-4core @@ -125,7 +103,6 @@ jobs: if: always() needs: - - file-guard - mangrove-core runs-on: ubuntu-latest From 7d55fd3269d90390c38c3dcd64529c8a3aa53634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Wed, 8 Nov 2023 12:32:00 +0100 Subject: [PATCH 03/13] feat: Make deployment queries configurable By default, query for deployments matching patches of the package version. --- config.js | 14 ++++++++++++++ copyDeploymentAddresses.js | 31 +++++++++++++++++-------------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/config.js b/config.js index 93214a0e5..c22883428 100644 --- a/config.js +++ b/config.js @@ -10,3 +10,17 @@ exports.abi_exports = [ // Contracts that should export their ABI + bytecode exports.full_exports = ["SimpleTestMaker"]; + +///////////////////////////////////// +// mangrove-deployments configuration + +// The SemVer range describing the versions of the Mangrove core contracts +// to query mangrove-deployments for. +// Default is the latest patch of the current package version. +const packageVersion = require("./package.json").version; +exports.coreDeploymentVersionRangePattern = `^${packageVersion}`; + +// Whether to query mangrove-deployments for released (true), unreleased (false), +// or the latest of either (undefined) versions of the core contracts. +// Default is the latest regardless of their release status. +exports.coreDeploymentVersionReleasedFilter = undefined; diff --git a/copyDeploymentAddresses.js b/copyDeploymentAddresses.js index fc795fba7..624aeac03 100644 --- a/copyDeploymentAddresses.js +++ b/copyDeploymentAddresses.js @@ -1,10 +1,10 @@ const deployments = require("@mangrovedao/mangrove-deployments"); const fs = require("fs"); const path = require("path"); +const config = require("./config"); -// FIXME: Move most of this logic into the mangrove-deployments package - -// FIXME: This is a hack to get the network names because the addresses files use non-canonical network names +// This is a hack to get the network names because the addresses +// file names use non-canonical network names from ethers.js const networkNames = { 1: "mainnet", 5: "goerli", @@ -13,16 +13,18 @@ const networkNames = { 80001: "maticmum", }; -// Get the latest deployments -// FIXME: It should be possible to choose other versions +// Query deployments based on the configuration in config.js const mangroveVersionDeployments = deployments.getMangroveVersionDeployments({ - released: undefined, + version: config.coreDeploymentVersionRangePattern, + released: config.coreDeploymentVersionReleasedFilter, }); const mgvOracleVersionDeployments = deployments.getMgvOracleVersionDeployments({ - released: undefined, + version: config.coreDeploymentVersionRangePattern, + released: config.coreDeploymentVersionReleasedFilter, }); const mgvReaderVersionDeployments = deployments.getMgvReaderVersionDeployments({ - released: undefined, + version: config.coreDeploymentVersionRangePattern, + released: config.coreDeploymentVersionReleasedFilter, }); // FIXME: Duplicated deployment/contract names should be removed from the token deployments const allTestErc20VersionDeployments = @@ -36,17 +38,18 @@ const contractsDeployments = [ mgvOracleVersionDeployments, mgvReaderVersionDeployments, ...allTestErc20VersionDeployments, -]; +].filter((x) => x !== undefined); const deployedAddresses = {}; // network name => { name: string, address: string }[] // Iterate over each contract deployment and add the addresses to the deployedAddresses object for (const contractDeployments of contractsDeployments) { - for (const key in contractDeployments.networkAddresses) { - let networkDeployments = contractDeployments.networkAddresses[key]; - const networkId = networkNames[key]; - let networkAddresses = deployedAddresses[networkId]; + for (const [networkId, networkDeployments] of Object.entries( + contractDeployments.networkAddresses, + )) { + const networkName = networkNames[+networkId]; + let networkAddresses = deployedAddresses[networkName]; if (networkAddresses === undefined) { networkAddresses = []; - deployedAddresses[networkId] = networkAddresses; + deployedAddresses[networkName] = networkAddresses; } networkAddresses.push({ name: From 2016b4455816a777a94b447dea04cd6bfb793a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Wed, 8 Nov 2023 12:36:56 +0100 Subject: [PATCH 04/13] feat: Replace deployed addresses files instead of merging --- copyDeploymentAddresses.js | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/copyDeploymentAddresses.js b/copyDeploymentAddresses.js index 624aeac03..3ac7f3f69 100644 --- a/copyDeploymentAddresses.js +++ b/copyDeploymentAddresses.js @@ -59,36 +59,13 @@ for (const contractDeployments of contractsDeployments) { } } -// Merge two lists of addresses, letting the second list override the first for any duplicate names -function mergeAddressLists(list1, list2) { - // Create a copy of the second list - const mergedList = [...list2]; - - // Add items from the first list only if they don't exist in the second list - list1.forEach((obj1) => { - if (!list2.some((obj2) => obj2.name == obj1.name)) { - mergedList.push(obj1); - } - }); - - return mergedList; -} - -// Update the addresses files with the loaded deployment addresses +// Replace the addresses files with the loaded deployment addresses for (const networkName in deployedAddresses) { let addressesToWrite = deployedAddresses[networkName]; - const networkAddressesFileName = `./addresses/deployed/${networkName}.json`; const networkAddressesFilePath = path.join( __dirname, - networkAddressesFileName, + `./addresses/deployed/${networkName}.json`, ); - if (fs.existsSync(networkAddressesFilePath)) { - const existingNetworkAddresses = require(networkAddressesFileName); - addressesToWrite = mergeAddressLists( - existingNetworkAddresses, - addressesToWrite, - ); - } fs.writeFileSync( networkAddressesFilePath, JSON.stringify(addressesToWrite, null, 2), From a1dc7046d5c49f7477acc4fbc9b26214d4dd9442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Wed, 8 Nov 2023 12:47:11 +0100 Subject: [PATCH 05/13] feat: Add config flag to turn off copying of deployment addresses --- config.js | 7 +++++++ copyDeploymentAddresses.js | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/config.js b/config.js index c22883428..e15e7ceb0 100644 --- a/config.js +++ b/config.js @@ -14,6 +14,13 @@ exports.full_exports = ["SimpleTestMaker"]; ///////////////////////////////////// // mangrove-deployments configuration +// Whether to fetch deployments from mangrove-deployments. +// Setting this to false allows manually specifying the addresses to use +// by writing them to the JSON files in the addresses/deployed directory. +// This may be useful if one wants to use a non-primary deployment. +// Default is true. +exports.copyDeployments = true; + // The SemVer range describing the versions of the Mangrove core contracts // to query mangrove-deployments for. // Default is the latest patch of the current package version. diff --git a/copyDeploymentAddresses.js b/copyDeploymentAddresses.js index 3ac7f3f69..30931ce35 100644 --- a/copyDeploymentAddresses.js +++ b/copyDeploymentAddresses.js @@ -3,6 +3,15 @@ const fs = require("fs"); const path = require("path"); const config = require("./config"); +if (!config.copyDeployments) { + console.group( + "Skipping copying deployments from the mangrove-deployments package.", + ); + console.log("Set copyDeployments = true in config.js to enable copying."); + console.log("Using addresses/deployed/*.json files as-is instead."); + console.groupEnd(); +} + // This is a hack to get the network names because the addresses // file names use non-canonical network names from ethers.js const networkNames = { From ff4ff7bd6ee409ff23bd97059886fc7ba134f622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Fri, 10 Nov 2023 15:04:40 +0100 Subject: [PATCH 06/13] feat(addresses): Get context addresses from context-addresses package This is a first version that simply copies the addresses to the addressses/context folder. --- addresses/context/.gitignore | 7 +++ addresses/context/README.md | 7 +++ addresses/context/arbitrum.json | 26 ---------- addresses/context/goerli.json | 14 ------ addresses/context/matic.json | 26 ---------- addresses/context/maticmum.json | 22 --------- config.js | 9 ++++ copyContextAddresses.js | 87 +++++++++++++++++++++++++++++++++ copyDeploymentAddresses.js | 33 +++++++------ package.json | 4 +- yarn.lock | 10 ++++ 11 files changed, 140 insertions(+), 105 deletions(-) create mode 100644 addresses/context/.gitignore create mode 100644 addresses/context/README.md delete mode 100644 addresses/context/arbitrum.json delete mode 100644 addresses/context/goerli.json delete mode 100644 addresses/context/matic.json delete mode 100644 addresses/context/maticmum.json create mode 100644 copyContextAddresses.js diff --git a/addresses/context/.gitignore b/addresses/context/.gitignore new file mode 100644 index 000000000..d869bcf3c --- /dev/null +++ b/addresses/context/.gitignore @@ -0,0 +1,7 @@ +# Ignore files +* +# Ignore subdirectories +*/ +# Don't ignore the README nor this file +!.gitignore +!README.md diff --git a/addresses/context/README.md b/addresses/context/README.md new file mode 100644 index 000000000..f21911bdf --- /dev/null +++ b/addresses/context/README.md @@ -0,0 +1,7 @@ +# context directory + +The committed version of this directory should be empty (except for this README.md file). + +It will contain context addresses read by forge script. None of them will be committed. + +This directory must exist so forge script can write to it. diff --git a/addresses/context/arbitrum.json b/addresses/context/arbitrum.json deleted file mode 100644 index 03a8f6625..000000000 --- a/addresses/context/arbitrum.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "address": "0x10B124Da45Bc440171664cee59Aafa23979C9616", - "name": "Gasbot" - }, - { - "address": "0x623059d3c70aC9a3DDe047CB630ff08634DaDedc", - "name": "MgvGovernance" - }, - { - "address": "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", - "name": "DAI" - }, - { - "address": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", - "name": "WETH" - }, - { - "address": "0xaf88d065e77c8cc2239327c5edb3a432268e5831", - "name": "USDC" - }, - { - "address": "0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9", - "name": "USDT" - } -] diff --git a/addresses/context/goerli.json b/addresses/context/goerli.json deleted file mode 100644 index 17fe2c196..000000000 --- a/addresses/context/goerli.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "address": "0x695364ffaa20f205e337f9e6226e5e22525838d9", - "name": "WETH" - }, - { - "address": "0x3a034fe373b6304f98b7a24a3f21c958946d4075", - "name": "USDC" - }, - { - "address": "0xd77b79be3e85351ff0cbe78f1b58cf8d1064047c", - "name": "DAI" - } -] diff --git a/addresses/context/matic.json b/addresses/context/matic.json deleted file mode 100644 index 1ba1a1fe8..000000000 --- a/addresses/context/matic.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", - "name": "WETH" - }, - { - "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", - "name": "USDC" - }, - { - "address": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", - "name": "USDT" - }, - { - "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", - "name": "DAI" - }, - { - "address": "0x10B124Da45Bc440171664cee59Aafa23979C9616", - "name": "Gasbot" - }, - { - "address": "0x59a424169526ECae25856038598F862043DCeDf7", - "name": "MgvGovernance" - } -] diff --git a/addresses/context/maticmum.json b/addresses/context/maticmum.json deleted file mode 100644 index 0b10c7b57..000000000 --- a/addresses/context/maticmum.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "address": "0x4d184a4C8d79BbBdCC4E95A1AdEA2454c535280A", - "name": "Gasbot" - }, - { - "address": "0x47897EE61498D02B18794601Ed3A71896A1Ff894", - "name": "MgvGovernance" - }, - { - "address": "0x2Fa2e7a6dEB7bb51B625336DBe1dA23511914a8A", - "name": "WBTC" - }, - { - "address": "0xc8c0Cf9436F4862a8F60Ce680Ca5a9f0f99b5ded", - "name": "DAI" - }, - { - "address": "0x2bbF1f48a678d2f7c291dc5F8fD04805D34F485f", - "name": "CRV" - } -] diff --git a/config.js b/config.js index e15e7ceb0..13957d245 100644 --- a/config.js +++ b/config.js @@ -31,3 +31,12 @@ exports.coreDeploymentVersionRangePattern = `^${packageVersion}`; // or the latest of either (undefined) versions of the core contracts. // Default is the latest regardless of their release status. exports.coreDeploymentVersionReleasedFilter = undefined; + +////////////////////////////////// +// context-addresses configuration + +// Whether to fetch deployments from context-addresses. +// Setting this to false allows manually specifying the addresses to use +// by writing them to the JSON files in the addresses/context directory. +// Default is true. +exports.copyContextAddresses = true; diff --git a/copyContextAddresses.js b/copyContextAddresses.js new file mode 100644 index 000000000..c610ed489 --- /dev/null +++ b/copyContextAddresses.js @@ -0,0 +1,87 @@ +const contextAddresses = require("@mangrovedao/context-addresses"); +const fs = require("fs"); +const path = require("path"); +const config = require("./config"); + +if (!config.copyContextAddresses) { + console.group( + "Skipping copying context addresses from the context-addresses package.", + ); + console.log( + "Set copyContextAddresses = true in config.js to enable copying.", + ); + console.log("Using addresses/context/*.json files as-is instead."); + console.groupEnd(); +} + +// This is a hack to get the network names because the addresses +// file names use non-canonical network names from ethers.js +const networkNames = { + 1: "mainnet", + 5: "goerli", + 137: "matic", + 42161: "arbitrum", + 80001: "maticmum", +}; + +// Construct the addresses object for each network +// FIXME: For ERC20, name == symbol for now as this how it was done before. This should change to use the ERC20 id instead. +// This relies the fact that only one ERC20 instance is marked as 'default' for each network. +const contextAddressesByNetwork = {}; // network name => { name: string, address: string }[] +function getOrCreateNetworkAddresses(networkId) { + const networkName = networkNames[+networkId]; + let networkAddresses = contextAddressesByNetwork[networkName]; + if (networkAddresses === undefined) { + networkAddresses = []; + contextAddressesByNetwork[networkName] = networkAddresses; + } + return networkAddresses; +} + +// Accounts +const allAccounts = contextAddresses.getAllAccounts(); +for (const [accountId, account] of Object.entries(allAccounts)) { + for (const [networkId, address] of Object.entries(account.networkAddresses)) { + const networkAddresses = getOrCreateNetworkAddresses(networkId); + networkAddresses.push({ + name: accountId, + address: address, + }); + } +} + +// Token addresses +const allErc20s = contextAddresses.getAllErc20s(); +for (const [erc20Id, erc20] of Object.entries(allErc20s)) { + for (const [networkId, networkInstances] of Object.entries( + erc20.networkInstances, + )) { + const networkAddresses = getOrCreateNetworkAddresses(networkId); + // NOTE: There is only one instance here since only one ERC20 instance is marked as 'default' for each network. + for (const [instanceId, networkInstance] of Object.entries( + networkInstances, + )) { + if (!networkInstance.default) { + continue; + } + networkAddresses.push({ + name: erc20.symbol, + address: networkInstance.address, + }); + break; + } + } +} + +// Replace the addresses files with the loaded context addresses +for (const networkName in contextAddressesByNetwork) { + let addressesToWrite = contextAddressesByNetwork[networkName]; + const networkAddressesFilePath = path.join( + __dirname, + `./addresses/context/${networkName}.json`, + ); + fs.writeFileSync( + networkAddressesFilePath, + JSON.stringify(addressesToWrite, null, 2), + ); +} diff --git a/copyDeploymentAddresses.js b/copyDeploymentAddresses.js index 30931ce35..7a16f6d8a 100644 --- a/copyDeploymentAddresses.js +++ b/copyDeploymentAddresses.js @@ -35,31 +35,32 @@ const mgvReaderVersionDeployments = deployments.getMgvReaderVersionDeployments({ version: config.coreDeploymentVersionRangePattern, released: config.coreDeploymentVersionReleasedFilter, }); -// FIXME: Duplicated deployment/contract names should be removed from the token deployments -const allTestErc20VersionDeployments = - deployments.getAllTestErc20VersionDeployments({ - released: undefined, - }); + +// NB: Test token deployments are included in the context-addresses package, +// so they are not queried from mangrove-deployments. // Construct the addresses object for each network const contractsDeployments = [ mangroveVersionDeployments, mgvOracleVersionDeployments, mgvReaderVersionDeployments, - ...allTestErc20VersionDeployments, ].filter((x) => x !== undefined); -const deployedAddresses = {}; // network name => { name: string, address: string }[] -// Iterate over each contract deployment and add the addresses to the deployedAddresses object +const deployedAddressesByNetwork = {}; // network name => { name: string, address: string }[] +function getOrCreateNetworkAddresses(networkId) { + const networkName = networkNames[+networkId]; + let networkAddresses = deployedAddressesByNetwork[networkName]; + if (networkAddresses === undefined) { + networkAddresses = []; + deployedAddressesByNetwork[networkName] = networkAddresses; + } + return networkAddresses; +} + for (const contractDeployments of contractsDeployments) { for (const [networkId, networkDeployments] of Object.entries( contractDeployments.networkAddresses, )) { - const networkName = networkNames[+networkId]; - let networkAddresses = deployedAddresses[networkName]; - if (networkAddresses === undefined) { - networkAddresses = []; - deployedAddresses[networkName] = networkAddresses; - } + const networkAddresses = getOrCreateNetworkAddresses(networkId); networkAddresses.push({ name: contractDeployments.deploymentName ?? contractDeployments.contractName, @@ -69,8 +70,8 @@ for (const contractDeployments of contractsDeployments) { } // Replace the addresses files with the loaded deployment addresses -for (const networkName in deployedAddresses) { - let addressesToWrite = deployedAddresses[networkName]; +for (const networkName in deployedAddressesByNetwork) { + let addressesToWrite = deployedAddressesByNetwork[networkName]; const networkAddressesFilePath = path.join( __dirname, `./addresses/deployed/${networkName}.json`, diff --git a/package.json b/package.json index b2440d51c..c1bdd4b12 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,11 @@ "postpack": "pinst --enable", "postinstall": "husky install", "corecov": "forge coverage --match-path 'test/core/*'", - "build": "yarn run copyDeploymentAddresses && forge build && node copyArtifacts && node buildIndex && node checkNatspec", + "build": "yarn run copyDeploymentAddresses && yarn run copyContextAddresses && forge build && node copyArtifacts && node buildIndex && node checkNatspec", "clean": "forge clean; rimraf index.js dist", "doc": "solcco -f doc/MgvDoc.html preprocessing/structs.ts lib/core/Constants.sol src/core/MgvLib.sol src/core/MgvCommon.sol src/core/MgvHasOffers.sol src/core/MgvOfferMaking.sol src/core/MgvOfferTaking.sol src/core/MgvOfferTakingWithPermit.sol src/core/MgvGovernable.sol src/core/MgvView.sol src/core/MgvAppendix.sol src/core/Mangrove.sol lib/core/DensityLib.sol lib/core/TickTreeLib.sol lib/core/TickLib.sol lib/core/BitLib.sol lib/core/OfferExtra.sol lib/core/OfferDetailExtra.sol lib/core/LocalExtra.sol", "copyDeploymentAddresses": "node copyDeploymentAddresses", + "copyContextAddresses": "node copyContextAddresses", "preproc": "ts-node preprocessing/run.ts", "generate-ratios": "node test-ratios/generate_ratios.js", "gas-measurement": "GAS_MATCH_PATH='test/core/gas/*' bash gas-measurement.sh", @@ -42,6 +43,7 @@ "gas-measurement.sh" ], "devDependencies": { + "@mangrovedao/context-addresses": "^0.0.2-0", "@mangrovedao/mangrove-deployments": "^0.0.2-0", "@types/node": "^20.9.0", "bn.js": "^5.2.1", diff --git a/yarn.lock b/yarn.lock index 68c88efc3..8980ab3dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -104,10 +104,20 @@ __metadata: languageName: node linkType: hard +"@mangrovedao/context-addresses@npm:^0.0.2-0": + version: 0.0.2-0 + resolution: "@mangrovedao/context-addresses@npm:0.0.2-0" + dependencies: + semver: ^7.5.4 + checksum: ce9a6bdded4f22b55848215336908043507f2d5f9ec482274c01d03537428ac5460b30ca55e17f377a6a41ae2fd67722c1f53a7e944c3574bb47886f0036e742 + languageName: node + linkType: hard + "@mangrovedao/mangrove-core@workspace:.": version: 0.0.0-use.local resolution: "@mangrovedao/mangrove-core@workspace:." dependencies: + "@mangrovedao/context-addresses": ^0.0.2-0 "@mangrovedao/mangrove-deployments": ^0.0.2-0 "@types/node": ^20.9.0 bn.js: ^5.2.1 From 2ff8147a386d5ed622c85db5f2fa00e2f48a10ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Fri, 10 Nov 2023 17:36:23 +0100 Subject: [PATCH 07/13] feat(addresses): Use ERC20 instance IDs Instead of the ambiguous token symbols use the instance ID's assigned by context-addresses. This makes all token instances available and enforces clarity on which ERC20 instance on is interacting with. To ease the transition, the default instances are still available using just the token symbol as identifier. However, use of this is deprecated. --- copyContextAddresses.js | 16 ++++++++-------- package.json | 4 ++-- test/core/gas/OfferGasBase.t.sol | 2 +- yarn.lock | 20 ++++++++++---------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/copyContextAddresses.js b/copyContextAddresses.js index c610ed489..a9c2d044c 100644 --- a/copyContextAddresses.js +++ b/copyContextAddresses.js @@ -25,8 +25,6 @@ const networkNames = { }; // Construct the addresses object for each network -// FIXME: For ERC20, name == symbol for now as this how it was done before. This should change to use the ERC20 id instead. -// This relies the fact that only one ERC20 instance is marked as 'default' for each network. const contextAddressesByNetwork = {}; // network name => { name: string, address: string }[] function getOrCreateNetworkAddresses(networkId) { const networkName = networkNames[+networkId]; @@ -57,18 +55,20 @@ for (const [erc20Id, erc20] of Object.entries(allErc20s)) { erc20.networkInstances, )) { const networkAddresses = getOrCreateNetworkAddresses(networkId); - // NOTE: There is only one instance here since only one ERC20 instance is marked as 'default' for each network. for (const [instanceId, networkInstance] of Object.entries( networkInstances, )) { - if (!networkInstance.default) { - continue; - } networkAddresses.push({ - name: erc20.symbol, + name: instanceId, address: networkInstance.address, }); - break; + // Also register the default instance as the token symbol for convenience + if (networkInstance.default) { + networkAddresses.push({ + name: erc20.symbol, + address: networkInstance.address, + }); + } } } } diff --git a/package.json b/package.json index c1bdd4b12..43e343ea8 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,8 @@ "gas-measurement.sh" ], "devDependencies": { - "@mangrovedao/context-addresses": "^0.0.2-0", - "@mangrovedao/mangrove-deployments": "^0.0.2-0", + "@mangrovedao/context-addresses": "next", + "@mangrovedao/mangrove-deployments": "next", "@types/node": "^20.9.0", "bn.js": "^5.2.1", "husky": "^8.0.3", diff --git a/test/core/gas/OfferGasBase.t.sol b/test/core/gas/OfferGasBase.t.sol index a4e3426d1..769313a4f 100644 --- a/test/core/gas/OfferGasBase.t.sol +++ b/test/core/gas/OfferGasBase.t.sol @@ -25,6 +25,6 @@ contract OfferGasBaseGasreqMeasuringTest_Generic_A_B is OfferGasBaseBaseTest { contract OfferGasBaseTest_Polygon_WETH_DAI is OfferGasBaseBaseTest { function setUp() public override { super.setUpPolygon(); - this.setUpTokens("WETH", "DAI"); + this.setUpTokens("WETH.e", "DAI.e"); } } diff --git a/yarn.lock b/yarn.lock index 8980ab3dd..41d298cbe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -104,12 +104,12 @@ __metadata: languageName: node linkType: hard -"@mangrovedao/context-addresses@npm:^0.0.2-0": - version: 0.0.2-0 - resolution: "@mangrovedao/context-addresses@npm:0.0.2-0" +"@mangrovedao/context-addresses@npm:next": + version: 0.0.2-2 + resolution: "@mangrovedao/context-addresses@npm:0.0.2-2" dependencies: semver: ^7.5.4 - checksum: ce9a6bdded4f22b55848215336908043507f2d5f9ec482274c01d03537428ac5460b30ca55e17f377a6a41ae2fd67722c1f53a7e944c3574bb47886f0036e742 + checksum: 1f9389c1533da92d6032d26cab4edb483a5608096933e8a70c733a26dea0f39208e514fd43006c6d5ad5a08c984f47dff5b5d252a85664854114b8b7d51b12b0 languageName: node linkType: hard @@ -117,8 +117,8 @@ __metadata: version: 0.0.0-use.local resolution: "@mangrovedao/mangrove-core@workspace:." dependencies: - "@mangrovedao/context-addresses": ^0.0.2-0 - "@mangrovedao/mangrove-deployments": ^0.0.2-0 + "@mangrovedao/context-addresses": next + "@mangrovedao/mangrove-deployments": next "@types/node": ^20.9.0 bn.js: ^5.2.1 husky: ^8.0.3 @@ -137,12 +137,12 @@ __metadata: languageName: unknown linkType: soft -"@mangrovedao/mangrove-deployments@npm:^0.0.2-0": - version: 0.0.2-0 - resolution: "@mangrovedao/mangrove-deployments@npm:0.0.2-0" +"@mangrovedao/mangrove-deployments@npm:next": + version: 0.0.2-1 + resolution: "@mangrovedao/mangrove-deployments@npm:0.0.2-1" dependencies: semver: ^7.5.4 - checksum: 390701d2eba1a08753c318ca7dcb11f0c429b4d4392354c47f9538ed96385f72cdffc0fdd7ac21798a25d62956fabacd9e0ba5f263fca684b5a96cda5eb1d351 + checksum: b6c53d3c5339a2e5cc45b1b53e359e85fd46f657286b9bf4255a319b6c72211e1c5a9a25f14ab7ae895d38d1e7923ab0f5e5398618b238eeef782aa34bd703e3 languageName: node linkType: hard From 6f2c644ebc3936c7b97191dcdd10753dd67d1f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Sat, 11 Nov 2023 10:09:27 +0100 Subject: [PATCH 08/13] feat!(addresses): Do not include addresses in distribution --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 43e343ea8..8d4a09e15 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "/src", "/script", "/test/lib/**/*", - "/addresses/**/!(*.backup.json)", "foundry.toml", "remappings.txt", "/lib", From f5f64d2de7bfe744b9fd2a83791083725db083dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Tue, 14 Nov 2023 17:48:50 +0100 Subject: [PATCH 09/13] chore(addresses): Bump context-addresses --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 41d298cbe..40ceeb55e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -105,11 +105,11 @@ __metadata: linkType: hard "@mangrovedao/context-addresses@npm:next": - version: 0.0.2-2 - resolution: "@mangrovedao/context-addresses@npm:0.0.2-2" + version: 0.0.2-5 + resolution: "@mangrovedao/context-addresses@npm:0.0.2-5" dependencies: semver: ^7.5.4 - checksum: 1f9389c1533da92d6032d26cab4edb483a5608096933e8a70c733a26dea0f39208e514fd43006c6d5ad5a08c984f47dff5b5d252a85664854114b8b7d51b12b0 + checksum: 4b926524f80b3886dad893d2415fb5d8f2a5b23e6d900112765cdad1b6cc90d017b025a59d0451da4aee50d4970ce6768f53d92d837808c7eb304da81d8343b7 languageName: node linkType: hard From e981230aa16ee8ca02090df19e2b4a16ce9dbf06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Wed, 15 Nov 2023 11:15:04 +0100 Subject: [PATCH 10/13] fix(addresses): Stop address copy scripts if disabled --- copyContextAddresses.js | 1 + copyDeploymentAddresses.js | 1 + 2 files changed, 2 insertions(+) diff --git a/copyContextAddresses.js b/copyContextAddresses.js index a9c2d044c..cc84b627c 100644 --- a/copyContextAddresses.js +++ b/copyContextAddresses.js @@ -12,6 +12,7 @@ if (!config.copyContextAddresses) { ); console.log("Using addresses/context/*.json files as-is instead."); console.groupEnd(); + process.exit(0); } // This is a hack to get the network names because the addresses diff --git a/copyDeploymentAddresses.js b/copyDeploymentAddresses.js index 7a16f6d8a..ae78ae09c 100644 --- a/copyDeploymentAddresses.js +++ b/copyDeploymentAddresses.js @@ -10,6 +10,7 @@ if (!config.copyDeployments) { console.log("Set copyDeployments = true in config.js to enable copying."); console.log("Using addresses/deployed/*.json files as-is instead."); console.groupEnd(); + process.exit(0); } // This is a hack to get the network names because the addresses From ffafa3b35fe844166fdee62c0b534b5629000556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Wed, 15 Nov 2023 11:16:51 +0100 Subject: [PATCH 11/13] feat(addresses): Log progress when copying addresses --- copyContextAddresses.js | 6 ++++++ copyDeploymentAddresses.js | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/copyContextAddresses.js b/copyContextAddresses.js index cc84b627c..d48894445 100644 --- a/copyContextAddresses.js +++ b/copyContextAddresses.js @@ -3,6 +3,8 @@ const fs = require("fs"); const path = require("path"); const config = require("./config"); +const script = path.basename(__filename); + if (!config.copyContextAddresses) { console.group( "Skipping copying context addresses from the context-addresses package.", @@ -15,6 +17,8 @@ if (!config.copyContextAddresses) { process.exit(0); } +console.log(`${script}: Copying context addresses...`); + // This is a hack to get the network names because the addresses // file names use non-canonical network names from ethers.js const networkNames = { @@ -86,3 +90,5 @@ for (const networkName in contextAddressesByNetwork) { JSON.stringify(addressesToWrite, null, 2), ); } + +console.log(`${script}: ...Done copying context addresses`); diff --git a/copyDeploymentAddresses.js b/copyDeploymentAddresses.js index ae78ae09c..5d1015939 100644 --- a/copyDeploymentAddresses.js +++ b/copyDeploymentAddresses.js @@ -3,6 +3,8 @@ const fs = require("fs"); const path = require("path"); const config = require("./config"); +const script = path.basename(__filename); + if (!config.copyDeployments) { console.group( "Skipping copying deployments from the mangrove-deployments package.", @@ -13,6 +15,8 @@ if (!config.copyDeployments) { process.exit(0); } +console.log(`${script}: Copying deployment addresses...`); + // This is a hack to get the network names because the addresses // file names use non-canonical network names from ethers.js const networkNames = { @@ -82,3 +86,5 @@ for (const networkName in deployedAddressesByNetwork) { JSON.stringify(addressesToWrite, null, 2), ); } + +console.log(`${script}: ...Done copying deployment addresses`); From 2a745aa1803f83dd96daf7a94b717e5be32cb973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Wed, 15 Nov 2023 11:17:28 +0100 Subject: [PATCH 12/13] ci: Update CI workflow step names --- .github/workflows/node.js.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 9a1938ac8..7f8dfd8a8 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -39,23 +39,23 @@ jobs: - name: Foundry Setup uses: mangrovedao/.github/.github/actions/foundry-setup@master - - name: Solidity Compile + - name: Build run: yarn run build # Pinned forks are used in tests and utilize secrets. For PRs from forks these are not available # Let the tests attempt to run with demo endpoints which are more unstable. - - name: Mangrove Solidity Tests (fast) + - name: Solidity Tests (fast) run: yarn run test:fast env: POLYGON_NODE_URL: ${{ secrets.POLYGON_NODE_URL || 'https://polygon.llamarpc.com' }} MUMBAI_NODE_URL: ${{ secrets.MUMBAI_NODE_URL || 'unused' }} # Memory intensive tests run without -vvv as GitHub actions otherwise cancels the step due to memory usage - - name: Mangrove Solidity Tests (memory intensive) + - name: Solidity Tests (memory intensive) run: yarn run test:memory-intensive # For push runs we also create a coverage report - - name: Create coverage report for mangrove-solidity + - name: Create coverage report if: github.event_name != 'pull_request' run: forge coverage --report lcov env: @@ -70,7 +70,7 @@ jobs: if: github.event_name != 'pull_request' run: echo "::set-output name=sha_for_head::$(git rev-parse HEAD)" - - name: Upload to Coveralls for mangrove-solidity + - name: Upload to Coveralls uses: coverallsapp/github-action@master if: github.event_name != 'pull_request' with: From 70917d5bde336873c24c5418c9510b92ee540ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Espen=20H=C3=B8jsgaard?= Date: Wed, 15 Nov 2023 11:20:51 +0100 Subject: [PATCH 13/13] docs: Fix comments in copy*Addresses scripts --- copyContextAddresses.js | 2 +- copyDeploymentAddresses.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/copyContextAddresses.js b/copyContextAddresses.js index d48894445..50390c2b0 100644 --- a/copyContextAddresses.js +++ b/copyContextAddresses.js @@ -78,7 +78,7 @@ for (const [erc20Id, erc20] of Object.entries(allErc20s)) { } } -// Replace the addresses files with the loaded context addresses +// Create the addresses files with the loaded context addresses for (const networkName in contextAddressesByNetwork) { let addressesToWrite = contextAddressesByNetwork[networkName]; const networkAddressesFilePath = path.join( diff --git a/copyDeploymentAddresses.js b/copyDeploymentAddresses.js index 5d1015939..1ab0390a7 100644 --- a/copyDeploymentAddresses.js +++ b/copyDeploymentAddresses.js @@ -74,7 +74,7 @@ for (const contractDeployments of contractsDeployments) { } } -// Replace the addresses files with the loaded deployment addresses +// Create the addresses files with the loaded deployment addresses for (const networkName in deployedAddressesByNetwork) { let addressesToWrite = deployedAddressesByNetwork[networkName]; const networkAddressesFilePath = path.join(