From 504d85bf7222714c10e4403bf65b3cb36f71f7bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 14 Feb 2025 14:08:06 -0300 Subject: [PATCH 01/15] feat: refactor deployment tooling, use task instead of script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- packages/hardhat-graph-protocol/package.json | 6 +- packages/hardhat-graph-protocol/src/gre.ts | 5 +- .../src/sdk/address-book.ts | 48 +++--- .../src/sdk/deployments/horizon/contracts.ts | 4 +- .../src/sdk/hardhat.base.config.ts | 21 +-- .../src/sdk/ignition/ignition.ts | 71 ++++++--- .../hardhat-graph-protocol/src/sdk/index.ts | 4 +- packages/horizon/hardhat.config.ts | 2 + .../ignition/modules/core/GraphPayments.ts | 4 +- .../ignition/modules/core/HorizonStaking.ts | 4 +- .../ignition/modules/core/PaymentsEscrow.ts | 4 +- .../horizon/ignition/modules/core/core.ts | 32 +++- packages/horizon/ignition/modules/deploy.ts | 32 +++- .../ignition/modules/migrate/migrate-1.ts | 8 +- .../ignition/modules/migrate/migrate-3.ts | 28 ++-- .../ignition/modules/migrate/migrate-4.ts | 12 +- .../ignition/modules/periphery/Curation.ts | 6 +- .../modules/periphery/EpochManager.ts | 4 +- .../ignition/modules/periphery/GraphToken.ts | 4 +- .../modules/periphery/GraphTokenGateway.ts | 4 +- .../modules/periphery/RewardsManager.ts | 6 +- .../ignition/modules/periphery/periphery.ts | 15 +- .../ignition/modules/proxy/GraphProxy.ts | 2 +- packages/horizon/package.json | 2 +- packages/horizon/scripts/deploy.ts | 21 --- packages/horizon/scripts/migrate.ts | 98 ------------ packages/horizon/tasks/deploy.ts | 143 ++++++++++++++++++ .../horizon/types/hardhat-graph-protocol.d.ts | 45 ++++++ .../types/hardhat-graph-protocol.d.ts | 2 +- yarn.lock | 2 + 30 files changed, 392 insertions(+), 247 deletions(-) delete mode 100644 packages/horizon/scripts/deploy.ts delete mode 100644 packages/horizon/scripts/migrate.ts create mode 100644 packages/horizon/tasks/deploy.ts create mode 100644 packages/horizon/types/hardhat-graph-protocol.d.ts diff --git a/packages/hardhat-graph-protocol/package.json b/packages/hardhat-graph-protocol/package.json index e484a0643..fc9f247c0 100644 --- a/packages/hardhat-graph-protocol/package.json +++ b/packages/hardhat-graph-protocol/package.json @@ -16,8 +16,8 @@ "main": "./dist/src/index.js", "exports": { ".": { - "types": "./dist/src/index.d.ts", - "default": "./dist/src/index.js" + "types": "./src/types.ts", + "default": "./src/index.ts" }, "./sdk": { "types": "./src/sdk/index.ts", @@ -47,7 +47,9 @@ "json5": "^2.2.3" }, "devDependencies": { + "@nomicfoundation/hardhat-ignition": "^0.15.9", "@nomicfoundation/hardhat-verify": "^2.0.12", + "@nomicfoundation/ignition-core": "^0.15.9", "@types/chai": "^4.0.0", "@types/debug": "^4.1.12", "@types/mocha": "^10.0.9", diff --git a/packages/hardhat-graph-protocol/src/gre.ts b/packages/hardhat-graph-protocol/src/gre.ts index 028df6229..7f6e0566a 100644 --- a/packages/hardhat-graph-protocol/src/gre.ts +++ b/packages/hardhat-graph-protocol/src/gre.ts @@ -2,6 +2,7 @@ import path from 'path' import { getAddressBookPath } from './config' import { HardhatEthersProvider } from '@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider' +import { lazyFunction } from 'hardhat/plugins' import { logDebug } from './logger' import { GraphHorizonAddressBook } from './sdk/deployments/horizon' @@ -28,7 +29,7 @@ export const greExtendConfig = (config: HardhatConfig, userConfig: Readonly { - hre.graph = (opts: GraphRuntimeEnvironmentOptions = { deployments: {} }) => { + hre.graph = lazyFunction(() => (opts: GraphRuntimeEnvironmentOptions = { deployments: {} }) => { logDebug('*** Initializing Graph Runtime Environment (GRE) ***') logDebug(`Main network: ${hre.network.name}`) const chainId = hre.network.config.chainId @@ -80,5 +81,5 @@ export const greExtendEnvironment = (hre: HardhatRuntimeEnvironment) => { assertGraphRuntimeEnvironment(gre) logDebug('GRE initialized successfully!') return gre - } + }) } diff --git a/packages/hardhat-graph-protocol/src/sdk/address-book.ts b/packages/hardhat-graph-protocol/src/sdk/address-book.ts index dda2f8490..884d91c35 100644 --- a/packages/hardhat-graph-protocol/src/sdk/address-book.ts +++ b/packages/hardhat-graph-protocol/src/sdk/address-book.ts @@ -13,8 +13,9 @@ export type AddressBookJson< export type AddressBookEntry = { address: string - proxy?: boolean - implementation?: AddressBookEntry + proxy?: 'graph' | 'transparent' + proxyAdmin?: string + implementation?: string } /** @@ -24,8 +25,9 @@ export type AddressBookEntry = { * "": { * "": { * "address": "
", - * "proxy": true, // optional - * "implementation": { ... } // optional, nested contract structure + * "proxy": "", // optional + * "proxyAdmin": "
", // optional + * "implementation": "
", // optional * ... * } * } @@ -80,7 +82,7 @@ export abstract class AddressBook< // If it's empty, initialize it with an empty object const fileContents = JSON.parse(fs.readFileSync(this.file, 'utf8') || '{}') if (!fileContents[this.chainId]) { - fileContents[this.chainId] = {} as Record + fileContents[this.chainId] = {} } this.assertAddressBookJson(fileContents) this.addressBook = fileContents @@ -100,25 +102,29 @@ export abstract class AddressBook< * Get an entry from the address book * * @param name the name of the contract to get + * @param strict if true it will throw an error if the contract is not found * @returns the address book entry for the contract * Returns an empty address book entry if the contract is not found */ - getEntry(name: ContractName): { address: string } { - const entry = this.addressBook[this.chainId][name] - // Handle both object and string formats - if (typeof entry === 'string') { - return { address: entry } + getEntry(name: string): AddressBookEntry { + if (!this.isContractName(name)) { + throw new Error(`Contract name ${name} is not a valid contract name`) } + const entry = this.addressBook[this.chainId][name] + this._assertAddressBookEntry(entry) return entry } /** * Save an entry to the address book - * + * Allows partial address book entries to be saved * @param name the name of the contract to save * @param entry the address book entry for the contract */ - setEntry(name: ContractName, entry: AddressBookEntry): void { + setEntry(name: ContractName, entry: Partial): void { + if (entry.address === undefined) { + entry.address = '0x0000000000000000000000000000000000000000' + } this._assertAddressBookEntry(entry) this.addressBook[this.chainId][name] = entry try { @@ -162,7 +168,8 @@ export abstract class AddressBook< ): ContractList { const contracts = {} as ContractList if (this.listEntries().length == 0) { - throw Error('No valid contracts found in address book') + logError('No valid contracts found in address book') + return contracts } for (const contractName of this.listEntries()) { const artifactPath = typeof artifactsPath === 'object' && !Array.isArray(artifactsPath) @@ -214,18 +221,17 @@ export abstract class AddressBook< // Asserts the provided object is a valid address book entry _assertAddressBookEntry( entry: unknown, - ): asserts entry is { address: string } { - if (typeof entry === 'string') { - // If it's a string, treat it as an address - return - } - + ): asserts entry is AddressBookEntry { assertObject(entry) if (!('address' in entry)) { throw new Error('Address book entry must have an address field') } - if (typeof entry.address !== 'string') { - throw new Error('Address book entry address must be a string') + + const allowedFields = ['address', 'implementation', 'proxyAdmin', 'proxy'] + const entryFields = Object.keys(entry) + const invalidFields = entryFields.filter(field => !allowedFields.includes(field)) + if (invalidFields.length > 0) { + throw new Error(`Address book entry contains invalid fields: ${invalidFields.join(', ')}`) } } } diff --git a/packages/hardhat-graph-protocol/src/sdk/deployments/horizon/contracts.ts b/packages/hardhat-graph-protocol/src/sdk/deployments/horizon/contracts.ts index 86dd00be4..2797f2c83 100644 --- a/packages/hardhat-graph-protocol/src/sdk/deployments/horizon/contracts.ts +++ b/packages/hardhat-graph-protocol/src/sdk/deployments/horizon/contracts.ts @@ -24,6 +24,7 @@ export const GraphHorizonContractNameList = [ 'RewardsManager', 'L2GraphToken', 'L2GraphTokenGateway', + 'L2Curation', // @graphprotocol/horizon 'HorizonStaking', @@ -32,7 +33,7 @@ export const GraphHorizonContractNameList = [ 'GraphTallyCollector', ] as const -const root = path.resolve(__dirname, '../../../../..') // hardhat-graph-protocol root +const root = path.resolve(__dirname, '../../../..') // hardhat-graph-protocol root export const CONTRACTS_ARTIFACTS_PATH = path.resolve(root, 'node_modules', '@graphprotocol/contracts/build/contracts') export const HORIZON_ARTIFACTS_PATH = path.resolve(root, 'node_modules', '@graphprotocol/horizon/build/contracts') @@ -44,6 +45,7 @@ export const GraphHorizonArtifactsMap = { RewardsManager: CONTRACTS_ARTIFACTS_PATH, L2GraphToken: CONTRACTS_ARTIFACTS_PATH, L2GraphTokenGateway: CONTRACTS_ARTIFACTS_PATH, + L2Curation: CONTRACTS_ARTIFACTS_PATH, // @graphprotocol/horizon HorizonStaking: HORIZON_ARTIFACTS_PATH, diff --git a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts index ea1ab8d1d..49731f0c8 100644 --- a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts +++ b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts @@ -13,19 +13,6 @@ interface SecureAccountsOptions { const ARBITRUM_ONE_RPC = vars.get('ARBITRUM_ONE_RPC', 'https://arb1.arbitrum.io/rpc') const ARBITRUM_SEPOLIA_RPC = vars.get('ARBITRUM_SEPOLIA_RPC', 'https://sepolia-rollup.arbitrum.io/rpc') -// Accounts -const getTestnetAccounts = () => { - const accounts: string[] = [] - if (vars.has('DEPLOYER_PRIVATE_KEY')) accounts.push(vars.get('DEPLOYER_PRIVATE_KEY')) - if (vars.has('GOVERNOR_PRIVATE_KEY')) accounts.push(vars.get('GOVERNOR_PRIVATE_KEY')) - return accounts -} -const getHardhatAccounts = () => { - return { - mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect', - } -} - export const solidityUserConfig: SolidityUserConfig = { version: '0.8.27', settings: { @@ -57,7 +44,9 @@ type BaseNetworksUserConfig = NetworksUserConfig & export const networksUserConfig: BaseNetworksUserConfig = { hardhat: { chainId: 31337, - accounts: getHardhatAccounts(), + accounts: { + mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect', + }, deployments: { horizon: require.resolve('@graphprotocol/horizon/addresses-local.json'), }, @@ -65,7 +54,9 @@ export const networksUserConfig: BaseNetworksUserConfig = { localhost: { chainId: 31337, url: 'http://localhost:8545', - accounts: getTestnetAccounts(), + secureAccounts: { + enabled: true, + }, deployments: { horizon: require.resolve('@graphprotocol/horizon/addresses-local.json'), }, diff --git a/packages/hardhat-graph-protocol/src/sdk/ignition/ignition.ts b/packages/hardhat-graph-protocol/src/sdk/ignition/ignition.ts index 55e11a772..8bc551d68 100644 --- a/packages/hardhat-graph-protocol/src/sdk/ignition/ignition.ts +++ b/packages/hardhat-graph-protocol/src/sdk/ignition/ignition.ts @@ -5,6 +5,7 @@ require('json5/lib/register') import fs from 'fs' import path from 'path' +import { AddressBook } from '../address-book' export function loadConfig(configPath: string, prefix: string, networkName: string): any { const configFileCandidates = [ @@ -19,7 +20,7 @@ export function loadConfig(configPath: string, prefix: string, networkName: stri ) } - return removeNFromBigInts(require(configFile)) + return { config: removeNFromBigInts(require(configFile)), file: configFile } } export function patchConfig(jsonData: any, patches: Record) { @@ -55,40 +56,62 @@ export function mergeConfigs(obj1: any, obj2: any) { return merged } -export function saveAddressBook( +export function saveToAddressBook( contracts: any, chainId: number | undefined, - addressBook = 'addresses.json', -): Record> { + addressBook: AddressBook, +): AddressBook { if (!chainId) { throw new Error('Chain ID is required') } - // Use different address book for local networks - this one can be gitignored - if ([1377, 31337].includes(chainId)) { - addressBook = 'addresses-local.json' - } + // Extract contract names and addresses + for (const [ignitionContractName, contract] of Object.entries(contracts)) { + // Proxy contracts + if (ignitionContractName.includes('_Proxy_')) { + const contractName = ignitionContractName.replace(/(Transparent_Proxy_|Graph_Proxy_)/, '') as ContractName + const proxy = ignitionContractName.includes('Transparent_Proxy_') ? 'transparent' : 'graph' + const entry = addressBook.getEntry(contractName) + addressBook.setEntry(contractName, { + ...entry, + address: (contract as any).target, + proxy, + }) + } - const output = fs.existsSync(addressBook) - ? JSON.parse(fs.readFileSync(addressBook, 'utf8')) - : {} + // Proxy admin contracts + if (ignitionContractName.includes('_ProxyAdmin_')) { + const contractName = ignitionContractName.replace(/(Transparent_ProxyAdmin_|Graph_ProxyAdmin_)/, '') as ContractName + const proxy = ignitionContractName.includes('Transparent_ProxyAdmin_') ? 'transparent' : 'graph' + const entry = addressBook.getEntry(contractName) + addressBook.setEntry(contractName, { + ...entry, + proxy, + proxyAdmin: (contract as any).target, + }) + } - output[chainId] = output[chainId] || {} + // Implementation contracts + if (ignitionContractName.startsWith('Implementation_')) { + const contractName = ignitionContractName.replace('Implementation_', '') as ContractName + const entry = addressBook.getEntry(contractName) + addressBook.setEntry(contractName, { + ...entry, + implementation: (contract as any).target, + }) + } - // Extract contract names and addresses - Object.entries(contracts).forEach(([contractName, contract]: [string, any]) => { - output[chainId][contractName] = contract.target - }) - - // Write to output file - const outputDir = path.dirname(addressBook) - if (!fs.existsSync(outputDir)) { - fs.mkdirSync(outputDir, { recursive: true }) + // Non proxied contracts + if (addressBook.isContractName(ignitionContractName)) { + const entry = addressBook.getEntry(ignitionContractName) + addressBook.setEntry(ignitionContractName, { + ...entry, + address: (contract as any).target, + }) + } } - fs.writeFileSync(addressBook, JSON.stringify(output, null, 2)) - - return output as Record> + return addressBook } // Ignition requires "n" suffix for bigints, but not here diff --git a/packages/hardhat-graph-protocol/src/sdk/index.ts b/packages/hardhat-graph-protocol/src/sdk/index.ts index 5919c81f3..97531b3ea 100644 --- a/packages/hardhat-graph-protocol/src/sdk/index.ts +++ b/packages/hardhat-graph-protocol/src/sdk/index.ts @@ -1,5 +1,5 @@ -import { loadConfig, mergeConfigs, patchConfig, saveAddressBook } from './ignition/ignition' +import { loadConfig, mergeConfigs, patchConfig, saveToAddressBook } from './ignition/ignition' import { hardhatBaseConfig } from './hardhat.base.config' -const IgnitionHelper = { saveAddressBook, loadConfig, patchConfig, mergeConfigs } +const IgnitionHelper = { saveToAddressBook, loadConfig, patchConfig, mergeConfigs } export { hardhatBaseConfig, IgnitionHelper } diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts index 0c9262f8c..eb62f0f2a 100644 --- a/packages/horizon/hardhat.config.ts +++ b/packages/horizon/hardhat.config.ts @@ -8,6 +8,8 @@ import 'hardhat-storage-layout' import 'hardhat-contract-sizer' import 'hardhat-secure-accounts' +import './tasks/deploy' + // Skip importing hardhat-graph-protocol when building the project, it has circular dependency if (process.env.BUILD_RUN !== 'true') { require('hardhat-graph-protocol') diff --git a/packages/horizon/ignition/modules/core/GraphPayments.ts b/packages/horizon/ignition/modules/core/GraphPayments.ts index 414d3a8fa..56aa73f60 100644 --- a/packages/horizon/ignition/modules/core/GraphPayments.ts +++ b/packages/horizon/ignition/modules/core/GraphPayments.ts @@ -33,7 +33,7 @@ export default buildModule('GraphPayments', (m) => { m.call(GraphPaymentsProxyAdmin, 'transferOwnership', [governor], { after: [GraphPayments] }) - return { GraphPayments, GraphPaymentsProxyAdmin } + return { GraphPayments, GraphPaymentsProxyAdmin, GraphPaymentsImplementation } }) // Note that this module requires MigrateHorizonProxiesGovernorModule to be executed first @@ -66,5 +66,5 @@ export const MigrateGraphPaymentsModule = buildModule('GraphPayments', (m) => { m.call(GraphPaymentsProxyAdmin, 'transferOwnership', [governor], { after: [GraphPayments] }) - return { GraphPayments, GraphPaymentsProxyAdmin } + return { GraphPayments, GraphPaymentsProxyAdmin, GraphPaymentsImplementation } }) diff --git a/packages/horizon/ignition/modules/core/HorizonStaking.ts b/packages/horizon/ignition/modules/core/HorizonStaking.ts index e0e2d9b16..c87208be2 100644 --- a/packages/horizon/ignition/modules/core/HorizonStaking.ts +++ b/packages/horizon/ignition/modules/core/HorizonStaking.ts @@ -43,7 +43,7 @@ export default buildModule('HorizonStaking', (m) => { }) m.call(HorizonStaking, 'setMaxThawingPeriod', [maxThawingPeriod]) - return { HorizonStaking } + return { HorizonStaking, HorizonStakingImplementation } }) // Note that this module requires MigrateHorizonProxiesGovernorModule to be executed first @@ -95,5 +95,5 @@ export const MigrateHorizonStakingGovernorModule = buildModule('HorizonStakingGo }) m.call(HorizonStaking, 'setMaxThawingPeriod', [maxThawingPeriod]) - return { HorizonStaking } + return { HorizonStaking, HorizonStakingImplementation } }) diff --git a/packages/horizon/ignition/modules/core/PaymentsEscrow.ts b/packages/horizon/ignition/modules/core/PaymentsEscrow.ts index 2734dd205..139d06b06 100644 --- a/packages/horizon/ignition/modules/core/PaymentsEscrow.ts +++ b/packages/horizon/ignition/modules/core/PaymentsEscrow.ts @@ -33,7 +33,7 @@ export default buildModule('PaymentsEscrow', (m) => { m.call(PaymentsEscrowProxyAdmin, 'transferOwnership', [governor], { after: [PaymentsEscrow] }) - return { PaymentsEscrow, PaymentsEscrowProxyAdmin } + return { PaymentsEscrow, PaymentsEscrowProxyAdmin, PaymentsEscrowImplementation } }) // Note that this module requires MigrateHorizonProxiesGovernorModule to be executed first @@ -66,5 +66,5 @@ export const MigratePaymentsEscrowModule = buildModule('PaymentsEscrow', (m) => m.call(PaymentsEscrowProxyAdmin, 'transferOwnership', [governor], { after: [PaymentsEscrow] }) - return { PaymentsEscrow, PaymentsEscrowProxyAdmin } + return { PaymentsEscrow, PaymentsEscrowProxyAdmin, PaymentsEscrowImplementation } }) diff --git a/packages/horizon/ignition/modules/core/core.ts b/packages/horizon/ignition/modules/core/core.ts index e634e5e65..f719e6605 100644 --- a/packages/horizon/ignition/modules/core/core.ts +++ b/packages/horizon/ignition/modules/core/core.ts @@ -1,24 +1,40 @@ import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' import GraphPaymentsModule, { MigrateGraphPaymentsModule } from './GraphPayments' +import GraphTallyCollectorModule, { MigrateGraphTallyCollectorModule } from './GraphTallyCollector' import HorizonStakingModule, { MigrateHorizonStakingDeployerModule } from './HorizonStaking' import PaymentsEscrowModule, { MigratePaymentsEscrowModule } from './PaymentsEscrow' -import GraphTallyCollectorModule, { MigrateGraphTallyCollectorModule } from './GraphTallyCollector' export default buildModule('GraphHorizon_Core', (m) => { - const { HorizonStaking } = m.useModule(HorizonStakingModule) - const { GraphPayments } = m.useModule(GraphPaymentsModule) - const { PaymentsEscrow } = m.useModule(PaymentsEscrowModule) + const { HorizonStaking, HorizonStakingImplementation } = m.useModule(HorizonStakingModule) + const { GraphPayments, GraphPaymentsImplementation } = m.useModule(GraphPaymentsModule) + const { PaymentsEscrow, PaymentsEscrowImplementation } = m.useModule(PaymentsEscrowModule) const { GraphTallyCollector } = m.useModule(GraphTallyCollectorModule) - return { HorizonStaking, GraphPayments, PaymentsEscrow, GraphTallyCollector } + return { + HorizonStaking, + HorizonStakingImplementation, + GraphPayments, + GraphPaymentsImplementation, + PaymentsEscrow, + PaymentsEscrowImplementation, + GraphTallyCollector, + } }) export const MigrateHorizonCoreModule = buildModule('GraphHorizon_Core', (m) => { const { HorizonStakingProxy: HorizonStaking, HorizonStakingImplementation } = m.useModule(MigrateHorizonStakingDeployerModule) - const { GraphPayments } = m.useModule(MigrateGraphPaymentsModule) - const { PaymentsEscrow } = m.useModule(MigratePaymentsEscrowModule) + const { GraphPayments, GraphPaymentsImplementation } = m.useModule(MigrateGraphPaymentsModule) + const { PaymentsEscrow, PaymentsEscrowImplementation } = m.useModule(MigratePaymentsEscrowModule) const { GraphTallyCollector } = m.useModule(MigrateGraphTallyCollectorModule) - return { HorizonStaking, HorizonStakingImplementation, GraphPayments, PaymentsEscrow, GraphTallyCollector } + return { + HorizonStaking, + HorizonStakingImplementation, + GraphPayments, + GraphPaymentsImplementation, + PaymentsEscrow, + PaymentsEscrowImplementation, + GraphTallyCollector, + } }) diff --git a/packages/horizon/ignition/modules/deploy.ts b/packages/horizon/ignition/modules/deploy.ts index 4f904c05a..aed98f69f 100644 --- a/packages/horizon/ignition/modules/deploy.ts +++ b/packages/horizon/ignition/modules/deploy.ts @@ -7,16 +7,24 @@ export default buildModule('GraphHorizon_Deploy', (m) => { const { Controller, EpochManager, + EpochManagerImplementation, GraphProxyAdmin, L2GraphTokenGateway, + L2GraphTokenGatewayImplementation, L2GraphToken, + L2GraphTokenImplementation, RewardsManager, + RewardsManagerImplementation, L2Curation, + L2CurationImplementation, } = m.useModule(GraphPeripheryModule) const { HorizonStaking, + HorizonStakingImplementation, GraphPayments, + GraphPaymentsImplementation, PaymentsEscrow, + PaymentsEscrowImplementation, GraphTallyCollector, } = m.useModule(GraphHorizonCoreModule) @@ -32,15 +40,23 @@ export default buildModule('GraphHorizon_Deploy', (m) => { return { Controller, - L2Curation, - EpochManager, + Graph_Proxy_EpochManager: EpochManager, + Implementation_EpochManager: EpochManagerImplementation, + Graph_Proxy_L2Curation: L2Curation, + Implementation_L2Curation: L2CurationImplementation, + Graph_Proxy_RewardsManager: RewardsManager, + Implementation_RewardsManager: RewardsManagerImplementation, + Graph_Proxy_L2GraphTokenGateway: L2GraphTokenGateway, + Implementation_L2GraphTokenGateway: L2GraphTokenGatewayImplementation, + Graph_Proxy_L2GraphToken: L2GraphToken, + Implementation_L2GraphToken: L2GraphTokenImplementation, GraphProxyAdmin, - L2GraphTokenGateway, - L2GraphToken, - RewardsManager, - HorizonStaking, - GraphPayments, - PaymentsEscrow, + Graph_Proxy_HorizonStaking: HorizonStaking, + Implementation_HorizonStaking: HorizonStakingImplementation, + Transparent_Proxy_GraphPayments: GraphPayments, + Implementation_GraphPayments: GraphPaymentsImplementation, + Transparent_Proxy_PaymentsEscrow: PaymentsEscrow, + Implementation_PaymentsEscrow: PaymentsEscrowImplementation, GraphTallyCollector, } }) diff --git a/packages/horizon/ignition/modules/migrate/migrate-1.ts b/packages/horizon/ignition/modules/migrate/migrate-1.ts index f1fffc103..9b7cab512 100644 --- a/packages/horizon/ignition/modules/migrate/migrate-1.ts +++ b/packages/horizon/ignition/modules/migrate/migrate-1.ts @@ -11,9 +11,9 @@ export default buildModule('GraphHorizon_Migrate_1', (m) => { } = m.useModule(MigrateHorizonProxiesDeployerModule) return { - GraphPaymentsProxy, - PaymentsEscrowProxy, - GraphPaymentsProxyAdmin, - PaymentsEscrowProxyAdmin, + Transparent_Proxy_GraphPayments: GraphPaymentsProxy, + Transparent_Proxy_PaymentsEscrow: PaymentsEscrowProxy, + Transparent_ProxyAdmin_GraphPayments: GraphPaymentsProxyAdmin, + Transparent_ProxyAdmin_PaymentsEscrow: PaymentsEscrowProxyAdmin, } }) diff --git a/packages/horizon/ignition/modules/migrate/migrate-3.ts b/packages/horizon/ignition/modules/migrate/migrate-3.ts index 73def82c0..999cc25cc 100644 --- a/packages/horizon/ignition/modules/migrate/migrate-3.ts +++ b/packages/horizon/ignition/modules/migrate/migrate-3.ts @@ -20,24 +20,28 @@ export default buildModule('GraphHorizon_Migrate_3', (m) => { HorizonStaking, HorizonStakingImplementation, GraphPayments, + GraphPaymentsImplementation, PaymentsEscrow, + PaymentsEscrowImplementation, GraphTallyCollector, } = m.useModule(MigrateHorizonCoreModule) return { - L2Curation, - L2CurationImplementation, - RewardsManager, - RewardsManagerImplementation, - HorizonStaking, - HorizonStakingImplementation, - GraphPayments, - PaymentsEscrow, + Graph_Proxy_L2Curation: L2Curation, + Implementation_L2Curation: L2CurationImplementation, + Graph_Proxy_RewardsManager: RewardsManager, + Implementation_RewardsManager: RewardsManagerImplementation, + Graph_Proxy_HorizonStaking: HorizonStaking, + Implementation_HorizonStaking: HorizonStakingImplementation, + Transparent_Proxy_GraphPayments: GraphPayments, + Implementation_GraphPayments: GraphPaymentsImplementation, + Transparent_Proxy_PaymentsEscrow: PaymentsEscrow, + Implementation_PaymentsEscrow: PaymentsEscrowImplementation, GraphTallyCollector, - Controller, + Controller: Controller, GraphProxyAdmin, - EpochManager, - L2GraphToken, - L2GraphTokenGateway, + Graph_Proxy_EpochManager: EpochManager, + Graph_Proxy_L2GraphToken: L2GraphToken, + Graph_Proxy_L2GraphTokenGateway: L2GraphTokenGateway, } }) diff --git a/packages/horizon/ignition/modules/migrate/migrate-4.ts b/packages/horizon/ignition/modules/migrate/migrate-4.ts index f0c14ce32..9290cc753 100644 --- a/packages/horizon/ignition/modules/migrate/migrate-4.ts +++ b/packages/horizon/ignition/modules/migrate/migrate-4.ts @@ -7,19 +7,25 @@ import { MigrateRewardsManagerGovernorModule } from '../periphery/RewardsManager export default buildModule('GraphHorizon_Migrate_4', (m) => { const { L2Curation, + L2CurationImplementation, } = m.useModule(MigrateCurationGovernorModule) const { RewardsManager, + RewardsManagerImplementation, } = m.useModule(MigrateRewardsManagerGovernorModule) const { HorizonStaking, + HorizonStakingImplementation, } = m.useModule(MigrateHorizonStakingGovernorModule) return { - L2Curation, - RewardsManager, - HorizonStaking, + Graph_Proxy_L2Curation: L2Curation, + Implementation_L2Curation: L2CurationImplementation, + Graph_Proxy_RewardsManager: RewardsManager, + Implementation_RewardsManager: RewardsManagerImplementation, + Graph_Proxy_HorizonStaking: HorizonStaking, + Implementation_HorizonStaking: HorizonStakingImplementation, } }) diff --git a/packages/horizon/ignition/modules/periphery/Curation.ts b/packages/horizon/ignition/modules/periphery/Curation.ts index 102512e4d..d93ffc678 100644 --- a/packages/horizon/ignition/modules/periphery/Curation.ts +++ b/packages/horizon/ignition/modules/periphery/Curation.ts @@ -20,14 +20,14 @@ export default buildModule('L2Curation', (m) => { const GraphCurationToken = m.contract('GraphCurationToken', GraphCurationTokenArtifact, []) - const L2Curation = deployWithGraphProxy(m, GraphProxyAdmin, { + const { proxy: L2Curation, implementation: L2CurationImplementation } = deployWithGraphProxy(m, GraphProxyAdmin, { name: 'L2Curation', artifact: CurationArtifact, initArgs: [Controller, GraphCurationToken, curationTaxPercentage, minimumCurationDeposit], }) m.call(L2Curation, 'setSubgraphService', [subgraphServiceAddress]) - return { L2Curation } + return { L2Curation, L2CurationImplementation } }) export const MigrateCurationDeployerModule = buildModule('L2CurationDeployer', (m: IgnitionModuleBuilder) => { @@ -62,5 +62,5 @@ export const MigrateCurationGovernorModule = buildModule('L2CurationGovernor', ( const L2Curation = upgradeGraphProxy(m, GraphProxyAdmin, L2CurationProxy, L2CurationImplementation, implementationMetadata) m.call(L2Curation, 'setSubgraphService', [subgraphServiceAddress]) - return { L2Curation } + return { L2Curation, L2CurationImplementation } }) diff --git a/packages/horizon/ignition/modules/periphery/EpochManager.ts b/packages/horizon/ignition/modules/periphery/EpochManager.ts index 993cf7fdc..a7e08bf22 100644 --- a/packages/horizon/ignition/modules/periphery/EpochManager.ts +++ b/packages/horizon/ignition/modules/periphery/EpochManager.ts @@ -12,13 +12,13 @@ export default buildModule('EpochManager', (m) => { const epochLength = m.getParameter('epochLength') - const EpochManager = deployWithGraphProxy(m, GraphProxyAdmin, { + const { proxy: EpochManager, implementation: EpochManagerImplementation } = deployWithGraphProxy(m, GraphProxyAdmin, { name: 'EpochManager', artifact: EpochManagerArtifact, initArgs: [Controller, epochLength], }) - return { EpochManager } + return { EpochManager, EpochManagerImplementation } }) export const MigrateEpochManagerModule = buildModule('EpochManager', (m) => { diff --git a/packages/horizon/ignition/modules/periphery/GraphToken.ts b/packages/horizon/ignition/modules/periphery/GraphToken.ts index 9b55755cb..dd8c1a129 100644 --- a/packages/horizon/ignition/modules/periphery/GraphToken.ts +++ b/packages/horizon/ignition/modules/periphery/GraphToken.ts @@ -16,7 +16,7 @@ export default buildModule('L2GraphToken', (m) => { const governor = m.getAccount(1) const initialSupply = m.getParameter('initialSupply') - const L2GraphToken = deployWithGraphProxy(m, GraphProxyAdmin, { + const { proxy: L2GraphToken, implementation: L2GraphTokenImplementation } = deployWithGraphProxy(m, GraphProxyAdmin, { name: 'L2GraphToken', artifact: GraphTokenArtifact, initArgs: [deployer], @@ -31,7 +31,7 @@ export default buildModule('L2GraphToken', (m) => { const transferOwnershipCall = m.call(L2GraphToken, 'transferOwnership', [governor], { after: [mintCall, renounceMinterCall, addMinterRewardsManagerCall, addMinterGatewayCall] }) m.call(L2GraphToken, 'acceptOwnership', [], { from: governor, after: [transferOwnershipCall] }) - return { L2GraphToken } + return { L2GraphToken, L2GraphTokenImplementation } }) export const MigrateGraphTokenModule = buildModule('L2GraphToken', (m) => { diff --git a/packages/horizon/ignition/modules/periphery/GraphTokenGateway.ts b/packages/horizon/ignition/modules/periphery/GraphTokenGateway.ts index 5ddaf7860..fc679e8ad 100644 --- a/packages/horizon/ignition/modules/periphery/GraphTokenGateway.ts +++ b/packages/horizon/ignition/modules/periphery/GraphTokenGateway.ts @@ -13,14 +13,14 @@ export default buildModule('L2GraphTokenGateway', (m) => { const pauseGuardian = m.getParameter('pauseGuardian') - const L2GraphTokenGateway = deployWithGraphProxy(m, GraphProxyAdmin, { + const { proxy: L2GraphTokenGateway, implementation: L2GraphTokenGatewayImplementation } = deployWithGraphProxy(m, GraphProxyAdmin, { name: 'L2GraphTokenGateway', artifact: GraphTokenGatewayArtifact, initArgs: [Controller], }) m.call(L2GraphTokenGateway, 'setPauseGuardian', [pauseGuardian]) - return { L2GraphTokenGateway } + return { L2GraphTokenGateway, L2GraphTokenGatewayImplementation } }) export const MigrateGraphTokenGatewayModule = buildModule('L2GraphTokenGateway', (m) => { diff --git a/packages/horizon/ignition/modules/periphery/RewardsManager.ts b/packages/horizon/ignition/modules/periphery/RewardsManager.ts index 9fa043ee2..c1dc8e285 100644 --- a/packages/horizon/ignition/modules/periphery/RewardsManager.ts +++ b/packages/horizon/ignition/modules/periphery/RewardsManager.ts @@ -17,7 +17,7 @@ export default buildModule('RewardsManager', (m) => { const subgraphAvailabilityOracle = m.getParameter('subgraphAvailabilityOracle') const subgraphServiceAddress = m.getParameter('subgraphServiceAddress') - const RewardsManager = deployWithGraphProxy(m, GraphProxyAdmin, { + const { proxy: RewardsManager, implementation: RewardsManagerImplementation } = deployWithGraphProxy(m, GraphProxyAdmin, { name: 'RewardsManager', artifact: RewardsManagerArtifact, initArgs: [Controller], @@ -26,7 +26,7 @@ export default buildModule('RewardsManager', (m) => { m.call(RewardsManager, 'setIssuancePerBlock', [issuancePerBlock]) m.call(RewardsManager, 'setSubgraphService', [subgraphServiceAddress]) - return { RewardsManager } + return { RewardsManager, RewardsManagerImplementation } }) export const MigrateRewardsManagerDeployerModule = buildModule('RewardsManagerDeployer', (m: IgnitionModuleBuilder) => { @@ -62,5 +62,5 @@ export const MigrateRewardsManagerGovernorModule = buildModule('RewardsManagerGo const RewardsManager = upgradeGraphProxy(m, GraphProxyAdmin, RewardsManagerProxy, RewardsManagerImplementation, implementationMetadata) m.call(RewardsManager, 'setSubgraphService', [subgraphServiceAddress]) - return { RewardsManager } + return { RewardsManager, RewardsManagerImplementation } }) diff --git a/packages/horizon/ignition/modules/periphery/periphery.ts b/packages/horizon/ignition/modules/periphery/periphery.ts index 276455154..f02f9b2cc 100644 --- a/packages/horizon/ignition/modules/periphery/periphery.ts +++ b/packages/horizon/ignition/modules/periphery/periphery.ts @@ -14,11 +14,11 @@ export default buildModule('GraphHorizon_Periphery', (m) => { const { Controller } = m.useModule(ControllerModule) const { GraphProxyAdmin } = m.useModule(GraphProxyAdminModule) - const { EpochManager } = m.useModule(EpochManagerModule) - const { L2Curation } = m.useModule(CurationModule) - const { RewardsManager } = m.useModule(RewardsManagerModule) - const { L2GraphTokenGateway } = m.useModule(GraphTokenGatewayModule) - const { L2GraphToken } = m.useModule(GraphTokenModule) + const { EpochManager, EpochManagerImplementation } = m.useModule(EpochManagerModule) + const { L2Curation, L2CurationImplementation } = m.useModule(CurationModule) + const { RewardsManager, RewardsManagerImplementation } = m.useModule(RewardsManagerModule) + const { L2GraphTokenGateway, L2GraphTokenGatewayImplementation } = m.useModule(GraphTokenGatewayModule) + const { L2GraphToken, L2GraphTokenImplementation } = m.useModule(GraphTokenModule) m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('EpochManager')), EpochManager], { id: 'setContractProxy_EpochManager' }) m.call(Controller, 'setContractProxy', [ethers.keccak256(ethers.toUtf8Bytes('RewardsManager')), RewardsManager], { id: 'setContractProxy_RewardsManager' }) @@ -30,11 +30,16 @@ export default buildModule('GraphHorizon_Periphery', (m) => { return { Controller, EpochManager, + EpochManagerImplementation, L2Curation, + L2CurationImplementation, GraphProxyAdmin, L2GraphToken, + L2GraphTokenImplementation, L2GraphTokenGateway, + L2GraphTokenGatewayImplementation, RewardsManager, + RewardsManagerImplementation, } }) diff --git a/packages/horizon/ignition/modules/proxy/GraphProxy.ts b/packages/horizon/ignition/modules/proxy/GraphProxy.ts index 997ad65c1..efc6fe4ef 100644 --- a/packages/horizon/ignition/modules/proxy/GraphProxy.ts +++ b/packages/horizon/ignition/modules/proxy/GraphProxy.ts @@ -73,5 +73,5 @@ export function deployWithGraphProxy( m.call(proxyAdmin, 'acceptProxyAndCall', [implementation, proxy, m.encodeFunctionCall(implementation, 'initialize', metadata.initArgs)], options) } - return proxy + return { proxy, implementation } } diff --git a/packages/horizon/package.json b/packages/horizon/package.json index 89fda2213..b839c861c 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -15,7 +15,7 @@ "lint:sol": "prettier --write contracts/**/*.sol test/**/*.sol && solhint --noPrompt --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build dist cache cache_forge typechain-types", - "build": "forge build --skip test && BUILD_RUN=true hardhat compile", + "build": "BUILD_RUN=true hardhat compile", "test": "forge test && hardhat test" }, "devDependencies": { diff --git a/packages/horizon/scripts/deploy.ts b/packages/horizon/scripts/deploy.ts deleted file mode 100644 index 1b6eeac37..000000000 --- a/packages/horizon/scripts/deploy.ts +++ /dev/null @@ -1,21 +0,0 @@ -import hre, { ignition } from 'hardhat' -import { IgnitionHelper } from 'hardhat-graph-protocol/sdk' - -import DeployModule from '../ignition/modules/deploy' - -async function main() { - const HorizonConfig = IgnitionHelper.loadConfig('./ignition/configs/', 'horizon', hre.network.name) - - // Deploy Horizon - const deployment = await ignition.deploy(DeployModule, { - displayUi: true, - parameters: HorizonConfig, - }) - - IgnitionHelper.saveAddressBook(deployment, hre.network.config.chainId) -} - -main().catch((error) => { - console.error(error) - process.exit(1) -}) diff --git a/packages/horizon/scripts/migrate.ts b/packages/horizon/scripts/migrate.ts deleted file mode 100644 index c08f363da..000000000 --- a/packages/horizon/scripts/migrate.ts +++ /dev/null @@ -1,98 +0,0 @@ -import hre, { ignition } from 'hardhat' -import { IgnitionHelper } from 'hardhat-graph-protocol/sdk' - -import MigrateModuleStep1 from '../ignition/modules/migrate/migrate-1' -import MigrateModuleStep2 from '../ignition/modules/migrate/migrate-2' -import MigrateModuleStep3 from '../ignition/modules/migrate/migrate-3' -import MigrateModuleStep4 from '../ignition/modules/migrate/migrate-4' - -async function main() { - console.log(getHorizonBanner()) - const HorizonMigrateConfig = IgnitionHelper.loadConfig('./ignition/configs/', 'horizon-migrate', `horizon-${hre.network.name}`) - - const signers = await hre.ethers.getSigners() - const deployer = signers[0] - const governor = signers[1] - - console.log('Using deployer account:', deployer.address) - console.log('Using governor account:', governor.address) - - console.log('========== Running migration: step 1 ==========') - const { - GraphPaymentsProxy, - PaymentsEscrowProxy, - } = await ignition.deploy(MigrateModuleStep1, { - displayUi: true, - parameters: HorizonMigrateConfig, - deploymentId: `horizon-${hre.network.name}`, - }) - - let patchedHorizonMigrateConfig = IgnitionHelper.patchConfig(HorizonMigrateConfig, { - HorizonProxiesGovernor: { - graphPaymentsAddress: GraphPaymentsProxy.target, - paymentsEscrowAddress: PaymentsEscrowProxy.target, - }, - }) - - console.log('========== Running migration: step 2 ==========') - await ignition.deploy(MigrateModuleStep2, { - displayUi: true, - parameters: patchedHorizonMigrateConfig, - deploymentId: `horizon-${hre.network.name}`, - defaultSender: governor.address, - }) - - console.log('========== Running migration: step 3 ==========') - const deployment = await ignition.deploy(MigrateModuleStep3, { - displayUi: true, - parameters: HorizonMigrateConfig, - deploymentId: `horizon-${hre.network.name}`, - }) - - IgnitionHelper.saveAddressBook(deployment, hre.network.config.chainId) - - patchedHorizonMigrateConfig = IgnitionHelper.patchConfig(patchedHorizonMigrateConfig, { - HorizonStakingGovernor: { - horizonStakingImplementationAddress: deployment.HorizonStakingImplementation.target, - }, - L2CurationGovernor: { - curationImplementationAddress: deployment.L2CurationImplementation.target, - }, - RewardsManagerGovernor: { - rewardsManagerImplementationAddress: deployment.RewardsManagerImplementation.target, - }, - }) - - console.log('========== Running migration: step 4 ==========') - await ignition.deploy(MigrateModuleStep4, { - displayUi: true, - parameters: patchedHorizonMigrateConfig, - deploymentId: `horizon-${hre.network.name}`, - defaultSender: governor.address, - }) - - console.log('Migration successful! πŸŽ‰') -} - -main().catch((error) => { - console.error(error) - process.exit(1) -}) - -function getHorizonBanner(): string { - return ` -β–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•— -β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘ -β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘ -β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ -β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ -β•šβ•β• β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•šβ•β•β•šβ•β•β•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•β• - -β–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— -β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β• -β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— -β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β• -β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— - β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β•β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β• -` -} diff --git a/packages/horizon/tasks/deploy.ts b/packages/horizon/tasks/deploy.ts new file mode 100644 index 000000000..5e17d987a --- /dev/null +++ b/packages/horizon/tasks/deploy.ts @@ -0,0 +1,143 @@ +/* eslint-disable no-case-declarations */ +import { task, types } from 'hardhat/config' +import { IgnitionHelper } from 'hardhat-graph-protocol/sdk' + +import type { AddressBook } from '../../hardhat-graph-protocol/src/sdk/address-book' +import type { HardhatRuntimeEnvironment } from 'hardhat/types' + +import DeployModule from '../ignition/modules/deploy' + +task('deploy:protocol', 'Deploy a new version of the Graph Protocol Horizon contracts - no data services deployed') + .setAction(async (_, hre: HardhatRuntimeEnvironment) => { + const graph = hre.graph() + + // Load configuration for the deployment + console.log('\n========== βš™οΈ Deployment configuration ==========') + const { config: HorizonConfig, file } = IgnitionHelper.loadConfig('./ignition/configs/', 'horizon', hre.network.name) + console.log(`Loaded migration configuration from ${file}`) + + // Deploy the contracts + console.log(`\n========== 🚧 Deploy protocol ==========`) + const deployment = await hre.ignition.deploy(DeployModule, { + displayUi: true, + parameters: HorizonConfig, + }) + + // Save the addresses to the address book + console.log('\n========== πŸ“– Updating address book ==========') + IgnitionHelper.saveToAddressBook(deployment, hre.network.config.chainId, graph.horizon!.addressBook) + console.log(`Address book at ${graph.horizon!.addressBook.file} updated!`) + }) + +task('deploy:migrate', 'Upgrade an existing version of the Graph Protocol v1 to Horizon - no data services deployed') + .addOptionalParam('step', 'Migration step to run (1, 2, 3 or 4) - runs all if not provided', undefined, types.int) + .addFlag('patchConfig', 'Patch configuration file using address book values - does not save changes') + .setAction(async (args, hre: HardhatRuntimeEnvironment) => { + // Task parameters + const step: number = args.step ?? 0 + const patchConfig: boolean = args.patchConfig ?? false + + const graph = hre.graph() + console.log(getHorizonBanner()) + + // Migration step to run + console.log('\n========== πŸ—οΈ Migration steps ==========') + const validSteps = [0, 1, 2, 3, 4] + if (!validSteps.includes(step)) { + console.error(`Error: Invalid migration step provided: ${step}`) + console.error(`Valid steps are: ${validSteps.join(', ')}`) + process.exit(1) + } + console.log(`Running migration step: ${step}`) + + // Load configuration for the migration + console.log('\n========== βš™οΈ Deployment configuration ==========') + const { config: HorizonMigrateConfig, file } = IgnitionHelper.loadConfig('./ignition/configs/', 'horizon-migrate', `horizon-${hre.network.name}`) + console.log(`Loaded migration configuration from ${file}`) + + // Display the deployer -- this also triggers the secure accounts prompt if being used + console.log('\n========== πŸ”‘ Deployer account ==========') + const signers = await hre.ethers.getSigners() + const deployer = signers[0] + console.log('Using deployer account:', deployer.address) + const balance = await hre.ethers.provider.getBalance(deployer.address) + console.log('Deployer balance:', hre.ethers.formatEther(balance), 'ETH') + if (balance === 0n) { + console.error('Error: Deployer account has no ETH balance') + process.exit(1) + } + + // Run migration step + console.log(`\n========== 🚧 Running migration: step ${step} ==========`) + const MigrationModule = require(`../ignition/modules/migrate/migrate-${step}`).default + const deployment = await hre.ignition.deploy( + MigrationModule, + { + displayUi: true, + parameters: patchConfig ? _patchStepConfig(step, HorizonMigrateConfig, graph.horizon!.addressBook) : HorizonMigrateConfig, + deploymentId: `horizon-${hre.network.name}`, + }) + + // Update address book + console.log('\n========== πŸ“– Updating address book ==========') + IgnitionHelper.saveToAddressBook(deployment, hre.network.config.chainId, graph.horizon!.addressBook) + console.log(`Address book at ${graph.horizon!.addressBook.file} updated!`) + + console.log('\n\nπŸŽ‰ ✨ πŸš€ βœ… Migration successful! πŸŽ‰ ✨ πŸš€ βœ…') + }) + +// This function patches the Ignition configuration object using an address book to fill in the gaps +// The resulting configuration is not saved back to the configuration file +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function _patchStepConfig(step: number, config: any, addressBook: AddressBook): any { + let patchedConfig = config + + switch (step) { + case 2: + const GraphPayments = addressBook.getEntry('GraphPayments') + const PaymentsEscrow = addressBook.getEntry('PaymentsEscrow') + patchedConfig = IgnitionHelper.patchConfig(config, { + HorizonProxiesGovernor: { + graphPaymentsAddress: GraphPayments.address, + paymentsEscrowAddress: PaymentsEscrow.address, + }, + }) + break + case 4: + const HorizonStaking = addressBook.getEntry('HorizonStaking') + const L2Curation = addressBook.getEntry('L2Curation') + const RewardsManager = addressBook.getEntry('RewardsManager') + patchedConfig = IgnitionHelper.patchConfig(patchedConfig, { + HorizonStakingGovernor: { + horizonStakingImplementationAddress: HorizonStaking.implementation, + }, + L2CurationGovernor: { + curationImplementationAddress: L2Curation.implementation, + }, + RewardsManagerGovernor: { + rewardsManagerImplementationAddress: RewardsManager.implementation, + }, + }) + break + } + + return patchedConfig +} + +function getHorizonBanner(): string { + return ` + β–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•— + β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘ + β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘ + β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ + β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ + β•šβ•β• β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•šβ•β•β•šβ•β•β•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•β• + + β–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— + β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β• + β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— + β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β• + β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— + β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β•β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β• + ` +} diff --git a/packages/horizon/types/hardhat-graph-protocol.d.ts b/packages/horizon/types/hardhat-graph-protocol.d.ts new file mode 100644 index 000000000..8b5985269 --- /dev/null +++ b/packages/horizon/types/hardhat-graph-protocol.d.ts @@ -0,0 +1,45 @@ +// TypeScript does not resolve correctly the type extensions when they are symlinked from the same monorepo. +// So we need to re-type it... this file should be a copy of hardhat-graph-protocol/src/type-extensions.ts +import 'hardhat/types/config' +import 'hardhat/types/runtime' +import type { GraphDeployments, GraphRuntimeEnvironment, GraphRuntimeEnvironmentOptions } from 'hardhat-graph-protocol' + +declare module 'hardhat/types/runtime' { + interface HardhatRuntimeEnvironment { + graph: (opts?: GraphRuntimeEnvironmentOptions) => GraphRuntimeEnvironment + } +} + +declare module 'hardhat/types/config' { + interface HardhatConfig { + graph: GraphRuntimeEnvironmentOptions + } + + interface HardhatUserConfig { + graph: GraphRuntimeEnvironmentOptions + } + + interface HardhatNetworkConfig { + deployments?: GraphDeployments + } + + interface HardhatNetworkUserConfig { + deployments?: GraphDeployments + } + + interface HttpNetworkConfig { + deployments?: GraphDeployments + } + + interface HttpNetworkUserConfig { + deployments?: GraphDeployments + } + + interface ProjectPathsConfig { + graph?: string + } + + interface ProjectPathsUserConfig { + graph?: string + } +} diff --git a/packages/subgraph-service/types/hardhat-graph-protocol.d.ts b/packages/subgraph-service/types/hardhat-graph-protocol.d.ts index ab3c30b4b..8b5985269 100644 --- a/packages/subgraph-service/types/hardhat-graph-protocol.d.ts +++ b/packages/subgraph-service/types/hardhat-graph-protocol.d.ts @@ -2,7 +2,7 @@ // So we need to re-type it... this file should be a copy of hardhat-graph-protocol/src/type-extensions.ts import 'hardhat/types/config' import 'hardhat/types/runtime' -import type { GraphDeployments, GraphRuntimeEnvironment, GraphRuntimeEnvironmentOptions } from 'hardhat-graph-protocol/src/types' +import type { GraphDeployments, GraphRuntimeEnvironment, GraphRuntimeEnvironmentOptions } from 'hardhat-graph-protocol' declare module 'hardhat/types/runtime' { interface HardhatRuntimeEnvironment { diff --git a/yarn.lock b/yarn.lock index 837fcb1a2..f21ea08c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14468,7 +14468,9 @@ __metadata: "@graphprotocol/horizon": "workspace:^0.0.1" "@graphprotocol/subgraph-service": "workspace:^0.0.1" "@nomicfoundation/hardhat-ethers": "npm:^3.0.8" + "@nomicfoundation/hardhat-ignition": "npm:^0.15.9" "@nomicfoundation/hardhat-verify": "npm:^2.0.12" + "@nomicfoundation/ignition-core": "npm:^0.15.9" "@types/chai": "npm:^4.0.0" "@types/debug": "npm:^4.1.12" "@types/mocha": "npm:^10.0.9" From 1b9914df2751d7ea0a176c512582e0bf382a6c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 14 Feb 2025 17:20:14 -0300 Subject: [PATCH 02/15] feat: refactor deplyoment tooling for subgraph service MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- .gitignore | 3 + packages/hardhat-graph-protocol/src/config.ts | 6 +- .../src/sdk/address-book.ts | 18 +- .../deployments/subgraph-service/contracts.ts | 2 +- .../src/sdk/hardhat.base.config.ts | 14 +- .../src/sdk/ignition/ignition.ts | 45 ++-- packages/horizon/README.md | 11 +- .../configs/horizon-migrate.default.json5 | 16 +- ...n-migrate.horizon-virtualArbitrumOne.json5 | 50 ---- packages/horizon/tasks/deploy.ts | 20 +- packages/subgraph-service/addresses.json | 34 +-- packages/subgraph-service/hardhat.config.ts | 8 +- .../subgraph-service-migrate.default.json5 | 25 +- .../configs/subgraph-service.default.json5 | 20 +- .../ignition/modules/DisputeManager.ts | 11 +- .../ignition/modules/Proxies.ts | 8 +- .../ignition/modules/SubgraphService.ts | 13 +- .../ignition/modules/migrate/migrate-1.ts | 16 +- .../ignition/modules/migrate/migrate-2.ts | 11 +- packages/subgraph-service/scripts/deploy.ts | 76 ------- packages/subgraph-service/scripts/migrate.ts | 50 ---- packages/subgraph-service/tasks/deploy.ts | 215 ++++++++++++++++++ packages/subgraph-service/tsconfig.json | 1 + 23 files changed, 368 insertions(+), 305 deletions(-) delete mode 100644 packages/horizon/ignition/configs/horizon-migrate.horizon-virtualArbitrumOne.json5 delete mode 100644 packages/subgraph-service/scripts/deploy.ts delete mode 100644 packages/subgraph-service/scripts/migrate.ts create mode 100644 packages/subgraph-service/tasks/deploy.ts diff --git a/.gitignore b/.gitignore index 5861633e5..de3ae9b9d 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ addresses-fork.json # Forge artifacts cache_forge + # Graph client .graphclient @@ -62,4 +63,6 @@ tx-builder-*.json **/chain-1377/ **/horizon-localhost/ **/horizon-hardhat/ +**/subgraph-service-localhost/ +**/subgraph-service-hardhat/ !**/ignition/**/artifacts/ diff --git a/packages/hardhat-graph-protocol/src/config.ts b/packages/hardhat-graph-protocol/src/config.ts index acd966db0..9f2e2af82 100644 --- a/packages/hardhat-graph-protocol/src/config.ts +++ b/packages/hardhat-graph-protocol/src/config.ts @@ -28,11 +28,7 @@ export function getAddressBookPath( } const normalizedAddressBookPath = normalizePath(addressBookPath, hre.config.paths.graph) - if (!fs.existsSync(normalizedAddressBookPath)) { - throw new GraphPluginError(`Address book not found: ${normalizedAddressBookPath}`) - } - - logDebug(`Address book path found: ${normalizedAddressBookPath}`) + logDebug(`Address book path: ${normalizedAddressBookPath}`) return normalizedAddressBookPath } diff --git a/packages/hardhat-graph-protocol/src/sdk/address-book.ts b/packages/hardhat-graph-protocol/src/sdk/address-book.ts index 884d91c35..3c9634bec 100644 --- a/packages/hardhat-graph-protocol/src/sdk/address-book.ts +++ b/packages/hardhat-graph-protocol/src/sdk/address-book.ts @@ -76,11 +76,16 @@ export abstract class AddressBook< this.chainId = _chainId logDebug(`Loading address book from ${this.file}.`) - if (!fs.existsSync(this.file)) throw new Error(`Address book path provided does not exist!`) + + // Create empty address book if file doesn't exist + if (!fs.existsSync(this.file)) { + const emptyAddressBook = { [this.chainId]: {} } + fs.writeFileSync(this.file, JSON.stringify(emptyAddressBook, null, 2)) + logDebug(`Created new address book at ${this.file}`) + } // Load address book and validate its shape - // If it's empty, initialize it with an empty object - const fileContents = JSON.parse(fs.readFileSync(this.file, 'utf8') || '{}') + const fileContents = JSON.parse(fs.readFileSync(this.file, 'utf8')) if (!fileContents[this.chainId]) { fileContents[this.chainId] = {} } @@ -98,6 +103,13 @@ export abstract class AddressBook< return this.validContracts } + entryExists(name: string): boolean { + if (!this.isContractName(name)) { + throw new Error(`Contract name ${name} is not a valid contract name`) + } + return this.addressBook[this.chainId][name] !== undefined + } + /** * Get an entry from the address book * diff --git a/packages/hardhat-graph-protocol/src/sdk/deployments/subgraph-service/contracts.ts b/packages/hardhat-graph-protocol/src/sdk/deployments/subgraph-service/contracts.ts index 7d0ef1ebc..1e770e1ff 100644 --- a/packages/hardhat-graph-protocol/src/sdk/deployments/subgraph-service/contracts.ts +++ b/packages/hardhat-graph-protocol/src/sdk/deployments/subgraph-service/contracts.ts @@ -25,7 +25,7 @@ export const SubgraphServiceContractNameList = [ 'DisputeManager', ] as const -const root = path.resolve(__dirname, '../../../../..') // hardhat-graph-protocol root +const root = path.resolve(__dirname, '../../../..') // hardhat-graph-protocol root export const CONTRACTS_ARTIFACTS_PATH = path.resolve(root, 'node_modules', '@graphprotocol/contracts/build/contracts') export const SUBGRAPH_SERVICE_ARTIFACTS_PATH = path.resolve(root, 'node_modules', '@graphprotocol/subgraph-service/build/contracts') diff --git a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts index 49731f0c8..43b3dc509 100644 --- a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts +++ b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts @@ -48,7 +48,8 @@ export const networksUserConfig: BaseNetworksUserConfig = { mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect', }, deployments: { - horizon: require.resolve('@graphprotocol/horizon/addresses-local.json'), + horizon: resolveLocalAddressBook('@graphprotocol/horizon/addresses.json'), + subgraphService: resolveLocalAddressBook('@graphprotocol/subgraph-service/addresses.json'), }, }, localhost: { @@ -58,7 +59,8 @@ export const networksUserConfig: BaseNetworksUserConfig = { enabled: true, }, deployments: { - horizon: require.resolve('@graphprotocol/horizon/addresses-local.json'), + horizon: resolveLocalAddressBook('@graphprotocol/horizon/addresses.json'), + subgraphService: resolveLocalAddressBook('@graphprotocol/subgraph-service/addresses.json'), }, }, arbitrumOne: { @@ -77,6 +79,13 @@ export const networksUserConfig: BaseNetworksUserConfig = { }, } +// Local address books are not commited to GitHub so they might not exist +// require.resolve will throw an error if the file does not exist, so we hack it a bit +function resolveLocalAddressBook(path: string) { + const resolvedPath = require.resolve(path) + return resolvedPath.replace('addresses.json', 'addresses-local.json') +} + type BaseHardhatConfig = HardhatUserConfig & { etherscan: Partial } & { graph: GraphRuntimeEnvironmentOptions } & @@ -91,6 +100,7 @@ export const hardhatBaseConfig: BaseHardhatConfig = { graph: { deployments: { horizon: require.resolve('@graphprotocol/horizon/addresses.json'), + subgraphService: require.resolve('@graphprotocol/subgraph-service/addresses.json'), }, }, etherscan: etherscanUserConfig, diff --git a/packages/hardhat-graph-protocol/src/sdk/ignition/ignition.ts b/packages/hardhat-graph-protocol/src/sdk/ignition/ignition.ts index 8bc551d68..fdf73fcde 100644 --- a/packages/hardhat-graph-protocol/src/sdk/ignition/ignition.ts +++ b/packages/hardhat-graph-protocol/src/sdk/ignition/ignition.ts @@ -5,7 +5,8 @@ require('json5/lib/register') import fs from 'fs' import path from 'path' -import { AddressBook } from '../address-book' + +import type { AddressBook } from '../address-book' export function loadConfig(configPath: string, prefix: string, networkName: string): any { const configFileCandidates = [ @@ -24,36 +25,22 @@ export function loadConfig(configPath: string, prefix: string, networkName: stri } export function patchConfig(jsonData: any, patches: Record) { - function recursivePatch(obj: any) { - if (typeof obj === 'object' && obj !== null) { - for (const key in obj) { - if (key in patches) { - obj[key] = patches[key] + function recursivePatch(obj: any, patchObj: any) { + if (typeof obj === 'object' && obj !== null && typeof patchObj === 'object' && patchObj !== null) { + for (const key in patchObj) { + if (obj.hasOwnProperty(key) && typeof obj[key] === 'object' && typeof patchObj[key] === 'object') { + // Both are objects, recursively merge + recursivePatch(obj[key], patchObj[key]) } else { - recursivePatch(obj[key]) + // Either not an object or new key, directly assign + obj[key] = patchObj[key] } } } + return obj } - recursivePatch(jsonData) - return jsonData -} - -export function mergeConfigs(obj1: any, obj2: any) { - const merged = { ...obj1 } - - for (const key in obj2) { - if (obj2.hasOwnProperty(key)) { - if (typeof obj2[key] === 'object' && obj2[key] !== null && obj1[key]) { - merged[key] = mergeConfigs(obj1[key], obj2[key]) - } else { - merged[key] = obj2[key] - } - } - } - - return merged + return recursivePatch(jsonData, patches) } export function saveToAddressBook( @@ -71,7 +58,7 @@ export function saveToAddressBook { // Task parameters @@ -42,7 +56,7 @@ task('deploy:migrate', 'Upgrade an existing version of the Graph Protocol v1 to // Migration step to run console.log('\n========== πŸ—οΈ Migration steps ==========') - const validSteps = [0, 1, 2, 3, 4] + const validSteps = [1, 2, 3, 4] if (!validSteps.includes(step)) { console.error(`Error: Invalid migration step provided: ${step}`) console.error(`Valid steps are: ${validSteps.join(', ')}`) @@ -83,7 +97,7 @@ task('deploy:migrate', 'Upgrade an existing version of the Graph Protocol v1 to IgnitionHelper.saveToAddressBook(deployment, hre.network.config.chainId, graph.horizon!.addressBook) console.log(`Address book at ${graph.horizon!.addressBook.file} updated!`) - console.log('\n\nπŸŽ‰ ✨ πŸš€ βœ… Migration successful! πŸŽ‰ ✨ πŸš€ βœ…') + console.log('\n\nπŸŽ‰ ✨ πŸš€ βœ… Migration complete! πŸŽ‰ ✨ πŸš€ βœ…') }) // This function patches the Ignition configuration object using an address book to fill in the gaps diff --git a/packages/subgraph-service/addresses.json b/packages/subgraph-service/addresses.json index 0fb2088ec..7a73a41bf 100644 --- a/packages/subgraph-service/addresses.json +++ b/packages/subgraph-service/addresses.json @@ -1,34 +1,2 @@ { - "421614": { - "SubgraphService": { - "address": "0x2268247782f4b7AdB2DA810EFD6e43B27a37af54" - }, - "DisputeManager": { - "address": "0x8e436E815226C8Bd5e775C7FF693DAe6a94bE7d1" - }, - "ServiceRegistry": { - "address": "0x888541878CbDDEd880Cd58c728f1Af5C47343F86", - "proxy": true, - "implementation": { - "address": "0x05E732280bf9F37054346Cb83f5Fd58C5B44F6A8" - } - }, - "L2Curation": { - "address": "0xDe761f075200E75485F4358978FB4d1dC8644FD5", - "proxy": true, - "implementation": { - "address": "0xd90022aB67920212D0F902F5c427DE82732DE136" - } - }, - "SubgraphNFT": { - "address": "0xF21Df5BbA7EB9b54D8F60C560aFb9bA63e6aED1A" - }, - "L2GNS": { - "address": "0x3133948342F35b8699d8F94aeE064AbB76eDe965", - "proxy": true, - "implementation": { - "address": "0x00CBF5024d454255577Bf2b0fB6A43328a6828c9" - } - } - } -} +} \ No newline at end of file diff --git a/packages/subgraph-service/hardhat.config.ts b/packages/subgraph-service/hardhat.config.ts index 8239cb494..6683e122a 100644 --- a/packages/subgraph-service/hardhat.config.ts +++ b/packages/subgraph-service/hardhat.config.ts @@ -10,6 +10,8 @@ import 'hardhat-contract-sizer' import 'hardhat-secure-accounts' import 'solidity-docgen' +import './tasks/deploy' + // Skip importing hardhat-graph-protocol when building the project, it has circular dependency if (process.env.BUILD_RUN !== 'true') { require('hardhat-graph-protocol') @@ -26,12 +28,6 @@ const config: HardhatUserConfig = { }, }, }, - graph: { - deployments: { - ...hardhatBaseConfig.graph?.deployments, - subgraphService: './addresses.json', - }, - }, } export default config diff --git a/packages/subgraph-service/ignition/configs/subgraph-service-migrate.default.json5 b/packages/subgraph-service/ignition/configs/subgraph-service-migrate.default.json5 index d8ce79391..8f3c78b29 100644 --- a/packages/subgraph-service/ignition/configs/subgraph-service-migrate.default.json5 +++ b/packages/subgraph-service/ignition/configs/subgraph-service-migrate.default.json5 @@ -1,29 +1,34 @@ { "$global": { - // Accounts "governor": "0x72ee30d43Fb5A90B3FE983156C5d2fBE6F6d07B3", "arbitrator": "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0", // Addresses for contracts deployed in the original Graph Protocol "controllerAddress": "0x9DB3ee191681f092607035d9BDA6e59FbEaCa695", - "curationAddress": "0xDe761f075200E75485F4358978FB4d1dC8644FD5", - "graphTallyCollectorAddress": "0x0000000000000000000000000000000000000000", - // Must be set for step 2 of the migration - "disputeManagerAddress": "0x0000000000000000000000000000000000000000", - "disputeManagerProxyAdminAddress": "0x0000000000000000000000000000000000000000", - "subgraphServiceAddress": "0x0000000000000000000000000000000000000000", - "subgraphServiceProxyAdminAddress": "0x0000000000000000000000000000000000000000" + // Must be set for step 2 of the deployment + "disputeManagerProxyAddress": "" }, "DisputeManager": { "disputePeriod": 2419200, "disputeDeposit": "10000000000000000000000n", "fishermanRewardCut": 500000, - "maxSlashingCut": 1000000 + "maxSlashingCut": 1000000, + + // Must be set for step 2 of the deployment + "disputeManagerProxyAdminAddress": "" }, "SubgraphService": { "minimumProvisionTokens": "100000000000000000000000n", "maximumDelegationRatio": 16, - "stakeToFeesRatio": 2 + "stakeToFeesRatio": 2, + + // Addresses for contracts deployed in the original Graph Protocol + "curationAddress": "0xDe761f075200E75485F4358978FB4d1dC8644FD5", + + // Must be set for step 2 of the deployment + "subgraphServiceProxyAddress": "", + "subgraphServiceProxyAdminAddress": "", + "graphTallyCollectorAddress": "" } } diff --git a/packages/subgraph-service/ignition/configs/subgraph-service.default.json5 b/packages/subgraph-service/ignition/configs/subgraph-service.default.json5 index 12db4cf12..2f15d8f51 100644 --- a/packages/subgraph-service/ignition/configs/subgraph-service.default.json5 +++ b/packages/subgraph-service/ignition/configs/subgraph-service.default.json5 @@ -1,16 +1,30 @@ { "$global": { - "arbitrator": "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0" + "governor": "0x72ee30d43Fb5A90B3FE983156C5d2fBE6F6d07B3", + "arbitrator": "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0", + + // Must be set for step 2 of the deployment + "controllerAddress": "", + "disputeManagerProxyAddress": "" }, "DisputeManager": { "disputePeriod": 2419200, "disputeDeposit": "10000000000000000000000n", "fishermanRewardCut": 500000, - "maxSlashingCut": 1000000 + "maxSlashingCut": 1000000, + + // Must be set for step 2 of the deployment + "disputeManagerProxyAdminAddress": "", }, "SubgraphService": { "minimumProvisionTokens": "100000000000000000000000n", "maximumDelegationRatio": 16, - "stakeToFeesRatio": 2 + "stakeToFeesRatio": 2, + + // Must be set for step 2 of the deployment + "subgraphServiceProxyAddress": "", + "subgraphServiceProxyAdminAddress": "", + "curationAddress": "", + "graphTallyCollectorAddress": "" } } diff --git a/packages/subgraph-service/ignition/modules/DisputeManager.ts b/packages/subgraph-service/ignition/modules/DisputeManager.ts index 0da9b7dad..c3574f6d9 100644 --- a/packages/subgraph-service/ignition/modules/DisputeManager.ts +++ b/packages/subgraph-service/ignition/modules/DisputeManager.ts @@ -2,13 +2,14 @@ import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' import { deployImplementation } from '@graphprotocol/horizon/ignition/modules/proxy/implementation' import { upgradeTransparentUpgradeableProxy } from '@graphprotocol/horizon/ignition/modules/proxy/TransparentUpgradeableProxy' +import DisputeManagerArtifact from '../../build/contracts/contracts/DisputeManager.sol/DisputeManager.json' import ProxyAdminArtifact from '@openzeppelin/contracts/build/contracts/ProxyAdmin.json' import TransparentUpgradeableProxyArtifact from '@openzeppelin/contracts/build/contracts/TransparentUpgradeableProxy.json' export default buildModule('DisputeManager', (m) => { const governor = m.getParameter('governor') const controllerAddress = m.getParameter('controllerAddress') - const disputeManagerAddress = m.getParameter('disputeManagerAddress') + const disputeManagerProxyAddress = m.getParameter('disputeManagerProxyAddress') const disputeManagerProxyAdminAddress = m.getParameter('disputeManagerProxyAdminAddress') const arbitrator = m.getParameter('arbitrator') const disputePeriod = m.getParameter('disputePeriod') @@ -17,7 +18,7 @@ export default buildModule('DisputeManager', (m) => { const maxSlashingCut = m.getParameter('maxSlashingCut') const DisputeManagerProxyAdmin = m.contractAt('ProxyAdmin', ProxyAdminArtifact, disputeManagerProxyAdminAddress) - const DisputeManagerProxy = m.contractAt('DisputeManager', TransparentUpgradeableProxyArtifact, disputeManagerAddress) + const DisputeManagerProxy = m.contractAt('DisputeManagerProxy', TransparentUpgradeableProxyArtifact, disputeManagerProxyAddress) // Deploy implementation const DisputeManagerImplementation = deployImplementation(m, { @@ -31,6 +32,7 @@ export default buildModule('DisputeManager', (m) => { DisputeManagerProxy, DisputeManagerImplementation, { name: 'DisputeManager', + artifact: DisputeManagerArtifact, initArgs: [ arbitrator, disputePeriod, @@ -42,5 +44,8 @@ export default buildModule('DisputeManager', (m) => { m.call(DisputeManagerProxyAdmin, 'transferOwnership', [governor], { after: [DisputeManager] }) - return { DisputeManager, DisputeManagerImplementation } + return { + Transparent_Proxy_DisputeManager: DisputeManager, + Implementation_DisputeManager: DisputeManagerImplementation, + } }) diff --git a/packages/subgraph-service/ignition/modules/Proxies.ts b/packages/subgraph-service/ignition/modules/Proxies.ts index 92971ca90..804d54a5a 100644 --- a/packages/subgraph-service/ignition/modules/Proxies.ts +++ b/packages/subgraph-service/ignition/modules/Proxies.ts @@ -22,9 +22,9 @@ export default buildModule('SubgraphServiceProxies', (m) => { }) return { - DisputeManagerProxy, - DisputeManagerProxyAdmin, - SubgraphServiceProxy, - SubgraphServiceProxyAdmin, + Transparent_Proxy_SubgraphService: SubgraphServiceProxy, + Transparent_ProxyAdmin_SubgraphService: SubgraphServiceProxyAdmin, + Transparent_Proxy_DisputeManager: DisputeManagerProxy, + Transparent_ProxyAdmin_DisputeManager: DisputeManagerProxyAdmin, } }) diff --git a/packages/subgraph-service/ignition/modules/SubgraphService.ts b/packages/subgraph-service/ignition/modules/SubgraphService.ts index af90e8bf7..e31ba53a0 100644 --- a/packages/subgraph-service/ignition/modules/SubgraphService.ts +++ b/packages/subgraph-service/ignition/modules/SubgraphService.ts @@ -3,6 +3,7 @@ import { deployImplementation } from '@graphprotocol/horizon/ignition/modules/pr import { upgradeTransparentUpgradeableProxy } from '@graphprotocol/horizon/ignition/modules/proxy/TransparentUpgradeableProxy' import ProxyAdminArtifact from '@openzeppelin/contracts/build/contracts/ProxyAdmin.json' +import SubgraphServiceArtifact from '../../build/contracts/contracts/SubgraphService.sol/SubgraphService.json' import TransparentUpgradeableProxyArtifact from '@openzeppelin/contracts/build/contracts/TransparentUpgradeableProxy.json' export default buildModule('SubgraphService', (m) => { @@ -10,7 +11,7 @@ export default buildModule('SubgraphService', (m) => { const controllerAddress = m.getParameter('controllerAddress') const subgraphServiceProxyAddress = m.getParameter('subgraphServiceProxyAddress') const subgraphServiceProxyAdminAddress = m.getParameter('subgraphServiceProxyAdminAddress') - const disputeManagerAddress = m.getParameter('disputeManagerAddress') + const disputeManagerProxyAddress = m.getParameter('disputeManagerProxyAddress') const graphTallyCollectorAddress = m.getParameter('graphTallyCollectorAddress') const curationAddress = m.getParameter('curationAddress') const minimumProvisionTokens = m.getParameter('minimumProvisionTokens') @@ -18,12 +19,12 @@ export default buildModule('SubgraphService', (m) => { const stakeToFeesRatio = m.getParameter('stakeToFeesRatio') const SubgraphServiceProxyAdmin = m.contractAt('ProxyAdmin', ProxyAdminArtifact, subgraphServiceProxyAdminAddress) - const SubgraphServiceProxy = m.contractAt('SubgraphService', TransparentUpgradeableProxyArtifact, subgraphServiceProxyAddress) + const SubgraphServiceProxy = m.contractAt('SubgraphServiceProxy', TransparentUpgradeableProxyArtifact, subgraphServiceProxyAddress) // Deploy implementation const SubgraphServiceImplementation = deployImplementation(m, { name: 'SubgraphService', - constructorArgs: [controllerAddress, disputeManagerAddress, graphTallyCollectorAddress, curationAddress], + constructorArgs: [controllerAddress, disputeManagerProxyAddress, graphTallyCollectorAddress, curationAddress], }) // Upgrade implementation @@ -32,6 +33,7 @@ export default buildModule('SubgraphService', (m) => { SubgraphServiceProxy, SubgraphServiceImplementation, { name: 'SubgraphService', + artifact: SubgraphServiceArtifact, initArgs: [ minimumProvisionTokens, maximumDelegationRatio, @@ -41,5 +43,8 @@ export default buildModule('SubgraphService', (m) => { m.call(SubgraphServiceProxyAdmin, 'transferOwnership', [governor], { after: [SubgraphService] }) - return { SubgraphService, SubgraphServiceImplementation } + return { + Transparent_Proxy_SubgraphService: SubgraphService, + Implementation_SubgraphService: SubgraphServiceImplementation, + } }) diff --git a/packages/subgraph-service/ignition/modules/migrate/migrate-1.ts b/packages/subgraph-service/ignition/modules/migrate/migrate-1.ts index 48a189d81..b00a57c2d 100644 --- a/packages/subgraph-service/ignition/modules/migrate/migrate-1.ts +++ b/packages/subgraph-service/ignition/modules/migrate/migrate-1.ts @@ -4,16 +4,16 @@ import ProxiesModule from '../Proxies' export default buildModule('SubgraphService_Migrate_1', (m) => { const { - SubgraphServiceProxy, - SubgraphServiceProxyAdmin, - DisputeManagerProxy, - DisputeManagerProxyAdmin, + Transparent_Proxy_SubgraphService, + Transparent_ProxyAdmin_SubgraphService, + Transparent_Proxy_DisputeManager, + Transparent_ProxyAdmin_DisputeManager, } = m.useModule(ProxiesModule) return { - SubgraphServiceProxy, - SubgraphServiceProxyAdmin, - DisputeManagerProxy, - DisputeManagerProxyAdmin, + Transparent_Proxy_SubgraphService, + Transparent_ProxyAdmin_SubgraphService, + Transparent_Proxy_DisputeManager, + Transparent_ProxyAdmin_DisputeManager, } }) diff --git a/packages/subgraph-service/ignition/modules/migrate/migrate-2.ts b/packages/subgraph-service/ignition/modules/migrate/migrate-2.ts index 772c46973..65249a065 100644 --- a/packages/subgraph-service/ignition/modules/migrate/migrate-2.ts +++ b/packages/subgraph-service/ignition/modules/migrate/migrate-2.ts @@ -4,8 +4,13 @@ import DisputeManagerModule from '../DisputeManager' import SubgraphServiceModule from '../SubgraphService' export default buildModule('SubgraphService_Migrate_2', (m) => { - const { DisputeManager } = m.useModule(DisputeManagerModule) - const { SubgraphService } = m.useModule(SubgraphServiceModule) + const { Transparent_Proxy_DisputeManager, Implementation_DisputeManager } = m.useModule(DisputeManagerModule) + const { Transparent_Proxy_SubgraphService, Implementation_SubgraphService } = m.useModule(SubgraphServiceModule) - return { DisputeManager, SubgraphService } + return { + Transparent_Proxy_DisputeManager, + Implementation_DisputeManager, + Transparent_Proxy_SubgraphService, + Implementation_SubgraphService, + } }) diff --git a/packages/subgraph-service/scripts/deploy.ts b/packages/subgraph-service/scripts/deploy.ts deleted file mode 100644 index 00867588f..000000000 --- a/packages/subgraph-service/scripts/deploy.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* eslint-disable no-prototype-builtins */ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable @typescript-eslint/no-explicit-any */ -require('json5/lib/register') - -import hre, { ignition } from 'hardhat' -import { IgnitionHelper } from 'hardhat-graph-protocol/sdk' - -import DisputeManagerModule from '../ignition/modules/DisputeManager' -import HorizonModule from '@graphprotocol/horizon/ignition/modules/deploy' -import SubgraphServiceModule from '../ignition/modules/SubgraphService' -import SubgraphServiceProxiesModule from '../ignition/modules/Proxies' - -// Horizon needs the SubgraphService proxy address before it can be deployed -// But SubgraphService and DisputeManager implementations need Horizon... -// So the deployment order is: -// - Deploy SubgraphService and DisputeManager proxies -// - Deploy Horizon -// - Deploy SubgraphService and DisputeManager implementations -async function main() { - const SubgraphServiceConfig = IgnitionHelper.loadConfig('./ignition/configs/', 'subgraph-service', hre.network.name) - const HorizonConfig = IgnitionHelper.loadConfig('./node_modules/@graphprotocol/horizon/ignition/configs', 'horizon', hre.network.name) - - // Deploy proxies - const { - DisputeManagerProxy, - DisputeManagerProxyAdmin, - SubgraphServiceProxy, - SubgraphServiceProxyAdmin, - } = await ignition.deploy(SubgraphServiceProxiesModule, { - displayUi: true, - }) - - // Deploy Horizon - const { Controller, GraphTallyCollector, L2Curation } = await ignition.deploy(HorizonModule, { - displayUi: true, - parameters: IgnitionHelper.patchConfig(HorizonConfig, { - SubgraphService: { - subgraphServiceProxyAddress: SubgraphServiceProxy.target as string, - }, - }), - }) - - // Deploy DisputeManager implementation - await ignition.deploy(DisputeManagerModule, { - displayUi: true, - parameters: IgnitionHelper.mergeConfigs(SubgraphServiceConfig, { - DisputeManager: { - controllerAddress: Controller.target as string, - disputeManagerProxyAddress: DisputeManagerProxy.target as string, - disputeManagerProxyAdminAddress: DisputeManagerProxyAdmin.target as string, - }, - }), - }) - - // Deploy SubgraphService implementation - await ignition.deploy(SubgraphServiceModule, { - displayUi: true, - parameters: IgnitionHelper.mergeConfigs(SubgraphServiceConfig, { - SubgraphService: { - controllerAddress: Controller.target as string, - subgraphServiceProxyAddress: SubgraphServiceProxy.target as string, - subgraphServiceProxyAdminAddress: SubgraphServiceProxyAdmin.target as string, - disputeManagerAddress: DisputeManagerProxy.target as string, - graphTallyCollectorAddress: GraphTallyCollector.target as string, - curationAddress: L2Curation.target as string, - }, - }), - }) -} - -main().catch((error) => { - console.error(error) - process.exit(1) -}) diff --git a/packages/subgraph-service/scripts/migrate.ts b/packages/subgraph-service/scripts/migrate.ts deleted file mode 100644 index fd5dddcbc..000000000 --- a/packages/subgraph-service/scripts/migrate.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* eslint-disable no-prototype-builtins */ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable @typescript-eslint/no-explicit-any */ -require('json5/lib/register') - -import hre, { ignition } from 'hardhat' -import { IgnitionHelper } from 'hardhat-graph-protocol/sdk' - -import MigrateStep1 from '../ignition/modules/migrate/migrate-1' -import MigrateStep2 from '../ignition/modules/migrate/migrate-2' - -// Horizon needs the SubgraphService proxy address before it can be deployed -// But SubgraphService and DisputeManager implementations need Horizon... -// So the deployment order is: -// - Deploy SubgraphService and DisputeManager proxies -// - Deploy Horizon -// - Deploy SubgraphService and DisputeManager implementations -async function main() { - const SubgraphServiceConfig = IgnitionHelper.loadConfig('./ignition/configs/', 'subgraph-service', hre.network.name) - - // Deploy proxies - const { - DisputeManagerProxy, - DisputeManagerProxyAdmin, - SubgraphServiceProxy, - SubgraphServiceProxyAdmin, - } = await ignition.deploy(MigrateStep1, { - displayUi: true, - }) - - const PatchedSubgraphServiceConfig = IgnitionHelper.mergeConfigs(SubgraphServiceConfig, { - $global: { - subgraphServiceAddress: SubgraphServiceProxy.target as string, - subgraphServiceProxyAdminAddress: SubgraphServiceProxyAdmin.target as string, - disputeManagerAddress: DisputeManagerProxy.target as string, - disputeManagerProxyAdminAddress: DisputeManagerProxyAdmin.target as string, - }, - }) - - await ignition.deploy(MigrateStep2, { - displayUi: true, - parameters: PatchedSubgraphServiceConfig, - deploymentId: `subgraph-service-${hre.network.name}`, - }) -} -main().catch((error) => { - console.error(error) - process.exit(1) -}) diff --git a/packages/subgraph-service/tasks/deploy.ts b/packages/subgraph-service/tasks/deploy.ts new file mode 100644 index 000000000..75f741970 --- /dev/null +++ b/packages/subgraph-service/tasks/deploy.ts @@ -0,0 +1,215 @@ +/* eslint-disable no-case-declarations */ +import { task, types } from 'hardhat/config' +import { IgnitionHelper } from 'hardhat-graph-protocol/sdk' + +import type { AddressBook } from '../../hardhat-graph-protocol/src/sdk/address-book' +import type { HardhatRuntimeEnvironment } from 'hardhat/types' + +import DisputeManagerModule from '../ignition/modules/DisputeManager' +import HorizonModule from '@graphprotocol/horizon/ignition/modules/deploy' +import ProxiesModule from '../ignition/modules/Proxies' +import SubgraphServiceModule from '../ignition/modules/SubgraphService' + +// Horizon needs the SubgraphService proxy address before it can be deployed +// But SubgraphService and DisputeManager implementations need Horizon... +// So the deployment order is: +// - Deploy SubgraphService and DisputeManager proxies +// - Deploy Horizon +// - Deploy SubgraphService and DisputeManager implementations +task('deploy:protocol', 'Deploy a new version of the Graph Protocol Horizon contracts - with Subgraph Service') + .setAction(async (_, hre: HardhatRuntimeEnvironment) => { + const graph = hre.graph() + + // Load configuration files for the deployment + console.log('\n========== βš™οΈ Deployment configuration ==========') + const { config: HorizonConfig, file: horizonFile } = IgnitionHelper.loadConfig('./node_modules/@graphprotocol/horizon/ignition/configs', 'horizon', hre.network.name) + const { config: SubgraphServiceConfig, file: subgraphServiceFile } = IgnitionHelper.loadConfig('./ignition/configs/', 'subgraph-service', hre.network.name) + console.log(`Loaded Horizon migration configuration from ${horizonFile}`) + console.log(`Loaded Subgraph Service migration configuration from ${subgraphServiceFile}`) + + // Display the deployer -- this also triggers the secure accounts prompt if being used + console.log('\n========== πŸ”‘ Deployer account ==========') + const signers = await hre.ethers.getSigners() + const deployer = signers[0] + console.log('Using deployer account:', deployer.address) + const balance = await hre.ethers.provider.getBalance(deployer.address) + console.log('Deployer balance:', hre.ethers.formatEther(balance), 'ETH') + if (balance === 0n) { + console.error('Error: Deployer account has no ETH balance') + process.exit(1) + } + + // 1. Deploy SubgraphService and DisputeManager proxies + console.log(`\n========== 🚧 SubgraphService and DisputeManager proxies ==========`) + const proxiesDeployment = await hre.ignition.deploy(ProxiesModule, { + displayUi: true, + parameters: SubgraphServiceConfig, + }) + + // 2. Deploy Horizon + console.log(`\n========== 🚧 Deploy Horizon ==========`) + const horizonDeployment = await hre.ignition.deploy(HorizonModule, { + displayUi: true, + parameters: IgnitionHelper.patchConfig(HorizonConfig, { + SubgraphService: { + subgraphServiceProxyAddress: proxiesDeployment.Transparent_Proxy_SubgraphService.target as string, + }, + }), + }) + + // 3. Deploy SubgraphService and DisputeManager implementations + console.log(`\n========== 🚧 Deploy DisputeManager implementation and upgrade ==========`) + const disputeManagerDeployment = await hre.ignition.deploy(DisputeManagerModule, { + displayUi: true, + parameters: IgnitionHelper.patchConfig(SubgraphServiceConfig, { + $global: { + controllerAddress: horizonDeployment.Controller.target as string, + disputeManagerProxyAddress: proxiesDeployment.Transparent_Proxy_DisputeManager.target as string, + }, + DisputeManager: { + disputeManagerProxyAdminAddress: proxiesDeployment.Transparent_ProxyAdmin_DisputeManager.target as string, + }, + }), + }) + + console.log(`\n========== 🚧 Deploy SubgraphService implementation and upgrade ==========`) + const subgraphServiceDeployment = await hre.ignition.deploy(SubgraphServiceModule, { + displayUi: true, + parameters: IgnitionHelper.patchConfig(SubgraphServiceConfig, { + $global: { + controllerAddress: horizonDeployment.Controller.target as string, + disputeManagerProxyAddress: disputeManagerDeployment.Transparent_Proxy_DisputeManager.target as string, + }, + SubgraphService: { + subgraphServiceProxyAddress: proxiesDeployment.Transparent_Proxy_SubgraphService.target as string, + subgraphServiceProxyAdminAddress: proxiesDeployment.Transparent_ProxyAdmin_SubgraphService.target as string, + graphTallyCollectorAddress: horizonDeployment.GraphTallyCollector.target as string, + curationAddress: horizonDeployment.Graph_Proxy_L2Curation.target as string, + }, + }), + }) + + // Save the addresses to the address book + console.log('\n========== πŸ“– Updating address book ==========') + IgnitionHelper.saveToAddressBook(horizonDeployment, hre.network.config.chainId, graph.horizon!.addressBook) + IgnitionHelper.saveToAddressBook(proxiesDeployment, hre.network.config.chainId, graph.subgraphService!.addressBook) + IgnitionHelper.saveToAddressBook(disputeManagerDeployment, hre.network.config.chainId, graph.subgraphService!.addressBook) + IgnitionHelper.saveToAddressBook(subgraphServiceDeployment, hre.network.config.chainId, graph.subgraphService!.addressBook) + console.log(`Address book at ${graph.horizon!.addressBook.file} updated!`) + console.log(`Address book at ${graph.subgraphService!.addressBook.file} updated!`) + console.log('Note that Horizon deployment addresses are updated in the Horizon address book') + + console.log('\n\nπŸŽ‰ ✨ πŸš€ βœ… Deployment complete! πŸŽ‰ ✨ πŸš€ βœ…') + }) + +task('deploy:migrate', 'Deploy the Subgraph Service on an existing Horizon deployment') + .addOptionalParam('step', 'Migration step to run (1, 2)', undefined, types.int) + .addFlag('patchConfig', 'Patch configuration file using address book values - does not save changes') + .setAction(async (args, hre: HardhatRuntimeEnvironment) => { + // Task parameters + const step: number = args.step ?? 0 + const patchConfig: boolean = args.patchConfig ?? false + + const graph = hre.graph() + console.log(getHorizonBanner()) + + // Migration step to run + console.log('\n========== πŸ—οΈ Migration steps ==========') + const validSteps = [1, 2] + if (!validSteps.includes(step)) { + console.error(`Error: Invalid migration step provided: ${step}`) + console.error(`Valid steps are: ${validSteps.join(', ')}`) + process.exit(1) + } + console.log(`Running migration step: ${step}`) + + // Load configuration for the migration + console.log('\n========== βš™οΈ Deployment configuration ==========') + const { config: SubgraphServiceMigrateConfig, file } = IgnitionHelper.loadConfig('./ignition/configs/', 'subgraph-service-migrate', `subgraph-service-${hre.network.name}`) + console.log(`Loaded migration configuration from ${file}`) + + // Display the deployer -- this also triggers the secure accounts prompt if being used + console.log('\n========== πŸ”‘ Deployer account ==========') + const signers = await hre.ethers.getSigners() + const deployer = signers[0] + console.log('Using deployer account:', deployer.address) + const balance = await hre.ethers.provider.getBalance(deployer.address) + console.log('Deployer balance:', hre.ethers.formatEther(balance), 'ETH') + if (balance === 0n) { + console.error('Error: Deployer account has no ETH balance') + process.exit(1) + } + + // Run migration step + console.log(`\n========== 🚧 Running migration: step ${step} ==========`) + const MigrationModule = require(`../ignition/modules/migrate/migrate-${step}`).default + const deployment = await hre.ignition.deploy( + MigrationModule, + { + displayUi: true, + parameters: patchConfig ? _patchStepConfig(step, SubgraphServiceMigrateConfig, graph.subgraphService!.addressBook, graph.horizon!.addressBook) : SubgraphServiceMigrateConfig, + deploymentId: `subgraph-service-${hre.network.name}`, + }) + + // Update address book + console.log('\n========== πŸ“– Updating address book ==========') + IgnitionHelper.saveToAddressBook(deployment, hre.network.config.chainId, graph.subgraphService!.addressBook) + console.log(`Address book at ${graph.subgraphService!.addressBook.file} updated!`) + + console.log('\n\nπŸŽ‰ ✨ πŸš€ βœ… Migration complete! πŸŽ‰ ✨ πŸš€ βœ…') + }) + +// This function patches the Ignition configuration object using an address book to fill in the gaps +// The resulting configuration is not saved back to the configuration file + +function _patchStepConfig( + step: number, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + config: any, + addressBook: AddressBook, + horizonAddressBook: AddressBook, + // eslint-disable-next-line @typescript-eslint/no-explicit-any +): any { + let patchedConfig = config + + switch (step) { + case 2: + const SubgraphService = addressBook.getEntry('SubgraphService') + const DisputeManager = addressBook.getEntry('DisputeManager') + const GraphTallyCollector = horizonAddressBook.getEntry('GraphTallyCollector') + + patchedConfig = IgnitionHelper.patchConfig(config, { + SubgraphService: { + subgraphServiceProxyAddress: SubgraphService.address, + subgraphServiceProxyAdminAddress: SubgraphService.proxyAdmin, + graphTallyCollectorAddress: GraphTallyCollector.address, + disputeManagerProxyAddress: DisputeManager.address, + }, + DisputeManager: { + disputeManagerProxyAddress: DisputeManager.address, + disputeManagerProxyAdminAddress: DisputeManager.proxyAdmin, + }, + }) + break + } + + return patchedConfig +} + +function getHorizonBanner(): string { + return ` + β–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•— + β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘ + β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘ + β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ + β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ + β•šβ•β• β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•šβ•β•β•šβ•β•β•β•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•β• + + β–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— + β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β• + β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— + β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β• + β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— + β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β•β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β• + ` +} diff --git a/packages/subgraph-service/tsconfig.json b/packages/subgraph-service/tsconfig.json index 0cbbef9e2..4b7040a6c 100644 --- a/packages/subgraph-service/tsconfig.json +++ b/packages/subgraph-service/tsconfig.json @@ -14,6 +14,7 @@ "hardhat.config.ts", "types/**/*.ts", "scripts/**/*.ts", + "tasks/**/*.ts", "test/**/*.ts", "ignition/**/*.ts", "eslint.config.js", From f2b120a71e2177e704394301bb5bfb6a4ffa51fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Fri, 14 Feb 2025 17:29:06 -0300 Subject: [PATCH 03/15] chore: update readme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- packages/horizon/README.md | 11 +++----- packages/subgraph-service/README.md | 44 +++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/packages/horizon/README.md b/packages/horizon/README.md index f4034ccaf..57614c160 100644 --- a/packages/horizon/README.md +++ b/packages/horizon/README.md @@ -9,10 +9,7 @@ The following environment variables might be required: | Variable | Description | |----------|-------------| | `ARBISCAN_API_KEY` | Arbiscan API key | -| `DEPLOYER_PRIVATE_KEY` | Deployer private key - for testnet deployments | -| `GOVERNOR_PRIVATE_KEY` | Governor private key - for testnet deployments | | `ARBITRUM_SEPOLIA_RPC` | Arbitrum Sepolia RPC URL | -| `VIRTUAL_ARBITRUM_SEPOLIA_RPC` | Virtual Arbitrum Sepolia RPC URL | You can set them using Hardhat: @@ -27,7 +24,7 @@ yarn install yarn build ``` -## Deploy +## Deployment Note that this instructions will help you deploy Graph Horizon contracts, but no data service will be deployed. If you want to deploy the Subgraph Service please refer to the [Subgraph Service README](../subgraph-service/README.md) for deploy instructions. @@ -39,13 +36,13 @@ npx hardhat deploy:protocol --network hardhat ``` ### Upgrade deployment -Usually you would run this against a network (or a fork) where the original Graph Protocol was previously deployed. To upgrade an existing deployment of the original Graph Protocol to Graph Horizon, run the following commands. Note that each step might need to be run by different accounts (deployer vs governor): +Usually you would run this against a network (or a fork) where the original Graph Protocol was previously deployed. To upgrade an existing deployment of the original Graph Protocol to Graph Horizon, run the following commands. Note that some steps might need to be run by different accounts (deployer vs governor): ```bash npx hardhat deploy:migrate --network hardhat --step 1 -npx hardhat deploy:migrate --network hardhat --step 2 # Optionally add --patch-config +npx hardhat deploy:migrate --network hardhat --step 2 # Run with governor. Optionally add --patch-config npx hardhat deploy:migrate --network hardhat --step 3 -npx hardhat deploy:migrate --network hardhat --step 4 # Optionally add --patch-config +npx hardhat deploy:migrate --network hardhat --step 4 # Run with governor. Optionally add --patch-config ``` Steps 2 and 4 require patching the configuration file with addresses from previous steps. The files are located in the `ignition/configs` directory and need to be manually edited. You can also pass `--patch-config` flag to the deploy command to automatically patch the configuration reading values from the address book. Note that this will NOT update the configuration file. \ No newline at end of file diff --git a/packages/subgraph-service/README.md b/packages/subgraph-service/README.md index dbd580740..8dc114ebb 100644 --- a/packages/subgraph-service/README.md +++ b/packages/subgraph-service/README.md @@ -2,16 +2,50 @@ The Subgraph Service is a data service designed to work with Graph Horizon that supports indexing subgraphs and serving queries to consumers. -## Deployment +## Configuration -We use Hardhat Ignition to deploy the contracts. To build and deploy the Subgraph Service run the following commands: +The following environment variables might be required: + +| Variable | Description | +|----------|-------------| +| `ARBISCAN_API_KEY` | Arbiscan API key | +| `ARBITRUM_SEPOLIA_RPC` | Arbitrum Sepolia RPC URL | + +You can set them using Hardhat: + +```bash +npx hardhat vars set +``` + +## Build ```bash yarn install yarn build -npx hardhat run scripts/deploy.ts --network hardhat ``` -You can use any network defined in `hardhat.config.ts` by replacing `hardhat` with the network name. +## Deployment + +Note that this instructions will help you deploy Graph Horizon contracts alongside the Subgraph Service. If you want to deploy just the core Horizon contracts please refer to the [Horizon README](../horizon/README.md) for deploy instructions. + +### New deployment +To deploy Graph Horizon from scratch including the Subgraph Service run the following command: + +```bash +npx hardhat deploy:protocol --network hardhat +``` + +### Upgrade deployment +Usually you would run this against a network (or a fork) where the original Graph Protocol was previously deployed. To upgrade an existing deployment of the original Graph Protocol to Graph Horizon including the Subgraph Service, run the following commands. Note that some steps might need to be run by different accounts (deployer vs governor): + +```bash +cd ../ +cd horizon && npx hardhat deploy:migrate --network hardhat --step 1 && cd .. +cd subgraph-service && npx hardhat deploy:migrate --network hardhat --step 1 && cd .. +cd horizon && npx hardhat deploy:migrate --network hardhat --step 2 && cd .. # Run with governor. Optionally add --patch-config +cd horizon && npx hardhat deploy:migrate --network hardhat --step 3 && cd .. +cd subgraph-service && npx hardhat deploy:migrate --network hardhat --step 2 && cd .. # Optionally add --patch-config +cd horizon && npx hardhat deploy:migrate --network hardhat --step 4 && cd .. # Run with governor. Optionally add --patch-config +``` -Note that this will deploy and configure Graph Horizon contracts as well as the Subgraph Service. \ No newline at end of file +Horizon Steps 2 and 4, and Subgraph Service Step 2 require patching the configuration file with addresses from previous steps. The files are located in the `ignition/configs` directory and need to be manually edited. You can also pass `--patch-config` flag to the deploy command to automatically patch the configuration reading values from the address book. Note that this will NOT update the configuration file. \ No newline at end of file From 6db8d05f3dbd7114677b923c12e0f2b841dc0c32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 17 Feb 2025 13:49:18 -0300 Subject: [PATCH 04/15] fix: couple fixes for migration scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- .../configs/horizon-migrate.default.json5 | 2 +- packages/horizon/tasks/deploy.ts | 34 +++++++++++++++---- packages/subgraph-service/README.md | 2 +- .../configs/subgraph-service.default.json5 | 5 +-- .../ignition/modules/Curation.ts | 17 ++++++++++ .../ignition/modules/DisputeManager.ts | 4 +-- .../ignition/modules/Proxies.ts | 8 ++--- .../ignition/modules/SubgraphService.ts | 4 +-- .../ignition/modules/deploy/deploy-1.ts | 19 +++++++++++ .../ignition/modules/deploy/deploy-2.ts | 19 +++++++++++ .../ignition/modules/migrate/migrate-1.ts | 16 ++++----- .../ignition/modules/migrate/migrate-2.ts | 12 +++---- packages/subgraph-service/tasks/deploy.ts | 26 ++++---------- 13 files changed, 116 insertions(+), 52 deletions(-) create mode 100644 packages/subgraph-service/ignition/modules/Curation.ts create mode 100644 packages/subgraph-service/ignition/modules/deploy/deploy-1.ts create mode 100644 packages/subgraph-service/ignition/modules/deploy/deploy-2.ts diff --git a/packages/horizon/ignition/configs/horizon-migrate.default.json5 b/packages/horizon/ignition/configs/horizon-migrate.default.json5 index 96d60bb91..6061e1216 100644 --- a/packages/horizon/ignition/configs/horizon-migrate.default.json5 +++ b/packages/horizon/ignition/configs/horizon-migrate.default.json5 @@ -13,7 +13,7 @@ "rewardsManagerAddress": "0x1F49caE7669086c8ba53CC35d1E9f80176d67E79", "curationAddress": "0xDe761f075200E75485F4358978FB4d1dC8644FD5", - // Must be set for step 4 of the migration + // Must be set for step 3 and 4 of the migration "subgraphServiceAddress": "", // Parameters diff --git a/packages/horizon/tasks/deploy.ts b/packages/horizon/tasks/deploy.ts index df65fbff5..d9052745e 100644 --- a/packages/horizon/tasks/deploy.ts +++ b/packages/horizon/tasks/deploy.ts @@ -88,7 +88,7 @@ task('deploy:migrate', 'Upgrade an existing version of the Graph Protocol v1 to MigrationModule, { displayUi: true, - parameters: patchConfig ? _patchStepConfig(step, HorizonMigrateConfig, graph.horizon!.addressBook) : HorizonMigrateConfig, + parameters: patchConfig ? _patchStepConfig(step, HorizonMigrateConfig, graph.horizon!.addressBook, graph.subgraphService!.addressBook) : HorizonMigrateConfig, deploymentId: `horizon-${hre.network.name}`, }) @@ -103,13 +103,20 @@ task('deploy:migrate', 'Upgrade an existing version of the Graph Protocol v1 to // This function patches the Ignition configuration object using an address book to fill in the gaps // The resulting configuration is not saved back to the configuration file // eslint-disable-next-line @typescript-eslint/no-explicit-any -function _patchStepConfig(step: number, config: any, addressBook: AddressBook): any { +function _patchStepConfig( + step: number, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + config: any, + horizonAddressBook: AddressBook, + subgraphServiceAddressBook: AddressBook, + // eslint-disable-next-line @typescript-eslint/no-explicit-any +): any { let patchedConfig = config switch (step) { case 2: - const GraphPayments = addressBook.getEntry('GraphPayments') - const PaymentsEscrow = addressBook.getEntry('PaymentsEscrow') + const GraphPayments = horizonAddressBook.getEntry('GraphPayments') + const PaymentsEscrow = horizonAddressBook.getEntry('PaymentsEscrow') patchedConfig = IgnitionHelper.patchConfig(config, { HorizonProxiesGovernor: { graphPaymentsAddress: GraphPayments.address, @@ -117,11 +124,24 @@ function _patchStepConfig(s }, }) break + case 3: + const SubgraphService3 = subgraphServiceAddressBook.getEntry('SubgraphService') + patchedConfig = IgnitionHelper.patchConfig(patchedConfig, { + $global: { + subgraphServiceAddress: SubgraphService3.address, + }, + }) + console.log(patchedConfig) + break case 4: - const HorizonStaking = addressBook.getEntry('HorizonStaking') - const L2Curation = addressBook.getEntry('L2Curation') - const RewardsManager = addressBook.getEntry('RewardsManager') + const HorizonStaking = horizonAddressBook.getEntry('HorizonStaking') + const L2Curation = horizonAddressBook.getEntry('L2Curation') + const RewardsManager = horizonAddressBook.getEntry('RewardsManager') + const SubgraphService4 = subgraphServiceAddressBook.getEntry('SubgraphService') patchedConfig = IgnitionHelper.patchConfig(patchedConfig, { + $global: { + subgraphServiceAddress: SubgraphService4.address, + }, HorizonStakingGovernor: { horizonStakingImplementationAddress: HorizonStaking.implementation, }, diff --git a/packages/subgraph-service/README.md b/packages/subgraph-service/README.md index 8dc114ebb..bc49a201a 100644 --- a/packages/subgraph-service/README.md +++ b/packages/subgraph-service/README.md @@ -43,7 +43,7 @@ cd ../ cd horizon && npx hardhat deploy:migrate --network hardhat --step 1 && cd .. cd subgraph-service && npx hardhat deploy:migrate --network hardhat --step 1 && cd .. cd horizon && npx hardhat deploy:migrate --network hardhat --step 2 && cd .. # Run with governor. Optionally add --patch-config -cd horizon && npx hardhat deploy:migrate --network hardhat --step 3 && cd .. +cd horizon && npx hardhat deploy:migrate --network hardhat --step 3 && cd .. # Optionally add --patch-config cd subgraph-service && npx hardhat deploy:migrate --network hardhat --step 2 && cd .. # Optionally add --patch-config cd horizon && npx hardhat deploy:migrate --network hardhat --step 4 && cd .. # Run with governor. Optionally add --patch-config ``` diff --git a/packages/subgraph-service/ignition/configs/subgraph-service.default.json5 b/packages/subgraph-service/ignition/configs/subgraph-service.default.json5 index 2f15d8f51..2fd75fcbc 100644 --- a/packages/subgraph-service/ignition/configs/subgraph-service.default.json5 +++ b/packages/subgraph-service/ignition/configs/subgraph-service.default.json5 @@ -5,7 +5,9 @@ // Must be set for step 2 of the deployment "controllerAddress": "", - "disputeManagerProxyAddress": "" + "disputeManagerProxyAddress": "", + "curationAddress": "", + "curationImplementationAddress": "" }, "DisputeManager": { "disputePeriod": 2419200, @@ -24,7 +26,6 @@ // Must be set for step 2 of the deployment "subgraphServiceProxyAddress": "", "subgraphServiceProxyAdminAddress": "", - "curationAddress": "", "graphTallyCollectorAddress": "" } } diff --git a/packages/subgraph-service/ignition/modules/Curation.ts b/packages/subgraph-service/ignition/modules/Curation.ts new file mode 100644 index 000000000..b8cac18b9 --- /dev/null +++ b/packages/subgraph-service/ignition/modules/Curation.ts @@ -0,0 +1,17 @@ +import { buildModule } from '@nomicfoundation/ignition-core' + +import CurationArtifact from '@graphprotocol/contracts/build/contracts/contracts/l2/curation/L2Curation.sol/L2Curation.json' + +// Note that this module is a no-op, we only run it to get curation addresses into the address book. +// Curation deployment should be managed by ignition scripts in subgraph-service package however +// due to tight coupling with HorizonStakingExtension contract it's easier to do it on the horizon package. +// Once the transition period is over we can migrate it. +export default buildModule('L2Curation', (m) => { + const curationAddress = m.getParameter('curationAddress') + const curationImplementationAddress = m.getParameter('curationImplementationAddress') + + const L2Curation = m.contractAt('L2Curation', CurationArtifact, curationAddress) + const L2CurationImplementation = m.contractAt('L2CurationImplementation', CurationArtifact, curationImplementationAddress) + + return { L2Curation, L2CurationImplementation } +}) diff --git a/packages/subgraph-service/ignition/modules/DisputeManager.ts b/packages/subgraph-service/ignition/modules/DisputeManager.ts index c3574f6d9..e1a456059 100644 --- a/packages/subgraph-service/ignition/modules/DisputeManager.ts +++ b/packages/subgraph-service/ignition/modules/DisputeManager.ts @@ -45,7 +45,7 @@ export default buildModule('DisputeManager', (m) => { m.call(DisputeManagerProxyAdmin, 'transferOwnership', [governor], { after: [DisputeManager] }) return { - Transparent_Proxy_DisputeManager: DisputeManager, - Implementation_DisputeManager: DisputeManagerImplementation, + DisputeManager, + DisputeManagerImplementation, } }) diff --git a/packages/subgraph-service/ignition/modules/Proxies.ts b/packages/subgraph-service/ignition/modules/Proxies.ts index 804d54a5a..7fe2c8960 100644 --- a/packages/subgraph-service/ignition/modules/Proxies.ts +++ b/packages/subgraph-service/ignition/modules/Proxies.ts @@ -22,9 +22,9 @@ export default buildModule('SubgraphServiceProxies', (m) => { }) return { - Transparent_Proxy_SubgraphService: SubgraphServiceProxy, - Transparent_ProxyAdmin_SubgraphService: SubgraphServiceProxyAdmin, - Transparent_Proxy_DisputeManager: DisputeManagerProxy, - Transparent_ProxyAdmin_DisputeManager: DisputeManagerProxyAdmin, + SubgraphServiceProxy, + SubgraphServiceProxyAdmin, + DisputeManagerProxy, + DisputeManagerProxyAdmin, } }) diff --git a/packages/subgraph-service/ignition/modules/SubgraphService.ts b/packages/subgraph-service/ignition/modules/SubgraphService.ts index e31ba53a0..a4883a1b0 100644 --- a/packages/subgraph-service/ignition/modules/SubgraphService.ts +++ b/packages/subgraph-service/ignition/modules/SubgraphService.ts @@ -44,7 +44,7 @@ export default buildModule('SubgraphService', (m) => { m.call(SubgraphServiceProxyAdmin, 'transferOwnership', [governor], { after: [SubgraphService] }) return { - Transparent_Proxy_SubgraphService: SubgraphService, - Implementation_SubgraphService: SubgraphServiceImplementation, + SubgraphService, + SubgraphServiceImplementation, } }) diff --git a/packages/subgraph-service/ignition/modules/deploy/deploy-1.ts b/packages/subgraph-service/ignition/modules/deploy/deploy-1.ts new file mode 100644 index 000000000..027c4563f --- /dev/null +++ b/packages/subgraph-service/ignition/modules/deploy/deploy-1.ts @@ -0,0 +1,19 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import ProxiesModule from '../Proxies' + +export default buildModule('SubgraphService_Deploy_1', (m) => { + const { + SubgraphServiceProxy, + SubgraphServiceProxyAdmin, + DisputeManagerProxy, + DisputeManagerProxyAdmin, + } = m.useModule(ProxiesModule) + + return { + Transparent_Proxy_SubgraphService: SubgraphServiceProxy, + Transparent_ProxyAdmin_SubgraphService: SubgraphServiceProxyAdmin, + Transparent_Proxy_DisputeManager: DisputeManagerProxy, + Transparent_ProxyAdmin_DisputeManager: DisputeManagerProxyAdmin, + } +}) diff --git a/packages/subgraph-service/ignition/modules/deploy/deploy-2.ts b/packages/subgraph-service/ignition/modules/deploy/deploy-2.ts new file mode 100644 index 000000000..6f9ca65c5 --- /dev/null +++ b/packages/subgraph-service/ignition/modules/deploy/deploy-2.ts @@ -0,0 +1,19 @@ +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules' + +import CurationModule from '../Curation' +import DisputeManagerModule from '../DisputeManager' +import SubgraphServiceModule from '../SubgraphService' + +export default buildModule('SubgraphService_Deploy_2', (m) => { + const { DisputeManager, DisputeManagerImplementation } = m.useModule(DisputeManagerModule) + const { SubgraphService, SubgraphServiceImplementation } = m.useModule(SubgraphServiceModule) + const { L2Curation, L2CurationImplementation } = m.useModule(CurationModule) + return { + Transparent_Proxy_DisputeManager: DisputeManager, + Implementation_DisputeManager: DisputeManagerImplementation, + Transparent_Proxy_SubgraphService: SubgraphService, + Implementation_SubgraphService: SubgraphServiceImplementation, + Graph_Proxy_L2Curation: L2Curation, + Implementation_L2Curation: L2CurationImplementation, + } +}) diff --git a/packages/subgraph-service/ignition/modules/migrate/migrate-1.ts b/packages/subgraph-service/ignition/modules/migrate/migrate-1.ts index b00a57c2d..66b4bf74c 100644 --- a/packages/subgraph-service/ignition/modules/migrate/migrate-1.ts +++ b/packages/subgraph-service/ignition/modules/migrate/migrate-1.ts @@ -4,16 +4,16 @@ import ProxiesModule from '../Proxies' export default buildModule('SubgraphService_Migrate_1', (m) => { const { - Transparent_Proxy_SubgraphService, - Transparent_ProxyAdmin_SubgraphService, - Transparent_Proxy_DisputeManager, - Transparent_ProxyAdmin_DisputeManager, + SubgraphServiceProxy, + SubgraphServiceProxyAdmin, + DisputeManagerProxy, + DisputeManagerProxyAdmin, } = m.useModule(ProxiesModule) return { - Transparent_Proxy_SubgraphService, - Transparent_ProxyAdmin_SubgraphService, - Transparent_Proxy_DisputeManager, - Transparent_ProxyAdmin_DisputeManager, + Transparent_Proxy_SubgraphService: SubgraphServiceProxy, + Transparent_ProxyAdmin_SubgraphService: SubgraphServiceProxyAdmin, + Transparent_Proxy_DisputeManager: DisputeManagerProxy, + Transparent_ProxyAdmin_DisputeManager: DisputeManagerProxyAdmin, } }) diff --git a/packages/subgraph-service/ignition/modules/migrate/migrate-2.ts b/packages/subgraph-service/ignition/modules/migrate/migrate-2.ts index 65249a065..e50115193 100644 --- a/packages/subgraph-service/ignition/modules/migrate/migrate-2.ts +++ b/packages/subgraph-service/ignition/modules/migrate/migrate-2.ts @@ -4,13 +4,13 @@ import DisputeManagerModule from '../DisputeManager' import SubgraphServiceModule from '../SubgraphService' export default buildModule('SubgraphService_Migrate_2', (m) => { - const { Transparent_Proxy_DisputeManager, Implementation_DisputeManager } = m.useModule(DisputeManagerModule) - const { Transparent_Proxy_SubgraphService, Implementation_SubgraphService } = m.useModule(SubgraphServiceModule) + const { DisputeManager, DisputeManagerImplementation } = m.useModule(DisputeManagerModule) + const { SubgraphService, SubgraphServiceImplementation } = m.useModule(SubgraphServiceModule) return { - Transparent_Proxy_DisputeManager, - Implementation_DisputeManager, - Transparent_Proxy_SubgraphService, - Implementation_SubgraphService, + Transparent_Proxy_DisputeManager: DisputeManager, + Transparent_ProxyAdmin_DisputeManager: DisputeManagerImplementation, + Transparent_Proxy_SubgraphService: SubgraphService, + Transparent_ProxyAdmin_SubgraphService: SubgraphServiceImplementation, } }) diff --git a/packages/subgraph-service/tasks/deploy.ts b/packages/subgraph-service/tasks/deploy.ts index 75f741970..03a2c800b 100644 --- a/packages/subgraph-service/tasks/deploy.ts +++ b/packages/subgraph-service/tasks/deploy.ts @@ -5,10 +5,9 @@ import { IgnitionHelper } from 'hardhat-graph-protocol/sdk' import type { AddressBook } from '../../hardhat-graph-protocol/src/sdk/address-book' import type { HardhatRuntimeEnvironment } from 'hardhat/types' -import DisputeManagerModule from '../ignition/modules/DisputeManager' +import Deploy1Module from '../ignition/modules/deploy/deploy-1' +import Deploy2Module from '../ignition/modules/deploy/deploy-2' import HorizonModule from '@graphprotocol/horizon/ignition/modules/deploy' -import ProxiesModule from '../ignition/modules/Proxies' -import SubgraphServiceModule from '../ignition/modules/SubgraphService' // Horizon needs the SubgraphService proxy address before it can be deployed // But SubgraphService and DisputeManager implementations need Horizon... @@ -41,7 +40,7 @@ task('deploy:protocol', 'Deploy a new version of the Graph Protocol Horizon cont // 1. Deploy SubgraphService and DisputeManager proxies console.log(`\n========== 🚧 SubgraphService and DisputeManager proxies ==========`) - const proxiesDeployment = await hre.ignition.deploy(ProxiesModule, { + const proxiesDeployment = await hre.ignition.deploy(Deploy1Module, { displayUi: true, parameters: SubgraphServiceConfig, }) @@ -58,33 +57,23 @@ task('deploy:protocol', 'Deploy a new version of the Graph Protocol Horizon cont }) // 3. Deploy SubgraphService and DisputeManager implementations - console.log(`\n========== 🚧 Deploy DisputeManager implementation and upgrade ==========`) - const disputeManagerDeployment = await hre.ignition.deploy(DisputeManagerModule, { + console.log(`\n========== 🚧 Deploy SubgraphService implementations and upgrade them ==========`) + const subgraphServiceDeployment = await hre.ignition.deploy(Deploy2Module, { displayUi: true, parameters: IgnitionHelper.patchConfig(SubgraphServiceConfig, { $global: { controllerAddress: horizonDeployment.Controller.target as string, disputeManagerProxyAddress: proxiesDeployment.Transparent_Proxy_DisputeManager.target as string, + curationAddress: horizonDeployment.Graph_Proxy_L2Curation.target as string, + curationImplementationAddress: horizonDeployment.Implementation_L2Curation.target as string, }, DisputeManager: { disputeManagerProxyAdminAddress: proxiesDeployment.Transparent_ProxyAdmin_DisputeManager.target as string, }, - }), - }) - - console.log(`\n========== 🚧 Deploy SubgraphService implementation and upgrade ==========`) - const subgraphServiceDeployment = await hre.ignition.deploy(SubgraphServiceModule, { - displayUi: true, - parameters: IgnitionHelper.patchConfig(SubgraphServiceConfig, { - $global: { - controllerAddress: horizonDeployment.Controller.target as string, - disputeManagerProxyAddress: disputeManagerDeployment.Transparent_Proxy_DisputeManager.target as string, - }, SubgraphService: { subgraphServiceProxyAddress: proxiesDeployment.Transparent_Proxy_SubgraphService.target as string, subgraphServiceProxyAdminAddress: proxiesDeployment.Transparent_ProxyAdmin_SubgraphService.target as string, graphTallyCollectorAddress: horizonDeployment.GraphTallyCollector.target as string, - curationAddress: horizonDeployment.Graph_Proxy_L2Curation.target as string, }, }), }) @@ -93,7 +82,6 @@ task('deploy:protocol', 'Deploy a new version of the Graph Protocol Horizon cont console.log('\n========== πŸ“– Updating address book ==========') IgnitionHelper.saveToAddressBook(horizonDeployment, hre.network.config.chainId, graph.horizon!.addressBook) IgnitionHelper.saveToAddressBook(proxiesDeployment, hre.network.config.chainId, graph.subgraphService!.addressBook) - IgnitionHelper.saveToAddressBook(disputeManagerDeployment, hre.network.config.chainId, graph.subgraphService!.addressBook) IgnitionHelper.saveToAddressBook(subgraphServiceDeployment, hre.network.config.chainId, graph.subgraphService!.addressBook) console.log(`Address book at ${graph.horizon!.addressBook.file} updated!`) console.log(`Address book at ${graph.subgraphService!.addressBook.file} updated!`) From 4260ce6e19d5872d56eb8a92461dcf2203b10077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 17 Feb 2025 14:28:18 -0300 Subject: [PATCH 05/15] chore: update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- packages/horizon/README.md | 4 ++-- packages/subgraph-service/README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/horizon/README.md b/packages/horizon/README.md index 57614c160..55408891a 100644 --- a/packages/horizon/README.md +++ b/packages/horizon/README.md @@ -41,8 +41,8 @@ Usually you would run this against a network (or a fork) where the original Grap ```bash npx hardhat deploy:migrate --network hardhat --step 1 npx hardhat deploy:migrate --network hardhat --step 2 # Run with governor. Optionally add --patch-config -npx hardhat deploy:migrate --network hardhat --step 3 +npx hardhat deploy:migrate --network hardhat --step 3 # Optionally add --patch-config npx hardhat deploy:migrate --network hardhat --step 4 # Run with governor. Optionally add --patch-config ``` -Steps 2 and 4 require patching the configuration file with addresses from previous steps. The files are located in the `ignition/configs` directory and need to be manually edited. You can also pass `--patch-config` flag to the deploy command to automatically patch the configuration reading values from the address book. Note that this will NOT update the configuration file. \ No newline at end of file +Steps 2, 3 and 4 require patching the configuration file with addresses from previous steps. The files are located in the `ignition/configs` directory and need to be manually edited. You can also pass `--patch-config` flag to the deploy command to automatically patch the configuration reading values from the address book. Note that this will NOT update the configuration file. \ No newline at end of file diff --git a/packages/subgraph-service/README.md b/packages/subgraph-service/README.md index bc49a201a..c8d521d3b 100644 --- a/packages/subgraph-service/README.md +++ b/packages/subgraph-service/README.md @@ -48,4 +48,4 @@ cd subgraph-service && npx hardhat deploy:migrate --network hardhat --step 2 && cd horizon && npx hardhat deploy:migrate --network hardhat --step 4 && cd .. # Run with governor. Optionally add --patch-config ``` -Horizon Steps 2 and 4, and Subgraph Service Step 2 require patching the configuration file with addresses from previous steps. The files are located in the `ignition/configs` directory and need to be manually edited. You can also pass `--patch-config` flag to the deploy command to automatically patch the configuration reading values from the address book. Note that this will NOT update the configuration file. \ No newline at end of file +Horizon Steps 2, 3 and 4, and Subgraph Service Step 2 require patching the configuration file with addresses from previous steps. The files are located in the `ignition/configs` directory and need to be manually edited. You can also pass `--patch-config` flag to the deploy command to automatically patch the configuration reading values from the address book. Note that this will NOT update the configuration file. \ No newline at end of file From f978dbb4d78f6deee3e2a3959d471128b205f1fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Mon, 17 Feb 2025 14:31:32 -0300 Subject: [PATCH 06/15] chore: remove not used deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- packages/hardhat-graph-protocol/package.json | 2 -- yarn.lock | 2 -- 2 files changed, 4 deletions(-) diff --git a/packages/hardhat-graph-protocol/package.json b/packages/hardhat-graph-protocol/package.json index fc9f247c0..7140122db 100644 --- a/packages/hardhat-graph-protocol/package.json +++ b/packages/hardhat-graph-protocol/package.json @@ -47,9 +47,7 @@ "json5": "^2.2.3" }, "devDependencies": { - "@nomicfoundation/hardhat-ignition": "^0.15.9", "@nomicfoundation/hardhat-verify": "^2.0.12", - "@nomicfoundation/ignition-core": "^0.15.9", "@types/chai": "^4.0.0", "@types/debug": "^4.1.12", "@types/mocha": "^10.0.9", diff --git a/yarn.lock b/yarn.lock index f21ea08c1..837fcb1a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14468,9 +14468,7 @@ __metadata: "@graphprotocol/horizon": "workspace:^0.0.1" "@graphprotocol/subgraph-service": "workspace:^0.0.1" "@nomicfoundation/hardhat-ethers": "npm:^3.0.8" - "@nomicfoundation/hardhat-ignition": "npm:^0.15.9" "@nomicfoundation/hardhat-verify": "npm:^2.0.12" - "@nomicfoundation/ignition-core": "npm:^0.15.9" "@types/chai": "npm:^4.0.0" "@types/debug": "npm:^4.1.12" "@types/mocha": "npm:^10.0.9" From 176d5b183a5559fc3ce43d0bf975f1df21609c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 18 Feb 2025 10:40:43 -0300 Subject: [PATCH 07/15] fix: dont import tasks on initial build run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- packages/horizon/hardhat.config.ts | 3 +-- packages/subgraph-service/hardhat.config.ts | 3 +-- packages/subgraph-service/package.json | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/horizon/hardhat.config.ts b/packages/horizon/hardhat.config.ts index eb62f0f2a..6efe24059 100644 --- a/packages/horizon/hardhat.config.ts +++ b/packages/horizon/hardhat.config.ts @@ -8,11 +8,10 @@ import 'hardhat-storage-layout' import 'hardhat-contract-sizer' import 'hardhat-secure-accounts' -import './tasks/deploy' - // Skip importing hardhat-graph-protocol when building the project, it has circular dependency if (process.env.BUILD_RUN !== 'true') { require('hardhat-graph-protocol') + require('./tasks/deploy') } export default hardhatBaseConfig diff --git a/packages/subgraph-service/hardhat.config.ts b/packages/subgraph-service/hardhat.config.ts index 6683e122a..9660e89b1 100644 --- a/packages/subgraph-service/hardhat.config.ts +++ b/packages/subgraph-service/hardhat.config.ts @@ -10,11 +10,10 @@ import 'hardhat-contract-sizer' import 'hardhat-secure-accounts' import 'solidity-docgen' -import './tasks/deploy' - // Skip importing hardhat-graph-protocol when building the project, it has circular dependency if (process.env.BUILD_RUN !== 'true') { require('hardhat-graph-protocol') + require('./tasks/deploy') } const config: HardhatUserConfig = { diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index ade35a093..ca0d7884c 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -15,7 +15,7 @@ "lint:sol": "prettier --write contracts/**/*.sol test/**/*.sol && solhint --noPrompt --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", "lint": "yarn lint:ts && yarn lint:sol", "clean": "rm -rf build dist cache cache_forge typechain-types", - "build": "forge build --skip test && BUILD_RUN=true hardhat compile", + "build": "BUILD_RUN=true hardhat compile", "test": "forge test && hardhat test" }, "devDependencies": { From fac251544601fad3b73ed92a672d3164a41aff18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 18 Feb 2025 10:47:42 -0300 Subject: [PATCH 08/15] fix: remove dead export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- packages/hardhat-graph-protocol/src/sdk/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/hardhat-graph-protocol/src/sdk/index.ts b/packages/hardhat-graph-protocol/src/sdk/index.ts index 97531b3ea..4bdc82681 100644 --- a/packages/hardhat-graph-protocol/src/sdk/index.ts +++ b/packages/hardhat-graph-protocol/src/sdk/index.ts @@ -1,5 +1,5 @@ -import { loadConfig, mergeConfigs, patchConfig, saveToAddressBook } from './ignition/ignition' +import { loadConfig, patchConfig, saveToAddressBook } from './ignition/ignition' import { hardhatBaseConfig } from './hardhat.base.config' -const IgnitionHelper = { saveToAddressBook, loadConfig, patchConfig, mergeConfigs } +const IgnitionHelper = { saveToAddressBook, loadConfig, patchConfig } export { hardhatBaseConfig, IgnitionHelper } From 9647fa80a8d3bf3d33d219be9939fddbd1ea46d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 18 Feb 2025 12:39:38 -0300 Subject: [PATCH 09/15] chore: skip building token-distribution if api key not set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- packages/token-distribution/scripts/build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/token-distribution/scripts/build b/packages/token-distribution/scripts/build index 7805eacb4..a4f790e89 100755 --- a/packages/token-distribution/scripts/build +++ b/packages/token-distribution/scripts/build @@ -2,5 +2,10 @@ set -eo pipefail +if [ -z "${STUDIO_API_KEY}" ]; then + echo "Warning: STUDIO_API_KEY is not set. Skipping build steps. Some functionality may be limited." + exit 1 +fi + yarn graphclient build yarn run compile \ No newline at end of file From 2e57fe717ab2ccb168b31350326c79befeb9197b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 18 Feb 2025 12:46:39 -0300 Subject: [PATCH 10/15] fix: exit code 0 for token dist script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- packages/token-distribution/scripts/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/token-distribution/scripts/build b/packages/token-distribution/scripts/build index a4f790e89..5f63fc2ee 100755 --- a/packages/token-distribution/scripts/build +++ b/packages/token-distribution/scripts/build @@ -4,7 +4,7 @@ set -eo pipefail if [ -z "${STUDIO_API_KEY}" ]; then echo "Warning: STUDIO_API_KEY is not set. Skipping build steps. Some functionality may be limited." - exit 1 + exit 0 fi yarn graphclient build From 9287fa0ddf793bf438f1ac6b42b8ba14184355b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 18 Feb 2025 13:27:32 -0300 Subject: [PATCH 11/15] chore: add localnostNoSecureAccounts network to base hardhat config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- .../hardhat-graph-protocol/src/sdk/hardhat.base.config.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts index 43b3dc509..a4ef55047 100644 --- a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts +++ b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts @@ -52,6 +52,14 @@ export const networksUserConfig: BaseNetworksUserConfig = { subgraphService: resolveLocalAddressBook('@graphprotocol/subgraph-service/addresses.json'), }, }, + localhostNoSecureAccounts: { + chainId: 31337, + url: 'http://localhost:8545', + deployments: { + horizon: resolveLocalAddressBook('@graphprotocol/horizon/addresses.json'), + subgraphService: resolveLocalAddressBook('@graphprotocol/subgraph-service/addresses.json'), + }, + }, localhost: { chainId: 31337, url: 'http://localhost:8545', From 44dd7eaae7f4b890ab8f85f5ddf67e75aa29c292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 18 Feb 2025 14:01:05 -0300 Subject: [PATCH 12/15] chore: update hardhat-secure-accounts to latest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- .../src/sdk/hardhat.base.config.ts | 8 -------- packages/horizon/package.json | 2 +- packages/subgraph-service/package.json | 2 +- yarn.lock | 20 +++++++++++++++++-- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts index a4ef55047..43b3dc509 100644 --- a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts +++ b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts @@ -52,14 +52,6 @@ export const networksUserConfig: BaseNetworksUserConfig = { subgraphService: resolveLocalAddressBook('@graphprotocol/subgraph-service/addresses.json'), }, }, - localhostNoSecureAccounts: { - chainId: 31337, - url: 'http://localhost:8545', - deployments: { - horizon: resolveLocalAddressBook('@graphprotocol/horizon/addresses.json'), - subgraphService: resolveLocalAddressBook('@graphprotocol/subgraph-service/addresses.json'), - }, - }, localhost: { chainId: 31337, url: 'http://localhost:8545', diff --git a/packages/horizon/package.json b/packages/horizon/package.json index b839c861c..85d6bda27 100644 --- a/packages/horizon/package.json +++ b/packages/horizon/package.json @@ -44,7 +44,7 @@ "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.8", "hardhat-graph-protocol": "workspace:^0.0.1", - "hardhat-secure-accounts": "^1.0.4", + "hardhat-secure-accounts": "^1.0.5", "hardhat-storage-layout": "^0.1.7", "lint-staged": "^15.2.2", "prettier": "^3.2.5", diff --git a/packages/subgraph-service/package.json b/packages/subgraph-service/package.json index ca0d7884c..8ef39142d 100644 --- a/packages/subgraph-service/package.json +++ b/packages/subgraph-service/package.json @@ -45,7 +45,7 @@ "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.8", "hardhat-graph-protocol": "workspace:^0.0.1", - "hardhat-secure-accounts": "^1.0.4", + "hardhat-secure-accounts": "^1.0.5", "hardhat-storage-layout": "^0.1.7", "json5": "^2.2.3", "lint-staged": "^15.2.2", diff --git a/yarn.lock b/yarn.lock index 837fcb1a2..bb708f2c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2954,7 +2954,7 @@ __metadata: hardhat-contract-sizer: "npm:^2.10.0" hardhat-gas-reporter: "npm:^1.0.8" hardhat-graph-protocol: "workspace:^0.0.1" - hardhat-secure-accounts: "npm:^1.0.4" + hardhat-secure-accounts: "npm:^1.0.5" hardhat-storage-layout: "npm:^0.1.7" lint-staged: "npm:^15.2.2" prettier: "npm:^3.2.5" @@ -3049,7 +3049,7 @@ __metadata: hardhat-contract-sizer: "npm:^2.10.0" hardhat-gas-reporter: "npm:^1.0.8" hardhat-graph-protocol: "workspace:^0.0.1" - hardhat-secure-accounts: "npm:^1.0.4" + hardhat-secure-accounts: "npm:^1.0.5" hardhat-storage-layout: "npm:^0.1.7" json5: "npm:^2.2.3" lint-staged: "npm:^15.2.2" @@ -14537,6 +14537,22 @@ __metadata: languageName: node linkType: hard +"hardhat-secure-accounts@npm:^1.0.5": + version: 1.0.5 + resolution: "hardhat-secure-accounts@npm:1.0.5" + dependencies: + debug: "npm:^4.3.4" + enquirer: "npm:^2.3.6" + lodash.clonedeep: "npm:^4.5.0" + prompt-sync: "npm:^4.2.0" + peerDependencies: + "@nomicfoundation/hardhat-ethers": ^3.0.0 + ethers: ^6.13.0 + hardhat: ^2.22.0 + checksum: b1a30f083b1a2919d6aee2f79253edcadff70017e8006df914bba4e6ad9963db622317ca333dfce38f16a9d60ee9425c0591b578cbf8c6db52d617161d4b46ee + languageName: node + linkType: hard + "hardhat-storage-layout@npm:0.1.6": version: 0.1.6 resolution: "hardhat-storage-layout@npm:0.1.6" From 333f98ebcd4d8403105459cdcbe87349448d9e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 18 Feb 2025 15:42:45 -0300 Subject: [PATCH 13/15] feat: allow overriding localhost rpc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- .../hardhat-graph-protocol/src/sdk/hardhat.base.config.ts | 3 ++- packages/horizon/README.md | 6 ++++-- packages/subgraph-service/README.md | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts index 43b3dc509..32f3835c2 100644 --- a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts +++ b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts @@ -12,6 +12,7 @@ interface SecureAccountsOptions { // RPCs const ARBITRUM_ONE_RPC = vars.get('ARBITRUM_ONE_RPC', 'https://arb1.arbitrum.io/rpc') const ARBITRUM_SEPOLIA_RPC = vars.get('ARBITRUM_SEPOLIA_RPC', 'https://sepolia-rollup.arbitrum.io/rpc') +const LOCALHOST_RPC = vars.get('LOCALHOST_RPC', 'http://localhost:8545') export const solidityUserConfig: SolidityUserConfig = { version: '0.8.27', @@ -54,7 +55,7 @@ export const networksUserConfig: BaseNetworksUserConfig = { }, localhost: { chainId: 31337, - url: 'http://localhost:8545', + url: LOCALHOST_RPC, secureAccounts: { enabled: true, }, diff --git a/packages/horizon/README.md b/packages/horizon/README.md index 55408891a..2e681dcab 100644 --- a/packages/horizon/README.md +++ b/packages/horizon/README.md @@ -8,8 +8,10 @@ The following environment variables might be required: | Variable | Description | |----------|-------------| -| `ARBISCAN_API_KEY` | Arbiscan API key | -| `ARBITRUM_SEPOLIA_RPC` | Arbitrum Sepolia RPC URL | +| `ARBISCAN_API_KEY` | Arbiscan API key - for contract verification| +| `ARBITRUM_ONE_RPC` | Arbitrum One RPC URL - defaults to `https://arb1.arbitrum.io/rpc` | +| `ARBITRUM_SEPOLIA_RPC` | Arbitrum Sepolia RPC URL - defaults to `https://sepolia-rollup.arbitrum.io/rpc` | +| `LOCALHOST_RPC` | Localhost RPC URL - defaults to `http://localhost:8545` | You can set them using Hardhat: diff --git a/packages/subgraph-service/README.md b/packages/subgraph-service/README.md index c8d521d3b..d87d26d76 100644 --- a/packages/subgraph-service/README.md +++ b/packages/subgraph-service/README.md @@ -8,8 +8,10 @@ The following environment variables might be required: | Variable | Description | |----------|-------------| -| `ARBISCAN_API_KEY` | Arbiscan API key | -| `ARBITRUM_SEPOLIA_RPC` | Arbitrum Sepolia RPC URL | +| `ARBISCAN_API_KEY` | Arbiscan API key - for contract verification| +| `ARBITRUM_ONE_RPC` | Arbitrum One RPC URL - defaults to `https://arb1.arbitrum.io/rpc` | +| `ARBITRUM_SEPOLIA_RPC` | Arbitrum Sepolia RPC URL - defaults to `https://sepolia-rollup.arbitrum.io/rpc` | +| `LOCALHOST_RPC` | Localhost RPC URL - defaults to `http://localhost:8545` | You can set them using Hardhat: From e5aa136bb7c5b5f894d7572eb3f17c6d3597e67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 18 Feb 2025 16:12:24 -0300 Subject: [PATCH 14/15] chore: make localhost chain id a configurable variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- .../hardhat-graph-protocol/src/sdk/hardhat.base.config.ts | 5 +++-- packages/horizon/README.md | 1 + packages/subgraph-service/README.md | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts index 32f3835c2..b97e07273 100644 --- a/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts +++ b/packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts @@ -9,10 +9,11 @@ interface SecureAccountsOptions { enabled?: boolean } -// RPCs +// Hardhat variables const ARBITRUM_ONE_RPC = vars.get('ARBITRUM_ONE_RPC', 'https://arb1.arbitrum.io/rpc') const ARBITRUM_SEPOLIA_RPC = vars.get('ARBITRUM_SEPOLIA_RPC', 'https://sepolia-rollup.arbitrum.io/rpc') const LOCALHOST_RPC = vars.get('LOCALHOST_RPC', 'http://localhost:8545') +const LOCALHOST_CHAIN_ID = vars.get('LOCALHOST_CHAIN_ID', '31337') export const solidityUserConfig: SolidityUserConfig = { version: '0.8.27', @@ -54,7 +55,7 @@ export const networksUserConfig: BaseNetworksUserConfig = { }, }, localhost: { - chainId: 31337, + chainId: parseInt(LOCALHOST_CHAIN_ID), url: LOCALHOST_RPC, secureAccounts: { enabled: true, diff --git a/packages/horizon/README.md b/packages/horizon/README.md index 2e681dcab..748286c2e 100644 --- a/packages/horizon/README.md +++ b/packages/horizon/README.md @@ -12,6 +12,7 @@ The following environment variables might be required: | `ARBITRUM_ONE_RPC` | Arbitrum One RPC URL - defaults to `https://arb1.arbitrum.io/rpc` | | `ARBITRUM_SEPOLIA_RPC` | Arbitrum Sepolia RPC URL - defaults to `https://sepolia-rollup.arbitrum.io/rpc` | | `LOCALHOST_RPC` | Localhost RPC URL - defaults to `http://localhost:8545` | +| `LOCALHOST_CHAIN_ID` | Localhost chain ID - defaults to `31337` | You can set them using Hardhat: diff --git a/packages/subgraph-service/README.md b/packages/subgraph-service/README.md index d87d26d76..19522dfcd 100644 --- a/packages/subgraph-service/README.md +++ b/packages/subgraph-service/README.md @@ -12,7 +12,7 @@ The following environment variables might be required: | `ARBITRUM_ONE_RPC` | Arbitrum One RPC URL - defaults to `https://arb1.arbitrum.io/rpc` | | `ARBITRUM_SEPOLIA_RPC` | Arbitrum Sepolia RPC URL - defaults to `https://sepolia-rollup.arbitrum.io/rpc` | | `LOCALHOST_RPC` | Localhost RPC URL - defaults to `http://localhost:8545` | - +| `LOCALHOST_CHAIN_ID` | Localhost chain ID - defaults to `31337` | You can set them using Hardhat: ```bash From cbeb2e5efd17c7446b9d55ca1842fee9280861d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Tue, 18 Feb 2025 16:21:11 -0300 Subject: [PATCH 15/15] fix: ignition script bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: TomΓ‘s Migone --- packages/subgraph-service/ignition/modules/Curation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/subgraph-service/ignition/modules/Curation.ts b/packages/subgraph-service/ignition/modules/Curation.ts index b8cac18b9..9851a86ed 100644 --- a/packages/subgraph-service/ignition/modules/Curation.ts +++ b/packages/subgraph-service/ignition/modules/Curation.ts @@ -10,8 +10,8 @@ export default buildModule('L2Curation', (m) => { const curationAddress = m.getParameter('curationAddress') const curationImplementationAddress = m.getParameter('curationImplementationAddress') - const L2Curation = m.contractAt('L2Curation', CurationArtifact, curationAddress) - const L2CurationImplementation = m.contractAt('L2CurationImplementation', CurationArtifact, curationImplementationAddress) + const L2Curation = m.contractAt('L2CurationAddressBook', CurationArtifact, curationAddress) + const L2CurationImplementation = m.contractAt('L2CurationImplementationAddressBook', CurationArtifact, curationImplementationAddress) return { L2Curation, L2CurationImplementation } })