diff --git a/hardhat.config.js b/hardhat.config.js index 6d23d5e1..5ef27402 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -19,12 +19,6 @@ require('solidity-coverage') require('hardhat-contract-sizer') require('./tasks/index') -require('./tasks/utils/index') -require('./tasks/Amm/index') -require('./tasks/configuration/index') -require('./tasks/option/index') -require('./tasks/local/index') -require('./tasks/oracle/index') module.exports = { networks: { diff --git a/package.json b/package.json index c630749f..052996ed 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "hardhat-spdx-license-identifier": "2.0.3", "husky": "4.2.5", "mocha": "7.2.0", + "parse-duration": "1.0.0", "prettier": "2.0.5", "prettier-plugin-solidity": "1.0.0-alpha.54", "solhint": "3.0.0", diff --git a/tasks/Amm/addLiquidityAMM.js b/tasks/amm/addLiquidityAMM.js similarity index 100% rename from tasks/Amm/addLiquidityAMM.js rename to tasks/amm/addLiquidityAMM.js diff --git a/tasks/Amm/deployBS.js b/tasks/amm/deployBS.js similarity index 100% rename from tasks/Amm/deployBS.js rename to tasks/amm/deployBS.js diff --git a/tasks/Amm/deployIVGuesser.js b/tasks/amm/deployIVGuesser.js similarity index 100% rename from tasks/Amm/deployIVGuesser.js rename to tasks/amm/deployIVGuesser.js diff --git a/tasks/Amm/deployLibs.js b/tasks/amm/deployLibs.js similarity index 100% rename from tasks/Amm/deployLibs.js rename to tasks/amm/deployLibs.js diff --git a/tasks/Amm/deployNewOptionAMMPool.js b/tasks/amm/deployNewOptionAMMPool.js similarity index 93% rename from tasks/Amm/deployNewOptionAMMPool.js rename to tasks/amm/deployNewOptionAMMPool.js index 2dbf8bb7..8250232c 100644 --- a/tasks/Amm/deployNewOptionAMMPool.js +++ b/tasks/amm/deployNewOptionAMMPool.js @@ -26,9 +26,10 @@ task('deployNewOptionAMMPool', 'Deploy a New AMM Pool') const content = await fsPromises.readFile(_filePath) const contentJSON = JSON.parse(content) - const { OptionAMMFactory: optionAMMFactory, ConfigurationManager: configurationManager } = contentJSON + const { ConfigurationManager: configurationManagerAddress } = contentJSON - const OptionAMMFactory = await ethers.getContractAt('OptionAMMFactory', optionAMMFactory) + const configurationManager = await ethers.getContractAt('ConfigurationManager', configurationManagerAddress) + const OptionAMMFactory = await ethers.getContractAt('OptionAMMFactory', await configurationManager.getAMMFactory()) const tokenBContract = await ethers.getContractAt('MintableERC20', tokenb) const txIdNewPool = await OptionAMMFactory.createPool(option, tokenb, initialiv) @@ -54,8 +55,7 @@ task('deployNewOptionAMMPool', 'Deploy a New AMM Pool') const newPoolObj = Object.assign({}, currentPools, { [poolAddress]: poolObj }) if (cap != null && parseFloat(cap) > 0) { - const cm = await ethers.getContractAt('ConfigurationManager', configurationManager) - const capProvider = await ethers.getContractAt('CapProvider', await cm.getCapProvider()) + const capProvider = await ethers.getContractAt('CapProvider', await configurationManager.getCapProvider()) const capValue = toBigNumber(cap).mul(toBigNumber(10 ** await tokenBContract.decimals())) const tx = await capProvider.setCap(poolAddress, capValue) diff --git a/tasks/Amm/deployNormalDistribution.js b/tasks/amm/deployNormalDistribution.js similarity index 100% rename from tasks/Amm/deployNormalDistribution.js rename to tasks/amm/deployNormalDistribution.js diff --git a/tasks/Amm/deployOptionAMMFactory.js b/tasks/amm/deployOptionAMMFactory.js similarity index 100% rename from tasks/Amm/deployOptionAMMFactory.js rename to tasks/amm/deployOptionAMMFactory.js diff --git a/tasks/Amm/index.js b/tasks/amm/index.js similarity index 100% rename from tasks/Amm/index.js rename to tasks/amm/index.js diff --git a/tasks/Amm/setAMMEnvironment.js b/tasks/amm/setAMMEnvironment.js similarity index 100% rename from tasks/Amm/setAMMEnvironment.js rename to tasks/amm/setAMMEnvironment.js diff --git a/tasks/configuration/deployConfigurationManager.js b/tasks/configuration/deployConfigurationManager.js index ffe8a485..6254f17a 100644 --- a/tasks/configuration/deployConfigurationManager.js +++ b/tasks/configuration/deployConfigurationManager.js @@ -1,57 +1,38 @@ -const saveJSON = require('../utils/saveJSON') -const verifyContract = require('../utils/verify') - task('deployConfigurationManager', 'Deploy a new instance of ConfigurationManager + Emergency + Cap and link them') .addFlag('verify', 'if true, it should verify the contract after the deployment') .setAction(async ({ verify }, hre) => { - hre.run('compile') console.log('----Start Deploy ConfiguratorManager + Emergency + Cap----') - const [ConfigurationManager, EmergencyStop, CapProvider] = await Promise.all([ - ethers.getContractFactory('ConfigurationManager'), - ethers.getContractFactory('EmergencyStop'), - ethers.getContractFactory('CapProvider') - ]) - - const configurationManager = await ConfigurationManager.deploy() - await configurationManager.deployed() - const configurationManagerAddress = configurationManager.address - console.log('configurationManager Address', configurationManager.address) + const configurationManagerAddress = await hre.run('deploy', { + name: 'ConfigurationManager', + save: true, + verify + }) - const emergencyStop = await EmergencyStop.deploy() - await emergencyStop.deployed() - console.log('emergencyStop Address', emergencyStop.address) + const emergencyStopAddress = await hre.run('deploy', { + name: 'EmergencyStop', + save: true, + verify + }) await hre.run('linkConfigurationManager', { address: configurationManagerAddress, setter: 'setEmergencyStop', - newContract: emergencyStop.address + newContract: emergencyStopAddress }) - const capProvider = await CapProvider.deploy() - await capProvider.deployed() - console.log('capProvider Address', capProvider.address) + const capProviderAddress = await hre.run('deploy', { + name: 'CapProvider', + save: true, + verify + }) await hre.run('linkConfigurationManager', { address: configurationManagerAddress, setter: 'setCapProvider', - newContract: capProvider.address + newContract: capProviderAddress }) - const saveObj = { - ConfigurationManager: configurationManager.address, - EmergencyStop: emergencyStop.address, - CapProvider: capProvider.address - } - - await saveJSON(`../../deployments/${hre.network.name}.json`, saveObj) - - if (verify) { - await verifyContract(hre, configurationManager.address) - await verifyContract(hre, emergencyStop.address) - await verifyContract(hre, capProvider.address) - } - console.log('----End Deploy ConfiguratorManager + Emergency + Cap----') - return configurationManager.address + return configurationManagerAddress }) diff --git a/tasks/configuration/emergencyStop.js b/tasks/configuration/emergencyStop.js index 96f3c4f7..99c63cee 100644 --- a/tasks/configuration/emergencyStop.js +++ b/tasks/configuration/emergencyStop.js @@ -1,22 +1,18 @@ +const { getDeployments } = require('../utils/deployment') +const validateAddress = require('../utils/validateAddress') + task('emergencyStop', 'Interact with a EmergencyStop connected to a ConfigurationManager') .addOptionalParam('address', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') .addPositionalParam('command', 'The command to send. stop, resume, isStopped') .addPositionalParam('contract', 'The contract address to interact') .setAction(async ({ address, command, contract }, hre) => { - const filePath = `../../deployments/${hre.network.name}.json` - if (!address) { - const json = require(filePath) - address = json.ConfigurationManager + const deployment = getDeployments() + address = deployment.ConfigurationManager } - if (!ethers.utils.isAddress(address)) { - throw new Error(`\`address\` is not an address. Received: ${address}`) - } - - if (!ethers.utils.isAddress(contract)) { - throw new Error(`\`contract\` is not an address. Received: ${contract}`) - } + validateAddress(address, 'address') + validateAddress(contract, 'contract') const configurationManager = await ethers.getContractAt('ConfigurationManager', address) const emergencyStop = await ethers.getContractAt('EmergencyStop', await configurationManager.getEmergencyStop()) diff --git a/tasks/configuration/getParameters.js b/tasks/configuration/getParameters.js index b79a0513..bcbf05e2 100644 --- a/tasks/configuration/getParameters.js +++ b/tasks/configuration/getParameters.js @@ -1,19 +1,18 @@ +const { getDeployments } = require('../utils/deployment') +const validateAddress = require('../utils/validateAddress') + task('getParameter', 'Get a ConfigurationManager parameter') .addPositionalParam('parameter', 'Parameter name') - .addOptionalParam('configurator', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') - .setAction(async ({ configurator, parameter }, bre) => { - const filePath = `../../deployments/${bre.network.name}.json` - - if (!configurator) { - const json = require(filePath) - configurator = json.configurationManager + .addOptionalParam('configuration', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') + .setAction(async ({ configuration, parameter }, hre) => { + if (!configuration) { + const deployment = getDeployments() + configuration = deployment.ConfigurationManager } - if (!ethers.utils.isAddress(configurator)) { - throw new Error(`\`configurator\` is not an address. Received: ${configurator}`) - } + validateAddress(configuration, 'configuration') - const configurationManager = await ethers.getContractAt('ConfigurationManager', configurator) + const configurationManager = await ethers.getContractAt('ConfigurationManager', configuration) const parameterName = ethers.utils.formatBytes32String(parameter) const currentValue = (await configurationManager.getParameter(parameterName)).toString() diff --git a/tasks/configuration/increaseCap.js b/tasks/configuration/increaseCap.js index 3cd0d52a..5096a7d8 100644 --- a/tasks/configuration/increaseCap.js +++ b/tasks/configuration/increaseCap.js @@ -1,24 +1,23 @@ +const { getDeployments } = require('../utils/deployment') +const validateAddress = require('../utils/validateAddress') + task('increaseCap', 'Increase an option or pool cap') .addParam('contract', 'An address of a target address to increase cap (either option or pool') .addOptionalParam('value', 'new cap number') .addOptionalParam('configurator', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') .addFlag('max', 'set pool cap to the max') - .setAction(async ({ contract, value, configurator, max }, bre) => { + .setAction(async ({ contract, value, configuration, max }, bre) => { console.log('======== START MODIFY CONTRACT CAP ==========') - const filePath = `../../deployments/${bre.network.name}.json` - if (!configurator) { - const json = require(filePath) - configurator = json.ConfigurationManager + if (!configuration) { + const deployment = getDeployments() + configuration = deployment.ConfigurationManager } - if (!ethers.utils.isAddress(contract)) { - throw new Error(`\`address\` is not an address. Received: ${configurator}`) - } + validateAddress(configuration, 'configuration') - const configurationManager = await ethers.getContractAt('ConfigurationManager', configurator) - const capProviderAddress = await configurationManager.getCapProvider() - const capContract = await ethers.getContractAt('CapProvider', capProviderAddress) + const configurationManager = await ethers.getContractAt('ConfigurationManager', configuration) + const capContract = await ethers.getContractAt('CapProvider', await configurationManager.getCapProvider()) const valueToSend = max ? 0 : value const tx = await capContract.setCap(contract, valueToSend) diff --git a/tasks/configuration/inspectConfigurationManager.js b/tasks/configuration/inspectConfigurationManager.js index c5c8a487..2bf6a365 100644 --- a/tasks/configuration/inspectConfigurationManager.js +++ b/tasks/configuration/inspectConfigurationManager.js @@ -1,16 +1,15 @@ +const { getDeployments } = require('../utils/deployment') +const validateAddress = require('../utils/validateAddress') + task('inspectConfigurationManager', 'Checks the contracts associated with a ConfigurationManager instance') .addOptionalPositionalParam('address', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') - .setAction(async ({ address }, bre) => { - const filePath = `../../deployments/${bre.network.name}.json` - + .setAction(async ({ address }, hre) => { if (!address) { - const json = require(filePath) - address = json.ConfigurationManager + const deployment = getDeployments() + address = deployment.ConfigurationManager } - if (!ethers.utils.isAddress(address)) { - throw new Error(`\`address\` is not an address. Received: ${address}`) - } + validateAddress(address, 'address') const configurationManager = await ethers.getContractAt('ConfigurationManager', address) diff --git a/tasks/configuration/linkConfigurationManager.js b/tasks/configuration/linkConfigurationManager.js index 5471574c..2015b05c 100644 --- a/tasks/configuration/linkConfigurationManager.js +++ b/tasks/configuration/linkConfigurationManager.js @@ -1,22 +1,18 @@ +const { getDeployments } = require('../utils/deployment') +const validateAddress = require('../utils/validateAddress') + task('linkConfigurationManager', 'Link a contract with a ConfigurationManager') .addOptionalParam('address', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') .addPositionalParam('setter', 'The setter to interact with') .addPositionalParam('newContract', 'The new contract address to set') .setAction(async ({ address, setter, newContract }, bre) => { - const filePath = `../../deployments/${bre.network.name}.json` - if (!address) { - const json = require(filePath) - address = json.ConfigurationManager + const deployment = getDeployments() + address = deployment.ConfigurationManager } - if (!ethers.utils.isAddress(address)) { - throw new Error(`\`address\` is not an address. Received: ${address}`) - } - - if (!ethers.utils.isAddress(newContract)) { - throw new Error(`\`newContract\` is not an address. Received: ${newContract}`) - } + validateAddress(address, 'address') + validateAddress(newContract, 'newContract') const configurationManager = await ethers.getContractAt('ConfigurationManager', address) diff --git a/tasks/configuration/setParameter.js b/tasks/configuration/setParameter.js index 0f519c9a..1ca5ad45 100644 --- a/tasks/configuration/setParameter.js +++ b/tasks/configuration/setParameter.js @@ -1,21 +1,20 @@ +const { getDeployments } = require('../utils/deployment') +const validateAddress = require('../utils/validateAddress') + task('setParameter', 'Set a ConfigurationManager parameter') .addPositionalParam('parameter', 'Parameter name') .addPositionalParam('value', 'New value') - .addOptionalParam('configurator', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') + .addOptionalParam('configuration', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') .addFlag('noUpdate', 'Specifies if the param change should trigger update on dependent contract, defaults to true') - .setAction(async ({ configurator, parameter, value, noUpdate }, bre) => { - const filePath = `../../deployments/${bre.network.name}.json` - - if (!configurator) { - const json = require(filePath) - configurator = json.configurationManager + .setAction(async ({ configuration, parameter, value, noUpdate }, bre) => { + if (!configuration) { + const deployment = getDeployments() + configuration = deployment.ConfigurationManager } - if (!ethers.utils.isAddress(configurator)) { - throw new Error(`\`configurator\` is not an address. Received: ${configurator}`) - } + validateAddress(configuration, 'configuration') - const configurationManager = await ethers.getContractAt('ConfigurationManager', configurator) + const configurationManager = await ethers.getContractAt('ConfigurationManager', configuration) const parameterName = ethers.utils.formatBytes32String(parameter) const parameterValue = ethers.BigNumber.from(value) diff --git a/tasks/deployOptionHelper.js b/tasks/deployOptionHelper.js index 74895888..1c86a055 100644 --- a/tasks/deployOptionHelper.js +++ b/tasks/deployOptionHelper.js @@ -1,21 +1,23 @@ -const saveJSON = require('./utils/saveJSON') -const verifyContract = require('./utils/verify') +const { getDeployments } = require('./utils/deployment') +const validateAddress = require('./utils/validateAddress') task('deployOptionHelper', 'Deploy new option helper using provider') - .addParam('configuration', 'Address of the factory to pass to initialize') + .addOptionalParam('configuration', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') .addFlag('verify', 'if true, it should verify the contract after the deployment') .setAction(async ({ configuration, verify }, hre) => { - console.log('----Start Deploy OptionHelper----') - const path = `../../deployments/${hre.network.name}.json` - const OptionHelper = await ethers.getContractFactory('OptionHelper') - const optionHelper = await OptionHelper.deploy(configuration) - console.log('Option Helper Address: ', optionHelper.address) + if (!configuration) { + const deployment = getDeployments() + configuration = deployment.ConfigurationManager + } - await saveJSON(path, { optionHelper: optionHelper.address }) + validateAddress(configuration, 'configuration') - if (verify) { - await verifyContract(hre, optionHelper.address, [configuration]) - } + const address = await hre.run('deploy', { + name: 'OptionHelper', + args: [configuration], + verify, + save: true + }) - return optionHelper.address + return address }) diff --git a/tasks/deployWeek.js b/tasks/deployWeek.js index 371d7cb7..0e3e8da9 100644 --- a/tasks/deployWeek.js +++ b/tasks/deployWeek.js @@ -1,3 +1,4 @@ +const parseDuration = require('parse-duration') const getTimestamp = require('../test/util/getTimestamp') const fs = require('fs') const path = require('path') @@ -10,73 +11,66 @@ task('deployWeek', 'Deploy a whole local test environment') .addFlag('ivprovider', 'if true, it should add the option to the ivprovider') .setAction(async ({ start, verify, ivprovider, tenderly }, hre) => { const pathFile = `../deployments/${hre.network.name}.json` - // 4) Deploy Test Option const currentBlockTimestamp = await getTimestamp() const defaultInitialIV = '1750000000000000000' const _filePath = path.join(__dirname, pathFile) const content = await fsPromises.readFile(_filePath) const contentJSON = JSON.parse(content) - const cfgManagerAddress = contentJSON.ConfigurationManager const deployedOptions = [] - const options = [ { strike: 'USDC', underlying: 'WETH', - price: '2400' + price: '2400', + expiresIn: '7d' } ] - const intervals = [7] - const oneDayInSeconds = 24 * 60 * 60 + for (const option of options) { + const expiration = currentBlockTimestamp + (parseDuration(option.expiresIn) / 1000) - for (const optionObj of options) { - for (const interval of intervals) { - const optionAddress = await run('deployNewOption', { - strike: optionObj.strike, - underlying: optionObj.underlying, - price: optionObj.price, - expiration: (currentBlockTimestamp + oneDayInSeconds * interval).toString(), - cap: '1000000000', - verify, - tenderly - }) - const tokenbAddress = contentJSON[optionObj.strike] - deployedOptions.push(optionAddress) + const optionAddress = await hre.run('deployNewOption', { + strike: option.strike, + underlying: option.underlying, + price: option.price, + expiration: expiration.toString(), + cap: '1000000000', + verify, + tenderly + }) - if (ivprovider) { - const configurationManager = await ethers.getContractAt('ConfigurationManager', cfgManagerAddress) - const ivProviderAddress = await configurationManager.getIVProvider() - const ivProvider = await ethers.getContractAt('IVProvider', ivProviderAddress) - const tx = await ivProvider.updateIV(optionAddress, defaultInitialIV, '18') - await tx.wait(2) - } + const tokenbAddress = contentJSON[option.strike] + deployedOptions.push(optionAddress) - // 5) Create AMMPool test with this asset - const poolAddress = await run('deployNewOptionAMMPool', { - option: optionAddress, - tokenb: tokenbAddress, - initialiv: defaultInitialIV, - cap: '10000000000000000', - verify, - tenderly - }) + if (ivprovider) { + const configurationManager = await ethers.getContractAt('ConfigurationManager', contentJSON.ConfigurationManager) + const ivProviderAddress = await configurationManager.getIVProvider() + const ivProvider = await ethers.getContractAt('IVProvider', ivProviderAddress) + const tx = await ivProvider.updateIV(optionAddress, defaultInitialIV, '18') + await tx.wait(2) + } + + const poolAddress = await hre.run('deployNewOptionAMMPool', { + option: optionAddress, + tokenb: tokenbAddress, + initialiv: defaultInitialIV, + cap: '10000000000000000', + verify, + tenderly + }) - console.log('start Flag: ', start) + console.log('Provide initial liquidity: ', start) - if (start) { - // 7) Mint Options - await run('mintOptions', { option: optionAddress, amount: '5' }) + if (start) { + await hre.run('mintOptions', { option: optionAddress, amount: '5' }) - // 8) Add Liquidity - await run('addLiquidityAMM', { - pooladdress: poolAddress, - amounta: '5', - amountb: '10000' - }) - } + await hre.run('addLiquidityAMM', { + pooladdress: poolAddress, + amounta: '5', + amountb: '10000' + }) } } console.log('deployedOptions:') diff --git a/tasks/index.js b/tasks/index.js index fb23c22f..cd274ef3 100644 --- a/tasks/index.js +++ b/tasks/index.js @@ -1,3 +1,10 @@ +require('./utils/index') +require('./amm/index') +require('./configuration/index') +require('./option/index') +require('./local/index') +require('./oracle/index') + require('./exportABI') require('./deployWeek') require('./deployOptionHelper') diff --git a/tasks/local/deployERC20.js b/tasks/local/deployERC20.js index 0a5b04b2..dde00ad0 100644 --- a/tasks/local/deployERC20.js +++ b/tasks/local/deployERC20.js @@ -3,16 +3,34 @@ internalTask('deployToken', 'Deploy a whole local test environment') .addOptionalParam('symbol', 'token symbol') .addOptionalParam('decimals', 'token decimals') .addFlag('weth', 'if the token is WETH') - .setAction(async ({ name = 'Token', symbol = 'TKN', decimals = 18, weth }, bre) => { - // 1) Setup fake assets - const mockERC20 = await ethers.getContractFactory('MintableERC20') - const mockWETH = await ethers.getContractFactory('WETH') + .addFlag('verify', 'if true, it should verify the contract after the deployment') + .addFlag('save', 'if true, it should save the contract address inside the deployments folder') + .setAction(async ({ + name = 'Token', + symbol = 'TKN', + decimals = 18, + weth, + save, + verify + }, + hre + ) => { let tokenAddress if (weth) { - tokenAddress = await mockWETH.deploy() + tokenAddress = await hre.run('deploy', { + name: 'WETH', + save, + verify + }) } else { - tokenAddress = await mockERC20.deploy(name, symbol, decimals) + tokenAddress = await hre.run('deploy', { + name: 'MintableERC20', + args: [name, symbol, decimals], + save, + verify + }) } + return tokenAddress }) diff --git a/tasks/local/setupLocal.js b/tasks/local/setupLocal.js index 8cb07529..74257b44 100644 --- a/tasks/local/setupLocal.js +++ b/tasks/local/setupLocal.js @@ -5,65 +5,58 @@ const pathJoin = require('path') const fsPromises = fs.promises task('setupLocal', 'Deploy a whole local test environment') - .setAction(async ({}, bre) => { - const path = `../../deployments/${bre.network.name}.json` + .setAction(async ({}, hre) => { + const path = `../../deployments/${hre.network.name}.json` // Erasing local.json file await saveJSON(path, '', true) - // 1) Setup mock assets - const mockWETH = await run('deployToken', { name: 'weth', symbol: 'weth', decimals: '18', weth: true }) - - const mockUSDC = await run('deployToken', { name: 'USDC Token', symbol: 'USDC', decimals: '6' }) - - const mockAUSDC = await run('deployToken', { name: 'AUSDC Token', symbol: 'AUSDC', decimals: '6' }) - - const mockDAI = await run('deployToken', { name: 'DAI Token', symbol: 'DAI', decimals: '18' }) - - const mockWBTC = await run('deployToken', { name: 'Wrappeed BTC', symbol: 'WBTC', decimals: '8' }) - - const mockLINK = await run('deployToken', { name: 'LINK Address', symbol: 'LINK', decimals: '18' }) - - const tokensObj = { - WETH: mockWETH.address, - USDC: mockUSDC.address, - AUSDC: mockAUSDC.address, - DAI: mockDAI.address, - WBTC: mockWBTC.address, - LINK: mockLINK.address - + const deployedTokens = {} + const tokenList = [ + { name: 'Wrapped Ether', symbol: 'WETH', decimals: '18', weth: true }, + { name: 'USD Coin', symbol: 'USDC', decimals: '6' }, + { name: 'Aave Interest bearing USDC', symbol: 'aUSDC', decimals: '6' }, + { name: 'Dai Stablecoin', symbol: 'DAI', decimals: '18' }, + { name: 'Wrapped BTC', symbol: 'WBTC', decimals: '8' }, + { name: 'ChainLink Token', symbol: 'LINK', decimals: '18' } + ] + + for (const tokenObj of tokenList) { + const tokenAddress = await run('deployToken', tokenObj) + deployedTokens[tokenObj.symbol.toUpperCase()] = tokenAddress } - await saveJSON(path, tokensObj) - const configurationManagerAddress = await run('deployConfigurationManager') + await saveJSON(path, deployedTokens) + + const configurationManagerAddress = await hre.run('deployConfigurationManager') // 2) Setup Chainlink (Oracle) Mock - const ChainlinkWBTCFeed = await ethers.getContractFactory('MockChainlinkFeed') + const ChainlinkFeed = await ethers.getContractFactory('MockChainlinkFeed') - const chainlinkWBTCFeed = await ChainlinkWBTCFeed.deploy(mockWBTC.address, '8', '37170000000000') - const chainlinkWETHFeed = await ChainlinkWBTCFeed.deploy(mockWETH.address, '8', '1270000000000') - const chainlinkLINKFeed = await ChainlinkWBTCFeed.deploy(mockLINK.address, '8', '2496201073') + const chainlinkWBTCFeed = await ChainlinkFeed.deploy(deployedTokens.WBTC, '8', '37170000000000') + const chainlinkWETHFeed = await ChainlinkFeed.deploy(deployedTokens.WETH, '8', '1270000000000') + const chainlinkLINKFeed = await ChainlinkFeed.deploy(deployedTokens.LINK, '8', '2496201073') await saveJSON(path, { wbtcChainlinkFeed: chainlinkWBTCFeed.address }) // 3.2) Deploy BS + IV + AMMPoolFactory + Oracles - await run('setAMMEnvironment', { asset: mockWBTC.address, source: chainlinkWBTCFeed.address, configuration: configurationManagerAddress, builders: true }) + await run('setAMMEnvironment', { asset: deployedTokens.WBTC, source: chainlinkWBTCFeed.address, configuration: configurationManagerAddress, builders: true }) // 3.3) Deploy Option Exchange const _filePath = pathJoin.join(__dirname, path) const content = await fsPromises.readFile(_filePath) - // Set WETH price Provider - const priceProvider = await ethers.getContractAt('PriceProvider', JSON.parse(content).PriceProvider) + const configurationManager = await ethers.getContractAt('ConfigurationManager', configurationManagerAddress) - await priceProvider.setAssetFeeds([mockWETH.address], [chainlinkWETHFeed.address]) - await priceProvider.setAssetFeeds([mockLINK.address], [chainlinkLINKFeed.address]) + // Set WETH price Provider + const priceProvider = await ethers.getContractAt('PriceProvider', await configurationManager.getPriceProvider()) - const optionAMMFactory = JSON.parse(content).OptionAMMFactory + await priceProvider.setAssetFeeds([deployedTokens.WETH], [chainlinkWETHFeed.address]) + await priceProvider.setAssetFeeds([deployedTokens.LINK], [chainlinkLINKFeed.address]) // 4) Deploy Test Option const currentBlockTimestamp = await getTimestamp() - const optionWBTCAddress = await run('deployNewOption', { + const optionWBTCAddress = await hre.run('deployNewOption', { strike: 'USDC', underlying: 'WBTC', price: '18000', @@ -71,7 +64,7 @@ task('setupLocal', 'Deploy a whole local test environment') cap: '2000' }) - const optionWETHAddress = await run('deployNewOption', { + const optionWETHAddress = await hre.run('deployNewOption', { strike: 'USDC', underlying: 'WETH', price: '1500', @@ -79,7 +72,7 @@ task('setupLocal', 'Deploy a whole local test environment') cap: '2000' }) - const optionLINKAddress = await run('deployNewOption', { + const optionLINKAddress = await hre.run('deployNewOption', { strike: 'USDC', underlying: 'LINK', price: '25', @@ -88,36 +81,37 @@ task('setupLocal', 'Deploy a whole local test environment') }) // 5) Create AMMPool test with this asset - const optionAMMPoolAddress = await run('deployNewOptionAMMPool', { + const optionAMMPoolAddress = await hre.run('deployNewOptionAMMPool', { option: optionWBTCAddress, - tokenb: mockUSDC.address, + tokenb: deployedTokens.USDC, initialiv: '770000000000000000', // 0.77% cap: '500000' }) - const optionAMMETHPoolAddress = await run('deployNewOptionAMMPool', { + const optionAMMETHPoolAddress = await hre.run('deployNewOptionAMMPool', { option: optionWETHAddress, - tokenb: mockUSDC.address, + tokenb: deployedTokens.USDC, initialiv: '2000000000000000000', cap: '500000' }) - const optionLINKPoolAddress = await run('deployNewOptionAMMPool', { + const optionLINKPoolAddress = await hre.run('deployNewOptionAMMPool', { option: optionLINKAddress, - tokenb: mockUSDC.address, + tokenb: deployedTokens.USDC, initialiv: '2311200000000000000', cap: '500000' }) // 6) Mint Strike Asset console.log('Minting USDC strike asset') + const mockUSDC = await ethers.getContractAt('MintableERC20', deployedTokens.USDC) await mockUSDC.mint('10000000000000000') - // 7) Mint Options - await run('mintOptions', { option: optionLINKAddress, amount: '600' }) + // // 7) Mint Options + await hre.run('mintOptions', { option: optionLINKAddress, amount: '600' }) // 8) Add Liquidity - await run('addLiquidityAMM', { + await hre.run('addLiquidityAMM', { pooladdress: optionLINKPoolAddress, amounta: '500', amountb: '11000' diff --git a/tasks/option/deployOptionBuilder.js b/tasks/option/deployOptionBuilder.js new file mode 100644 index 00000000..8e4e572c --- /dev/null +++ b/tasks/option/deployOptionBuilder.js @@ -0,0 +1,21 @@ +internalTask('deployOptionBuilder', 'Deploy OptionBuilder') + .addParam('optiontype', 'Eg: PodPut, WPodPut, PodCall, WPodCall') + .addFlag('save', 'if true, it should save the contract address inside the deployments folder') + .addFlag('verify', 'if true, it should verify the contract after the deployment') + .setAction(async ({ optiontype, save, verify }, hre) => { + switch (optiontype) { + case 'PodPut': + case 'WPodPut': + case 'PodCall': + case 'WPodCall': + const contractName = optiontype + 'Builder' + + return await hre.run('deploy', { + name: contractName, + save, + verify + }) + default: + throw new Error('Builder not found! Available Builders: PodPut, WPodPut, PodCall, WPodCall') + } + }) diff --git a/tasks/option/deployOptionFactory.js b/tasks/option/deployOptionFactory.js index af99484f..4f3e2fbc 100644 --- a/tasks/option/deployOptionFactory.js +++ b/tasks/option/deployOptionFactory.js @@ -1,8 +1,5 @@ -const saveJSON = require('../utils/saveJSON') -const fs = require('fs') -const pathJoin = require('path') -const fsPromises = fs.promises -const verifyContract = require('../utils/verify') +const { getDeployments } = require('../utils/deployment') +const validateAddress = require('../utils/validateAddress') task('deployOptionFactory', 'Deploy OptionFactory') .addFlag('builders', 'true if want to deploy all builders combined') @@ -13,53 +10,36 @@ task('deployOptionFactory', 'Deploy OptionFactory') .addOptionalParam('podcallbuilder', 'podcallbuilder contract address') .addOptionalParam('wpodcallbuilder', 'wpodcallbuilder contract address') .addOptionalParam('wethadapt', 'alternative weth address in case of other networks') - .setAction(async ({ podputbuilder, wpodputbuilder, podcallbuilder, wpodcallbuilder, configuration, builders, wethadapt, verify }, hre) => { - const path = `../../deployments/${hre.network.name}.json` - const _filePath = pathJoin.join(__dirname, path) - const content = await fsPromises.readFile(_filePath) - const wethAddress = wethadapt || JSON.parse(content).WETH - const configurationManager = configuration || JSON.parse(content).ConfigurationManager + const deployment = getDeployments() + const wethAddress = wethadapt || deployment.WETH - if (!configurationManager) { - throw Error('Configuration Manager not found') + if (!configuration) { + configuration = deployment.ConfigurationManager } - if (builders) { - podputbuilder = await run('deployBuilder', { optiontype: 'PodPut' }) - wpodputbuilder = await run('deployBuilder', { optiontype: 'WPodPut' }) - podcallbuilder = await run('deployBuilder', { optiontype: 'PodCall' }) - wpodcallbuilder = await run('deployBuilder', { optiontype: 'WPodCall' }) - } - - const OptionFactory = await ethers.getContractFactory('OptionFactory') - - const constructorElements = [ - wethAddress, - podputbuilder, - wpodputbuilder, - podcallbuilder, - wpodcallbuilder, - configurationManager - ] + validateAddress(configuration, 'configuration') - const factory = await OptionFactory.deploy(...constructorElements) - - await factory.deployed() - - await saveJSON(path, { OptionFactory: factory.address }) - - if (verify) { - await verifyContract(hre, factory.address, constructorElements) - - if (builders) { - await verifyContract(hre, podputbuilder) - await verifyContract(hre, wpodputbuilder) - await verifyContract(hre, podcallbuilder) - await verifyContract(hre, wpodcallbuilder) - } + if (builders) { + podputbuilder = await hre.run('deployOptionBuilder', { optiontype: 'PodPut', save: true, verify }) + wpodputbuilder = await hre.run('deployOptionBuilder', { optiontype: 'WPodPut', save: true, verify }) + podcallbuilder = await hre.run('deployOptionBuilder', { optiontype: 'PodCall', save: true, verify }) + wpodcallbuilder = await hre.run('deployOptionBuilder', { optiontype: 'WPodCall', save: true, verify }) } - console.log('OptionFactory deployed to: ', factory.address) - return factory.address + const factoryAddress = await hre.run('deploy', { + name: 'OptionFactory', + args: [ + wethAddress, + podputbuilder, + wpodputbuilder, + podcallbuilder, + wpodcallbuilder, + configuration + ], + save: true, + verify + }) + + return factoryAddress }) diff --git a/tasks/option/deployOptionsBuilders.js b/tasks/option/deployOptionsBuilders.js deleted file mode 100644 index ac7cffc7..00000000 --- a/tasks/option/deployOptionsBuilders.js +++ /dev/null @@ -1,21 +0,0 @@ - -const saveJSON = require('../utils/saveJSON') - -internalTask('deployBuilder', 'Deploy OptionFactory or aOptionFactory') - .addParam('optiontype', 'Eg: PodPut, WPodPut, PodCall, WPodCall') - .setAction(async ({ optiontype }, bre) => { - const path = `../../deployments/${bre.network.name}.json` - console.log(`====== Start ${optiontype} Builder deploy ======`) - - const contractName = optiontype + 'Builder' - const OptionBuilder = await ethers.getContractFactory(contractName) - const builder = await OptionBuilder.deploy() - - await builder.deployed() - - console.log(`${contractName} deployed to:`, builder.address) - - await saveJSON(path, { [contractName]: builder.address }) - - return builder.address - }) diff --git a/tasks/option/index.js b/tasks/option/index.js index e1fa87ee..af1d30e3 100644 --- a/tasks/option/index.js +++ b/tasks/option/index.js @@ -1,4 +1,4 @@ -require('./deployOptionsBuilders') +require('./deployOptionBuilder') require('./mintOptions') require('./deployNewOption') require('./deployOptionFactory') diff --git a/tasks/oracle/deployChainlink.js b/tasks/oracle/deployChainlink.js index 7bbdf93b..202b9847 100644 --- a/tasks/oracle/deployChainlink.js +++ b/tasks/oracle/deployChainlink.js @@ -1,13 +1,17 @@ +const validateAddress = require('../utils/validateAddress') + task('deployChainlink', 'Deploy Chainlink Contract') .addParam('source', 'address of chainlink pricefeed') - .setAction(async ({ source }) => { - const numberOfConfirmations = hre.network.name === 'local' ? 1 : 2 + .addFlag('save', 'if true, it should save the contract address inside the deployments folder') + .addFlag('verify', 'if true, it should verify the contract after the deployment') + .setAction(async ({ source, save }, hre) => { + validateAddress(source, 'source') - console.log('----Start Deploy Chainlink----') - const Chainlink = await ethers.getContractFactory('ChainlinkPriceFeed') - const chainlink = await Chainlink.deploy(source) - await chainlink.deployTransaction.wait(numberOfConfirmations) + const address = await hre.run('deploy', { + name: 'ChainlinkPriceFeed', + args: [source], + save + }) - console.log('Chainlink', chainlink.address) - return chainlink.address + return address }) diff --git a/tasks/oracle/deployIVProvider.js b/tasks/oracle/deployIVProvider.js index 8aef85d7..a64564ce 100644 --- a/tasks/oracle/deployIVProvider.js +++ b/tasks/oracle/deployIVProvider.js @@ -1,27 +1,19 @@ -const verifyContract = require('../utils/verify') -const saveJSON = require('../utils/saveJSON') - task('deployIVProvider', 'Deploy Implied Volatility Contract') .addOptionalParam('updater', 'updater role address') .addFlag('verify', 'if true, it should verify the contract after the deployment') - .setAction(async ({ updater, verify }) => { - console.log('Deploying IVProvider') - const numberOfConfirmations = hre.network.name === 'local' ? 1 : 2 + .setAction(async ({ updater, verify }, hre) => { + const address = await hre.run('deploy', { + name: 'IVProvider', + verify, + save: true + }) - const IVProvider = await ethers.getContractFactory('IVProvider') - const provider = await IVProvider.deploy() - await provider.deployTransaction.wait(numberOfConfirmations) + const numberOfConfirmations = hre.network.name === 'local' ? 1 : 2 + const provider = await ethers.getContractAt('IVProvider', address) if (ethers.utils.isAddress(updater)) { await provider.setUpdater(updater).wait(numberOfConfirmations) } - if (verify) { - await verifyContract(hre, provider.address) - } - - await saveJSON(`../../deployments/${hre.network.name}.json`, { IVProvider: provider.address }) - - console.log(`IVProvider: ${provider.address}`) return provider.address }) diff --git a/tasks/oracle/deployOracle.js b/tasks/oracle/deployOracle.js index 048ba76c..4e715575 100644 --- a/tasks/oracle/deployOracle.js +++ b/tasks/oracle/deployOracle.js @@ -1,24 +1,31 @@ -const saveJSON = require('../utils/saveJSON') -const verifyContract = require('../utils/verify') +const { getDeployments } = require('../utils/deployment') +const validateAddress = require('../utils/validateAddress') task('deployOracle', 'Deploy full Oracle (Chainlink + PriceFeed)') - .addFlag('verify', 'if true, it should verify the contract after the deployment') .addParam('asset', 'address of initial asset of the feed (WETH: 0xD7FDf2747A855AC20b96A5cEDeA84b2138cEd280') .addParam('source', 'address of the asset price feed (Chainlink WETH/USD: ') - .addParam('configuration', 'address of the configurtion manager') + .addOptionalParam('configuration', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') + .addFlag('verify', 'if true, it should verify the contract after the deployment') .setAction(async ({ source, asset, configuration, verify }, hre) => { - console.log('----Start Deploy Oracle----') - const path = `../../deployments/${hre.network.name}.json` - const chainlinkAddress = await run('deployChainlink', { source }) - const priceProviderAddress = await run('deployPriceProvider', { configuration, asset, feed: chainlinkAddress }) + if (!configuration) { + const deployment = getDeployments() + configuration = deployment.ConfigurationManager + } - await saveJSON(path, { ChainlinkPriceFeed: chainlinkAddress, PriceProvider: priceProviderAddress }) + validateAddress(configuration, 'configuration') - if (verify) { - await verifyContract(hre, chainlinkAddress, [source]) - await verifyContract(hre, priceProviderAddress, [configuration, [asset], [chainlinkAddress]]) - } + const chainlinkAddress = await hre.run('deployChainlink', { + source, + verify + }) + + const priceProviderAddress = await hre.run('deployPriceProvider', { + configuration, + asset, + feed: chainlinkAddress, + save: true, + verify + }) - console.log('----End Deploy Oracle----') return priceProviderAddress }) diff --git a/tasks/oracle/deployPriceProvider.js b/tasks/oracle/deployPriceProvider.js index 67aa3ec3..e9ce0760 100644 --- a/tasks/oracle/deployPriceProvider.js +++ b/tasks/oracle/deployPriceProvider.js @@ -1,39 +1,34 @@ -const fs = require('fs') -const pathJoin = require('path') -const fsPromises = fs.promises +const { getDeployments } = require('../utils/deployment') +const validateAddress = require('../utils/validateAddress') task('deployPriceProvider', 'Deploy PriceProvider Contract') .addOptionalParam('asset', 'address of asset') .addOptionalParam('feed', 'address of priceFeed asset') .addOptionalParam('configuration', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') - .setAction(async ({ asset, feed, configuration }) => { - console.log('----Start Deploy PriceProvider----') - const path = `../../deployments/${hre.network.name}.json` - const _filePath = pathJoin.join(__dirname, path) - const content = await fsPromises.readFile(_filePath) - const configurationManagerAddress = configuration || JSON.parse(content).ConfigurationManager - let assetArray = [] - let feedArray = [] - - if (asset && feed) { - assetArray = [asset] - feedArray = [feed] + .addFlag('verify', 'if true, it should verify the contract after the deployment') + .addFlag('save', 'if true, it should save the contract address inside the deployments folder') + .setAction(async ({ asset, feed, configuration, verify, save }, hre) => { + if (!configuration) { + const deployment = getDeployments() + configuration = deployment.ConfigurationManager } - // const configurationManager = await ethers.getContractAt('ConfigurationManager', configurationManagerAddress) - // const parameterName = ethers.utils.formatBytes32String('MIN_UPDATE_INTERVAL') + validateAddress(configuration, 'configuration') - // const tx = await configurationManager.setParameter(parameterName, '17280000') - // tx.wait(2) + let assets = [] + let feeds = [] - if (!configurationManagerAddress) { - throw Error('Configuration Manager not found') + if (asset && feed) { + assets = [asset] + feeds = [feed] } - const PriceProvider = await ethers.getContractFactory('PriceProvider') - const priceProvider = await PriceProvider.deploy(configurationManagerAddress, assetArray, feedArray) + const address = await hre.run('deploy', { + name: 'PriceProvider', + args: [configuration, assets, feeds], + verify, + save + }) - await priceProvider.deployed(2) - console.log('PriceProvider Address', priceProvider.address) - return priceProvider.address + return address }) diff --git a/tasks/oracle/setIVUpdater.js b/tasks/oracle/setIVUpdater.js index aedc7fd1..d75884a4 100644 --- a/tasks/oracle/setIVUpdater.js +++ b/tasks/oracle/setIVUpdater.js @@ -1,23 +1,19 @@ +const { getDeployments } = require('../utils/deployment') +const validateAddress = require('../utils/validateAddress') + task('setIVUpdater', 'Set a ConfigurationManager parameter') .addPositionalParam('updater', 'updater role address') - .addOptionalParam('configurator', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') - .setAction(async ({ configurator, updater }, bre) => { - const filePath = `../../deployments/${bre.network.name}.json` - - if (!configurator) { - const json = require(filePath) - configurator = json.ConfigurationManager + .addOptionalParam('configuration', 'An address of a deployed ConfigurationManager, defaults to current `deployments` json file') + .setAction(async ({ configuration, updater }, bre) => { + if (!configuration) { + const deployment = getDeployments() + configuration = deployment.ConfigurationManager } - if (!ethers.utils.isAddress(configurator)) { - throw new Error(`\`configurator\` is not an address. Received: ${configurator}`) - } - - if (!ethers.utils.isAddress(updater)) { - throw new Error(`\`updater\` is not an address. Received: ${updater}`) - } + validateAddress(configuration, 'configuration') + validateAddress(updater, 'updater') - const configurationManager = await ethers.getContractAt('ConfigurationManager', configurator) + const configurationManager = await ethers.getContractAt('ConfigurationManager', configuration) const ivProviderAddress = await configurationManager.getIVProvider() const ivProvider = await ethers.getContractAt('IVProvider', ivProviderAddress) diff --git a/tasks/oracle/setNewFeed.js b/tasks/oracle/setNewFeed.js index 67c425eb..9efb8a11 100644 --- a/tasks/oracle/setNewFeed.js +++ b/tasks/oracle/setNewFeed.js @@ -1,27 +1,19 @@ -const saveJSON = require('../utils/saveJSON') - -const fs = require('fs') -const pathJoin = require('path') -const fsPromises = fs.promises +const { getDeployments } = require('../utils/deployment') task('setNewFeed', 'Deploy Chainlink w/ source + set source and asset to price provider') .addParam('asset', 'name of the asset (e.g: WETH / WBTC / DAI)') .addParam('source', 'address of the asset price feed (Chainlink WETH/USD: ') .setAction(async ({ source, asset }, hre) => { console.log('----Start Deploying new Chainlink Price Feed and Adding to PriceProvider----') - const path = `../../deployments/${hre.network.name}.json` const numberOfConfirmations = hre.network.name === 'local' ? 1 : 2 + const deployments = getDeployments() const assetUpper = asset.toUpperCase() - const _filePath = pathJoin.join(__dirname, path) - const content = await fsPromises.readFile(_filePath) - const contentJSON = JSON.parse(content) - - const assetAddress = contentJSON[assetUpper] - const priceProviderAddress = contentJSON.PriceProvider + const assetAddress = deployments[assetUpper] + const priceProviderAddress = deployments.PriceProvider - const chainlinkFeedAddress = await run('deployChainlink', { source }) + const chainlinkFeedAddress = await hre.run('deployChainlink', { source }) console.log('Setting feed to Price Provider') const priceProvider = await ethers.getContractAt('PriceProvider', priceProviderAddress) diff --git a/tasks/utils/deploy.js b/tasks/utils/deploy.js index ca4f0bc8..3b4c6924 100644 --- a/tasks/utils/deploy.js +++ b/tasks/utils/deploy.js @@ -1,29 +1,35 @@ +const { types } = require('hardhat/config') const verifyContract = require('../utils/verify') -const saveJSON = require('../utils/saveJSON') +const { saveDeployments } = require('../utils/deployment') task('deploy', 'Deploy a generic contract given artifact name') .addParam('name', 'name of the contract artifact') + .addOptionalParam('args', 'arguments passed to constructor', [], types.json) .addFlag('verify', 'if true, it should verify the contract after the deployment') .addFlag('save', 'if true, it should save the contract address inside the deployments folder') - .setAction(async ({ name, verify, save }) => { - console.log('----Start Deploy Contract----') + .setAction(async ({ name, args = [], verify, save }, hre) => { + console.log(`\nDeploying ${name}`) + if (args.length) { + if (typeof args === 'string') { + args = args.split(',') + } + console.log(`With args: `, args) + } const numberOfConfirmations = hre.network.name === 'local' ? 1 : 2 const Contract = await ethers.getContractFactory(name) - const contract = await Contract.deploy() + const contract = await Contract.deploy(...args) await contract.deployTransaction.wait(numberOfConfirmations) - console.log(`${name} Address: ${contract.address}`) + console.log(`Deployed ${name}: ${contract.address}`) if (verify) { - await verifyContract(hre, contract.address) + await verifyContract(hre, contract.address, args) } if (save) { - const saveObj = { + await saveDeployments({ [name]: contract.address - } - - await saveJSON(`../../deployments/${hre.network.name}.json`, saveObj) + }) } return contract.address diff --git a/tasks/utils/deployment.js b/tasks/utils/deployment.js new file mode 100644 index 00000000..14064fc2 --- /dev/null +++ b/tasks/utils/deployment.js @@ -0,0 +1,72 @@ +const path = require('path') +const fs = require('fs') + +/** + * Get addresses from a deployment file + * @param {string} [network] Specify a network file. Defaults to hardhat current network + */ +module.exports.getDeployments = function getDeployments (network) { + let filePath, deployment + + if (!network) { + const hardhat = require('hardhat') + network = hardhat.network.name + } + + try { + filePath = path.join(__dirname, `../../deployments/${network}.json`) + deployment = require(filePath) + } catch (e) { + console.error(`Deployment file not found! Received: ${network}`) + process.exit(1) + } + + return deployment +} + +/** + * Saves the contracts in a deployment file + * @param {Object} contracts Hashmap of contracts to save + * @param {string} [network] Specify a network file. Defaults to hardhat current network + */ +module.exports.saveDeployments = async function saveDeployments (contracts, network) { + let filePath, deployment + + if (!network) { + const hardhat = require('hardhat') + network = hardhat.network.name + } + + try { + filePath = path.join(__dirname, `../../deployments/${network}.json`) + deployment = require(filePath) + } catch (e) { + console.error(`Deployment file not found! Received: ${network}`) + process.exit(1) + } + + const updated = Object.assign(deployment, contracts) + fs.writeFileSync(filePath, JSON.stringify(updated, null, 2)) +} + +/** + * Clear all contracts in a deployment file + * @param {string} [network] Specify a network file. Defaults to hardhat current network + */ +module.exports.clearDeployments = async function clearDeployments (network) { + let filePath + + if (!network) { + const hardhat = require('hardhat') + network = hardhat.network.name + } + + try { + filePath = path.join(__dirname, `../../deployments/${network}.json`) + } catch (e) { + console.error(`Deployment file not found! Received: ${network}`) + process.exit(1) + } + + fs.writeFileSync(filePath, JSON.stringify({}, null, 2)) +} diff --git a/tasks/utils/validateAddress.js b/tasks/utils/validateAddress.js new file mode 100644 index 00000000..558a5c51 --- /dev/null +++ b/tasks/utils/validateAddress.js @@ -0,0 +1,10 @@ +/** + * Validate addresses and throw error script otherwise + * @param {string} address + * @param {string} [name] + */ +module.exports = function validateAddress (address, name = 'address') { + if (!ethers.utils.isAddress(address)) { + throw new Error(`\`${name}\` is not an address. Received: ${address}`) + } +} diff --git a/yarn.lock b/yarn.lock index c5ae5363..fedb6d9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7492,6 +7492,11 @@ parse-code-context@^1.0.0: resolved "https://registry.yarnpkg.com/parse-code-context/-/parse-code-context-1.0.0.tgz#718c295c593d0d19a37f898473268cc75e98de1e" integrity sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA== +parse-duration@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-duration/-/parse-duration-1.0.0.tgz#8605651745f61088f6fb14045c887526c291858c" + integrity sha512-X4kUkCTHU1N/kEbwK9FpUJ0UZQa90VzeczfS704frR30gljxDG0pSziws06XlK+CGRSo/1wtG1mFIdBFQTMQNw== + parse-headers@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.3.tgz#5e8e7512383d140ba02f0c7aa9f49b4399c92515"