From 02a9da183e74fe0d5e20e4cf9493398931c2735e Mon Sep 17 00:00:00 2001 From: Diana Carvalho Date: Mon, 24 Feb 2025 15:56:59 +0000 Subject: [PATCH] feat: Deploy executors and set them in router --- don't change below this line --- ENG-4101 Took 59 minutes Took 10 seconds --- foundry/package-lock.json | 50 ++++++++++++++--------- foundry/package.json | 3 +- foundry/scripts/README.md | 21 +++++++--- foundry/scripts/deploy-executors.js | 45 +++++++++++++++++++++ foundry/scripts/deploy-router.js | 1 - foundry/scripts/executors.json | 18 +++++++++ foundry/scripts/set-executors.js | 62 +++++++++++++++++++++++++++++ foundry/scripts/set-roles.js | 6 +-- test/TychoRouter.t.sol | 1 - 9 files changed, 178 insertions(+), 29 deletions(-) create mode 100644 foundry/scripts/deploy-executors.js create mode 100644 foundry/scripts/executors.json create mode 100644 foundry/scripts/set-executors.js delete mode 100644 test/TychoRouter.t.sol diff --git a/foundry/package-lock.json b/foundry/package-lock.json index 845ec0c..b4a9c11 100644 --- a/foundry/package-lock.json +++ b/foundry/package-lock.json @@ -6,7 +6,9 @@ "": { "name": "hardhat-project", "dependencies": { - "@nomicfoundation/hardhat-foundry": "^1.1.3" + "@nomicfoundation/hardhat-foundry": "^1.1.3", + "ethers": "^5.0.0", + "prompt-sync": "^4.2.0" }, "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.2.3", @@ -965,7 +967,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "dev": true, "funding": [ { "type": "individual", @@ -1041,7 +1042,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "dev": true, "funding": [ { "type": "individual", @@ -1095,7 +1095,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "dev": true, "funding": [ { "type": "individual", @@ -1125,7 +1124,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "dev": true, "funding": [ { "type": "individual", @@ -1208,7 +1206,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "dev": true, "funding": [ { "type": "individual", @@ -1246,7 +1243,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "dev": true, "funding": [ { "type": "individual", @@ -1284,7 +1280,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", - "dev": true, "funding": [ { "type": "individual", @@ -1323,7 +1318,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "dev": true, "funding": [ { "type": "individual", @@ -1367,7 +1361,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "dev": true, "funding": [ { "type": "individual", @@ -1437,7 +1430,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "dev": true, "funding": [ { "type": "individual", @@ -1458,7 +1450,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "dev": true, "funding": [ { "type": "individual", @@ -1513,7 +1504,6 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", - "dev": true, "funding": [ { "type": "individual", @@ -3780,8 +3770,7 @@ "node_modules/aes-js": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", - "dev": true + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" }, "node_modules/agent-base": { "version": "6.0.2", @@ -4023,8 +4012,7 @@ "node_modules/bech32": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "dev": true + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" }, "node_modules/binary-extensions": { "version": "2.3.0", @@ -4798,7 +4786,6 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, "funding": [ { "type": "individual", @@ -6727,6 +6714,33 @@ "node": ">=10" } }, + "node_modules/prompt-sync": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/prompt-sync/-/prompt-sync-4.2.0.tgz", + "integrity": "sha512-BuEzzc5zptP5LsgV5MZETjDaKSWfchl5U9Luiu8SKp7iZWD5tZalOxvNcZRwv+d2phNFr8xlbxmFNcRKfJOzJw==", + "dependencies": { + "strip-ansi": "^5.0.0" + } + }, + "node_modules/prompt-sync/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/prompt-sync/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", diff --git a/foundry/package.json b/foundry/package.json index 1bd0234..3b23875 100644 --- a/foundry/package.json +++ b/foundry/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "@nomicfoundation/hardhat-foundry": "^1.1.3", - "ethers": "^5.0.0" + "ethers": "^5.0.0", + "prompt-sync": "^4.2.0" } } diff --git a/foundry/scripts/README.md b/foundry/scripts/README.md index bb99d3a..652ecc2 100644 --- a/foundry/scripts/README.md +++ b/foundry/scripts/README.md @@ -2,7 +2,7 @@ - Install dependencies `npm install` -## Deploy on Tenderly fork +## Deploy on a Tenderly fork 1. Make a new [fork](https://dashboard.tenderly.co/) in tenderly dashboard. 2. Set the following environment variables: @@ -14,7 +14,18 @@ export PRIVATE_KEY= ``` 3. Fund wallet: `npx hardhat run scripts/fund-wallet-tenderly-fork.js --network tenderly` -4. Deploy router: `npx hardhat run scripts/deploy-router.js --network tenderly` -5. Define the accounts to grant roles to in `scripts/roles.json` -6. Export the router address to the environment variable `export ROUTER=` -7. Grant roles: `npx hardhat run scripts/set-roles.js --network tenderly` + +### Deploy Tycho Router + +1. Deploy router: `npx hardhat run scripts/deploy-router.js --network tenderly` +2. Define the accounts to grant roles to in `scripts/roles.json` +3. Export the router address to the environment variable `export ROUTER=` +4. Grant roles: `npx hardhat run scripts/set-roles.js --network tenderly` +5. Set executors: `npx hardhat run scripts/set-executors.js --network tenderly`. Make sure you change the DEPLOY_WALLET + to the executor deployer wallet. If you need to deploy executors, follow the instructions below. + +### Deploy executors + +1. In `scripts/deploy-executors.js` define the executors to be deployed +2. Deploy executors: `npx hardhat run scripts/deploy-executors.js --network tenderly` +3. Fill in the executor addresses in `scripts/executors.json` diff --git a/foundry/scripts/deploy-executors.js b/foundry/scripts/deploy-executors.js new file mode 100644 index 0000000..eadaae4 --- /dev/null +++ b/foundry/scripts/deploy-executors.js @@ -0,0 +1,45 @@ +require('dotenv').config(); +const {ethers} = require("hardhat"); +const hre = require("hardhat"); + +// Comment out the executors you don't want to deploy +const executors_to_deploy = [ + {exchange: "UniswapV2Executor", args: []}, + {exchange: "UniswapV3Executor", args: ["0x1F98431c8aD98523631AE4a59f267346ea31F984"]}, + {exchange: "UniswapV4Executor", args: ["0x000000000004444c5dc75cB358380D2e3dE08A90"]}, + {exchange: "BalancerV2Executor", args: []}, +] + +async function main() { + const network = hre.network.name; + console.log(`Deploying executors to ${network}`); + + const [deployer] = await ethers.getSigners(); + console.log(`Deploying with account: ${deployer.address}`); + console.log(`Account balance: ${ethers.utils.formatEther(await deployer.getBalance())} ETH`); + + for (const executor of executors_to_deploy) { + const {exchange, args} = executor; + const Executor = await ethers.getContractFactory(exchange); + const deployedExecutor = await Executor.deploy(...args); + await deployedExecutor.deployed(); + console.log(`${exchange} deployed to: ${deployedExecutor.address}`); + + try { + await hre.tenderly.verify({ + name: exchange, + address: deployedExecutor.address, + }); + console.log("Contract verified successfully on Tenderly"); + } catch (error) { + console.error("Error during contract verification:", error); + } + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error("Deployment failed:", error); + process.exit(1); + }); \ No newline at end of file diff --git a/foundry/scripts/deploy-router.js b/foundry/scripts/deploy-router.js index a138540..31ef82a 100644 --- a/foundry/scripts/deploy-router.js +++ b/foundry/scripts/deploy-router.js @@ -33,7 +33,6 @@ async function main() { } } -// Execute deployment main() .then(() => process.exit(0)) .catch((error) => { diff --git a/foundry/scripts/executors.json b/foundry/scripts/executors.json new file mode 100644 index 0000000..4a2b9dd --- /dev/null +++ b/foundry/scripts/executors.json @@ -0,0 +1,18 @@ +[ + { + "name": "UniswapV2Executor", + "executor": "0xFF804342b632bd2C210643c005Ef139c0AaeBa0c" + }, + { + "name": "UniswapV3Executor", + "executor": "0xb45f428357174C8d9DfB56E7ccf87EDdB8fDa5C6" + }, + { + "name": "UniswapV4Executor", + "executor": "0x0E759000F3C1FFEe31ecc56D125EB796151F556E" + }, + { + "name": "BalancerV2Executor", + "executor": "0x14702382b81e6d8677321ed904edd6ec3ea7e3dc" + } +] \ No newline at end of file diff --git a/foundry/scripts/set-executors.js b/foundry/scripts/set-executors.js new file mode 100644 index 0000000..e99a58a --- /dev/null +++ b/foundry/scripts/set-executors.js @@ -0,0 +1,62 @@ +require('dotenv').config(); +const {ethers} = require("hardhat"); +const path = require('path'); +const fs = require('fs'); +const hre = require("hardhat"); +const prompt = require('prompt-sync')(); + +async function main() { + const network = hre.network.name; + const routerAddress = process.env.ROUTER_ADDRESS; + console.log(`Setting executors on TychoRouter at ${routerAddress} on ${network}`); + + const [deployer] = await ethers.getSigners(); + console.log(`Setting executors with account: ${deployer.address}`); + console.log(`Account balance: ${ethers.utils.formatEther(await deployer.getBalance())} ETH`); + + const TychoRouter = await ethers.getContractFactory("TychoRouter"); + const router = TychoRouter.attach(routerAddress); + + const executorsFilePath = path.join(__dirname, "executors.json"); + const executors = JSON.parse(fs.readFileSync(executorsFilePath, "utf8")); + + // Filter out executors that are already set + const executorsToSet = []; + for (const executor of executors) { + const isExecutorSet = await router.executors(executor.executor); + if (!isExecutorSet) { + executorsToSet.push(executor); + } + } + + if (executorsToSet.length === 0) { + console.log("All executors are already set. No changes needed."); + return; + } + + console.log(`The following ${executorsToSet.length} executor(s) will be set:`); + executorsToSet.forEach(executor => { + console.log(`Name: ${executor.name}`); + console.log(`Address: ${executor.executor}`); + console.log("———"); + }); + + const userConfirmation = prompt("Do you want to proceed with setting these executors? (yes/no): "); + if (userConfirmation.toLowerCase() !== 'yes') { + console.log("Operation cancelled by user."); + return; + } + + // Set executors + const executorAddresses = executorsToSet.map(executor => executor.executor); + const tx = await router.setExecutors(executorAddresses); + await tx.wait(); // Wait for the transaction to be mined + console.log(`Executors set at transaction: ${tx.hash}`); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error("Error setting executors:", error); + process.exit(1); + }); \ No newline at end of file diff --git a/foundry/scripts/set-roles.js b/foundry/scripts/set-roles.js index 9c1aedc..88ba800 100644 --- a/foundry/scripts/set-roles.js +++ b/foundry/scripts/set-roles.js @@ -31,13 +31,13 @@ async function main() { const addresses = rolesDict[roleName]; if (addresses && addresses.length > 0) { console.log(`Granting ${roleName} to the following addresses:`, addresses); - await router.batchGrantRole(roleHash, addresses); + const tx = await router.batchGrantRole(roleHash, addresses); + await tx.wait(); // Wait for the transaction to be mined + console.log(`Role ${roleName} granted at transaction: ${tx.hash}`); } else { console.log(`No addresses found for role ${roleName}`); } } - - console.log("All roles have been set successfully."); } main() diff --git a/test/TychoRouter.t.sol b/test/TychoRouter.t.sol deleted file mode 100644 index 8b13789..0000000 --- a/test/TychoRouter.t.sol +++ /dev/null @@ -1 +0,0 @@ -