diff --git a/.env.example b/.env.example index 41fa43c..433d1be 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,8 @@ ETHERSCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1 POLYGONSCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1 +POLYGON_URL=https://polygon-mainnet.g.alchemy.com/v2/[YOUR_ALCHEMY_KEY] +MUMBAI_URL=https://polygon-mumbai.g.alchemy.com/v2/[YOUR_ALCHEMY_KEY] +AMOY_URL=https://polygon-amoy.g.alchemy.com/v2/[YOUR_ALCHEMY_KEY] PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1 COIN_MARKETCAP_API_KEY=[YOUR-API-KEY] GAS_PRICE=30000000000 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 32aaa5c..3ead912 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ cache artifacts # OpenZeppelin -.openzeppelin/unknown-*.json \ No newline at end of file +.openzeppelin/unknown-*.json +.DS_Store diff --git a/hardhat.config.ts b/hardhat.config.ts index c8c7a13..0603e77 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -24,6 +24,10 @@ const config: HardhatUserConfig = { url: process.env.POLYGON_URL || '', accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [] }, + amoy: { + url: process.env.AMOY_URL || '', + accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], + }, mumbai: { url: process.env.MUMBAI_URL || '', accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [] @@ -40,8 +44,19 @@ const config: HardhatUserConfig = { apiKey: { mainnet: process.env.ETHERSCAN_API_KEY || '', polygon: process.env.POLYGONSCAN_API_KEY || '', + polygonAmoy: process.env.POLYGONSCAN_API_KEY || '', polygonMumbai: process.env.POLYGONSCAN_API_KEY || '' - } + }, + customChains: [ + { + network: 'polygonAmoy', + chainId: 80002, + urls: { + apiURL: 'https://api-amoy.polygonscan.com/api', + browserURL: 'https://amoy.polygonscan.com/', + }, + }, + ], }, contractSizer: { alphaSort: true, diff --git a/scripts/data/addresses.json b/scripts/data/addresses.json index 149e302..59bfc44 100644 --- a/scripts/data/addresses.json +++ b/scripts/data/addresses.json @@ -63,6 +63,70 @@ } } }, + "amoy": { + "modules": { + "ResolverRegistry": { + "address": "0x8E498009CaCa11ca9dD6696Bc00eEFcCd51811d5", + "selectors": [ + "0x0df5b997", + "0x248a9ca3", + "0x2f2ff15d", + "0x91d14854", + "0x9748a762", + "0x8bb9c5bf", + "0xd547741f", + "0x06d1d2a1" + ] + }, + "Shared": { + "address": "0xCFB64F73c881b2Dc384475682b9936727720d22c", + "selectors": [ + "0x56f98b37", + "0xa1caf728", + "0x5b6c1979", + "0xf41377ca" + ] + }, + "NameResolver": { + "address": "0x1fE42E74fB191826392d5f887B9D97892b474d52", + "selectors": [ + "0x691f3431", + "0x77372213" + ] + }, + "VehicleIdResolver": { + "address": "0x459306CcA09E7B29f393EAC8A1CF97297398dCC0", + "selectors": [ + "0x01e11675", + "0x1bd59757", + "0xf3cdd5c3", + "0x9bfae6da", + "0x24f9e9da" + ] + }, + "Multicall": { + "address": "0x6b4751FD291DbDF20C565ce4Cf8Ba49D4630541a", + "selectors": [ + "0x415c2d96", + "0x1c0c6e51" + ] + } + }, + "contracts": { + "DcnRegistry": { + "proxy": "0x374350Ab806E06217e84a0238150E98788cd26ab", + "implementation": "0x95b78E4e4a0DCCDb4367aB22d9F7f97244c43e96" + }, + "PriceManager": { + "proxy": "0x07290D02F11F707DA3Ad9bE95e4bE63BbFFC59c3", + "implementation": "0x5A5BB56159E2B0bfAB10201e51cDc3ED78dD9940" + }, + "DcnManager": { + "proxy": "0x0c96a406e4883Ce60EFAF704aD38b381B34474d2", + "implementation": "0x916bb6552c5561B7c81CE1cd03d8A6cBCd49Eeac" + } + } + }, "mumbai": { "modules": { "ResolverRegistry": { diff --git a/scripts/data/deployConstants.ts b/scripts/data/deployConstants.ts index 6949cfc..62db90b 100644 --- a/scripts/data/deployConstants.ts +++ b/scripts/data/deployConstants.ts @@ -27,18 +27,21 @@ export const MANAGER_RESOLVER_ROLE = ethers.utils.keccak256( export const networkName = network.name; export const dimoToken: NetworkValue = { + amoy: '0x21cFE003997fB7c2B3cfe5cf71e7833B7B2eCe10', mumbai: '0x80ee7ec4493a1d7975ab900f94db25ba7c688201', polygon: '0xe261d618a959afffd53168cd07d12e37b26761db', hardhat: '0xffffffffffffffffffffffffffffffffffffffff', localhost: '0xffffffffffffffffffffffffffffffffffffffff' - }; +}; export const foundationAddress: NetworkValue = { - mumbai: '0x1741ec2915ab71fc03492715b5640133da69420b', - polygon: '0xCED3c922200559128930180d3f0bfFd4d9f4F123', - hardhat: '0xffffffffffffffffffffffffffffffffffffffff', - localhost: '0xffffffffffffffffffffffffffffffffffffffff' + amoy: '0x07B584f6a7125491C991ca2a45ab9e641B1CeE1b', + mumbai: '0x1741ec2915ab71fc03492715b5640133da69420b', + polygon: '0xCED3c922200559128930180d3f0bfFd4d9f4F123', + hardhat: '0xffffffffffffffffffffffffffffffffffffffff', + localhost: '0xffffffffffffffffffffffffffffffffffffffff' }; export const dimoVehicleIdAddress: NetworkValue = { + amoy: '0x45fbCD3ef7361d156e8b16F5538AE36DEdf61Da8', mumbai: '0x90C4D6113Ec88dd4BDf12f26DB2b3998fd13A144', polygon: '0xbA5738a18d83D41847dfFbDC6101d37C69c9B0cF', hardhat: '0xffffffffffffffffffffffffffffffffffffffff', diff --git a/scripts/data/disallowed.ts b/scripts/data/disallowed.ts index ce9847b..ebdcbb8 100644 --- a/scripts/data/disallowed.ts +++ b/scripts/data/disallowed.ts @@ -139,5 +139,8 @@ export const disallowedList = [ 'Dimo', 'DAF', 'HINO', - 'Scania' + 'Scania', + 'Chery', + 'Hashdog', + 'International' ]; \ No newline at end of file diff --git a/scripts/deploy.ts b/scripts/deploy.ts index 7e165c1..ad94ada 100644 --- a/scripts/deploy.ts +++ b/scripts/deploy.ts @@ -4,32 +4,30 @@ import { ethers, upgrades } from 'hardhat'; import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { DcnManager, DcnRegistry, ResolverRegistry, Shared, VehicleIdResolver } from '../typechain-types'; -import { getSelectors, ContractAddressesByNetwork } from '../utils'; +import { getSelectors, AddressesByNetwork } from '../utils'; import * as C from './data/deployConstants'; -import addressesJSON from './data/addresses.json'; -const contractAddresses: ContractAddressesByNetwork = addressesJSON; +function getAddresses(): AddressesByNetwork { + return JSON.parse( + fs.readFileSync(path.resolve(__dirname, 'data', 'addresses.json'), 'utf8'), + ); +} -function writeAddresses( - addresses: ContractAddressesByNetwork, - networkName: string -) { - console.log('\n----- Writing addresses to file -----'); +function writeAddresses(addresses: AddressesByNetwork, networkName: string) { + console.log('\n----- Writing addresses to file -----\n'); - const currentAddresses: ContractAddressesByNetwork = contractAddresses; + const currentAddresses: AddressesByNetwork = addresses; currentAddresses[networkName] = addresses[networkName]; fs.writeFileSync( path.resolve(__dirname, 'data', 'addresses.json'), - JSON.stringify(currentAddresses, null, 4) + JSON.stringify(currentAddresses, null, 4), ); - - console.log('----- Addresses written to file -----\n'); } async function deployModules( deployer: SignerWithAddress -): Promise { +): Promise { console.log('\n----- Deploying contracts -----\n'); const contractNameArgs: any[] = [ @@ -39,9 +37,7 @@ async function deployModules( { name: 'Multicall', args: [] } ]; - const instances: ContractAddressesByNetwork = JSON.parse( - JSON.stringify(contractAddresses) - ); + const instances: AddressesByNetwork = getAddresses(); // Deploy ResolverRegistry Implementation const DIMORegistry = await ethers.getContractFactory("ResolverRegistry"); @@ -81,12 +77,10 @@ async function deployModules( async function deployContracts( deployer: SignerWithAddress -): Promise { +): Promise { console.log('\n----- Deploying contracts -----\n'); - const instances: ContractAddressesByNetwork = JSON.parse( - JSON.stringify(contractAddresses) - ); + const instances: AddressesByNetwork = getAddresses(); const contractNameArgs = [ { @@ -95,7 +89,7 @@ async function deployContracts( C.DCN_REGISTRY_NFT_NAME, C.DCN_REGISTRY_NFT_SYMBOL, C.DCN_REGISTRY_NFT_BASE_URI, - contractAddresses[C.networkName].modules.ResolverRegistry.address + instances[C.networkName].modules.ResolverRegistry.address ] }, { @@ -152,7 +146,7 @@ async function deployContracts( C.dimoToken[C.networkName], instances[C.networkName].contracts.DcnRegistry.proxy, instances[C.networkName].contracts.PriceManager.proxy, - contractAddresses[C.networkName].modules.ResolverRegistry.address, + instances[C.networkName].modules.ResolverRegistry.address, C.foundationAddress[C.networkName] ], { @@ -179,23 +173,22 @@ async function deployContracts( async function addModule( deployer: SignerWithAddress -): Promise { +): Promise { + const instances: AddressesByNetwork = getAddresses(); + const resolverRegistryInstance = await ethers.getContractAt( 'ResolverRegistry', - contractAddresses[C.networkName].modules.ResolverRegistry.address + instances[C.networkName].modules.ResolverRegistry.address ) as ResolverRegistry; - const instances: ContractAddressesByNetwork = JSON.parse( - JSON.stringify(contractAddresses) - ); const contractsNameImpl = Object.keys( - contractAddresses[C.networkName].modules + instances[C.networkName].modules ).map((contractName) => { return { name: contractName, implementation: - contractAddresses[C.networkName].modules[contractName].address + instances[C.networkName].modules[contractName].address }; }); @@ -224,13 +217,15 @@ async function addModule( } async function setup(deployer: SignerWithAddress) { + const instances: AddressesByNetwork = getAddresses(); + const vehicleIdResolverInstance = await ethers.getContractAt( 'VehicleIdResolver', - contractAddresses[C.networkName].modules.ResolverRegistry.address + instances[C.networkName].modules.ResolverRegistry.address ) as VehicleIdResolver; const sharedInstance = await ethers.getContractAt( 'Shared', - contractAddresses[C.networkName].modules.ResolverRegistry.address + instances[C.networkName].modules.ResolverRegistry.address ) as Shared; console.log('\n----- Setting vehicle ID proxy address -----'); @@ -246,39 +241,50 @@ async function setup(deployer: SignerWithAddress) { console.log('----- DIMO token address set -----\n'); console.log('\n----- Setting DcnManager address -----'); - await sharedInstance.connect(deployer).setDcnManager(contractAddresses[C.networkName].contracts.DcnManager.proxy); + await sharedInstance.connect(deployer).setDcnManager(instances[C.networkName].contracts.DcnManager.proxy); console.log('----- DcnManager address set -----\n'); console.log('\n----- Setting DcnRegistry address -----'); - await sharedInstance.connect(deployer).setDcnRegistry(contractAddresses[C.networkName].contracts.DcnRegistry.proxy); - console.log('----- DcnRegistry addresse set -----\n'); + await sharedInstance.connect(deployer).setDcnRegistry(instances[C.networkName].contracts.DcnRegistry.proxy); + console.log('----- DcnRegistry address set -----\n'); } async function grantRoles(deployer: SignerWithAddress) { + const instances: AddressesByNetwork = getAddresses(); + const dcnRegistryInstance = await ethers.getContractAt( 'DcnRegistry', - contractAddresses[C.networkName].contracts.DcnRegistry.proxy + instances[C.networkName].contracts.DcnRegistry.proxy ) as DcnRegistry; const resolverRegistryInstance = await ethers.getContractAt( 'ResolverRegistry', - contractAddresses[C.networkName].modules.ResolverRegistry.address + instances[C.networkName].modules.ResolverRegistry.address ) as ResolverRegistry; const dcnManagerInstance = await ethers.getContractAt( 'DcnManager', - contractAddresses[C.networkName].contracts.DcnManager.proxy + instances[C.networkName].contracts.DcnManager.proxy ) as DcnManager; + const priceManagerInstance = await ethers.getContractAt( + 'PriceManager', + instances[C.networkName].contracts.PriceManager.proxy + ); console.log('\n----- Granting roles -----'); await dcnRegistryInstance.connect(deployer).grantRole(C.ADMIN_ROLE, deployer.address); await dcnRegistryInstance.connect(deployer).grantRole(C.MINTER_ROLE, deployer.address); - await dcnRegistryInstance.connect(deployer).grantRole(C.MANAGER_ROLE, contractAddresses[C.networkName].contracts.DcnManager.proxy); + await dcnRegistryInstance.connect(deployer).grantRole(C.UPGRADER_ROLE, deployer.address); + await dcnRegistryInstance.connect(deployer).grantRole(C.MANAGER_ROLE, instances[C.networkName].contracts.DcnManager.proxy); await resolverRegistryInstance.connect(deployer).grantRole(C.ADMIN_ROLE, deployer.address); await dcnManagerInstance.connect(deployer).grantRole(C.TLD_MINTER_ROLE, deployer.address); await dcnManagerInstance.connect(deployer).grantRole(C.ADMIN_ROLE, deployer.address); await dcnManagerInstance.connect(deployer).grantRole(C.MINTER_ROLE, deployer.address); + await dcnManagerInstance.connect(deployer).grantRole(C.UPGRADER_ROLE, deployer.address); + + await priceManagerInstance.connect(deployer).grantRole(C.ADMIN_ROLE, deployer.address); + await priceManagerInstance.connect(deployer).grantRole(C.UPGRADER_ROLE, deployer.address); console.log('----- Roles granted -----\n'); } @@ -288,26 +294,25 @@ async function upgradeContract( contractName: string, networkName: string, forceImport?: boolean -): Promise { - // const NftFactoryOld = await ethers.getContractFactory( - // 'AftermarketDeviceIdOld', - // deployer - // ); +): Promise { const NftFactory = await ethers.getContractFactory(contractName, deployer); - const instances: ContractAddressesByNetwork = JSON.parse( - JSON.stringify(contractAddresses) - ); + const instances: AddressesByNetwork = getAddresses(); const oldProxyAddress = instances[networkName].contracts[contractName].proxy; console.log('\n----- Upgrading NFT -----\n'); - // if (forceImport) { - // await upgrades.forceImport(oldProxyAddress, NftFactoryOld, { - // kind: 'uups' - // }); - // } + if (forceImport) { + const NftFactoryOld = await ethers.getContractFactory( + `${contractName}_old`, + deployer + ); + + await upgrades.forceImport(oldProxyAddress, NftFactoryOld, { + kind: 'uups' + }); + } console.log(await upgrades.erc1967.getImplementationAddress(oldProxyAddress)); @@ -337,14 +342,14 @@ async function upgradeContract( async function main() { const [deployer] = await ethers.getSigners(); - const instances = await deployModules(deployer); - writeAddresses(instances, C.networkName); - const instancesWithSelectors = await addModule(deployer); - writeAddresses(instancesWithSelectors, C.networkName); - const contractInstances = await deployContracts(deployer); - writeAddresses(contractInstances, C.networkName); + // const instances = await deployModules(deployer); + // writeAddresses(instances, C.networkName); + // const instancesWithSelectors = await addModule(deployer); + // writeAddresses(instancesWithSelectors, C.networkName); + // const contractInstances = await deployContracts(deployer); + // writeAddresses(contractInstances, C.networkName); - await grantRoles(deployer); + // await grantRoles(deployer); await setup(deployer); } diff --git a/scripts/loadUpDisallowedLabels.ts b/scripts/loadUpDisallowedLabels.ts index 455ee5a..9e2ba46 100644 --- a/scripts/loadUpDisallowedLabels.ts +++ b/scripts/loadUpDisallowedLabels.ts @@ -1,11 +1,11 @@ import { ethers, network } from 'hardhat'; import { DcnManager } from '../typechain-types'; -import { ContractAddressesByNetwork } from '../utils'; +import { AddressesByNetwork } from '../utils'; import addressesJSON from './data/addresses.json'; import { disallowedList } from './data/disallowed'; -const contractAddresses: ContractAddressesByNetwork = addressesJSON; +const contractAddresses: AddressesByNetwork = addressesJSON; function cleanUpLabels(labels: string[]): string[] { return labels.map(label => { diff --git a/scripts/upgrade.ts b/scripts/upgrade.ts index d85ef06..e127d08 100644 --- a/scripts/upgrade.ts +++ b/scripts/upgrade.ts @@ -4,20 +4,23 @@ import { ethers, upgrades } from 'hardhat'; import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; import { ResolverRegistry, DcnManager } from '../typechain-types'; -import { getSelectors, ContractAddressesByNetwork } from '../utils'; +import { getSelectors, AddressesByNetwork } from '../utils'; import * as C from './data/deployConstants'; -import addressesJSON from './data/addresses.json'; -const contractAddresses: ContractAddressesByNetwork = addressesJSON; +function getAddresses(): AddressesByNetwork { + return JSON.parse( + fs.readFileSync(path.resolve(__dirname, 'data', 'addresses.json'), 'utf8'), + ); +} // eslint-disable-next-line no-unused-vars function writeAddresses( - addresses: ContractAddressesByNetwork, + addresses: AddressesByNetwork, networkName: string ) { console.log('\n----- Writing addresses to file -----'); - const currentAddresses: ContractAddressesByNetwork = contractAddresses; + const currentAddresses: AddressesByNetwork = addresses; currentAddresses[networkName] = addresses[networkName]; fs.writeFileSync( @@ -33,12 +36,10 @@ async function deployModules( deployer: SignerWithAddress, contractNames: string[], networkName: string -): Promise { +): Promise { console.log('\n----- Deploying contracts -----\n'); - const instances: ContractAddressesByNetwork = JSON.parse( - JSON.stringify(contractAddresses) - ); + const instances: AddressesByNetwork = getAddresses(); for (const contractName of contractNames) { const ContractFactory = await ethers.getContractFactory(contractName); @@ -69,23 +70,21 @@ async function addModules( deployer: SignerWithAddress, contractNames: string[], networkName: string -): Promise { +): Promise { + const instances: AddressesByNetwork = getAddresses(); + const resolverRegistryInstance = await ethers.getContractAt( 'ResolverRegistry', - contractAddresses[C.networkName].modules.ResolverRegistry.address + instances[C.networkName].modules.ResolverRegistry.address ) as ResolverRegistry; - const instances: ContractAddressesByNetwork = JSON.parse( - JSON.stringify(contractAddresses) - ); - - const contractsNameImpl = Object.keys(contractAddresses[networkName].modules) + const contractsNameImpl = Object.keys(instances[networkName].modules) .filter((contractName) => contractNames.includes(contractName)) .map((contractName) => { return { name: contractName, implementation: - contractAddresses[networkName].modules[contractName].address + instances[networkName].modules[contractName].address }; }); @@ -117,16 +116,14 @@ async function updateModule( deployer: SignerWithAddress, contractName: string, networkName: string -): Promise { +): Promise { + const instances: AddressesByNetwork = getAddresses(); + const resolverRegistryInstance = await ethers.getContractAt( 'ResolverRegistry', - contractAddresses[C.networkName].modules.ResolverRegistry.address + instances[C.networkName].modules.ResolverRegistry.address ) as ResolverRegistry; - const instances: ContractAddressesByNetwork = JSON.parse( - JSON.stringify(contractAddresses) - ); - const contractAddressOld = instances[networkName].modules[contractName].address; const contractSelectorsOld = @@ -178,22 +175,20 @@ async function upgradeContract( contractName: string, networkName: string, forceImport?: boolean -): Promise { - const contractFactoryOld = await ethers.getContractFactory( - 'DcnManagerOld', - deployer - ); - const ContractFactory = await ethers.getContractFactory(contractName, deployer); - - const instances: ContractAddressesByNetwork = JSON.parse( - JSON.stringify(contractAddresses) - ); +): Promise { + const instances: AddressesByNetwork = getAddresses(); + const ContractFactory = await ethers.getContractFactory(contractName, deployer); const oldProxyAddress = instances[networkName].contracts[contractName].proxy; console.log(`\n----- Upgrading contract ${contractName} -----\n`); if (forceImport) { + const contractFactoryOld = await ethers.getContractFactory( + `${contractName}_old`, + deployer + ); + await upgrades.forceImport(oldProxyAddress, contractFactoryOld, { kind: 'uups' }); @@ -237,12 +232,14 @@ async function main() { // value: ethers.utils.parseEther('100') // }); - const instances = await updateModule(deployer, 'VehicleIdResolver', currentNetwork); - writeAddresses(instances, currentNetwork); + const instances: AddressesByNetwork = getAddresses(); + + const instances1 = await updateModule(deployer, 'VehicleIdResolver', currentNetwork); + writeAddresses(instances1, currentNetwork); const dcnManagerInstance = await ethers.getContractAt( 'DcnManager', - contractAddresses[currentNetwork].contracts.DcnManager.proxy + instances[currentNetwork].contracts.DcnManager.proxy ) as DcnManager; await dcnManagerInstance.connect(deployer).grantRole(C.UPGRADER_ROLE, deployer.address); diff --git a/utils/types.ts b/utils/types.ts index c218205..128c2fa 100644 --- a/utils/types.ts +++ b/utils/types.ts @@ -1,4 +1,4 @@ -export interface ContractAddressesByNetwork { +export interface AddressesByNetwork { [index: string]: { modules: { [index: string]: {