Skip to content

Commit

Permalink
Merge pull request #1094 from graphprotocol/tmigone/tooling-improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
tmigone authored Jan 28, 2025
2 parents c3c94ca + ea21739 commit 4799228
Show file tree
Hide file tree
Showing 17 changed files with 184 additions and 113 deletions.
2 changes: 2 additions & 0 deletions packages/hardhat-graph-protocol/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"json5": "^2.2.3"
},
"devDependencies": {
"@nomicfoundation/hardhat-verify": "^2.0.12",
"@types/chai": "^4.0.0",
"@types/debug": "^4.1.12",
"@types/mocha": "^10.0.9",
Expand All @@ -55,6 +56,7 @@
"eslint-graph-config": "workspace:^0.0.1",
"ethers": "^6.13.4",
"hardhat": "^2.22.16",
"hardhat-secure-accounts": "^1.0.4",
"mocha": "^10.8.2",
"ts-node": "^8.0.0",
"typescript": "^5.6.3"
Expand Down
107 changes: 107 additions & 0 deletions packages/hardhat-graph-protocol/src/sdk/hardhat.base.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { vars } from 'hardhat/config'

import type { HardhatUserConfig, NetworksUserConfig, ProjectPathsUserConfig, SolidityUserConfig } from 'hardhat/types'
import type { EtherscanConfig } from '@nomicfoundation/hardhat-verify/types'

// This next import ensures secure accounts config is correctly typed
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type { SecureAccountsOptions } from 'hardhat-secure-accounts/src/type-extensions'

// Environment variables
const ARBISCAN_API_KEY = vars.get('ARBISCAN_API_KEY', undefined)

// RPCs
const VIRTUAL_ARBITRUM_SEPOLIA_RPC = vars.has('VIRTUAL_ARBITRUM_SEPOLIA_RPC') ? vars.get('VIRTUAL_ARBITRUM_SEPOLIA_RPC') : undefined
const ARBITRUM_SEPOLIA_RPC = vars.get('ARBITRUM_SEPOLIA_RPC', 'https://sepolia-rollup.arbitrum.io/rpc')

// Accounts
const DEPLOYER_PRIVATE_KEY = vars.get('DEPLOYER_PRIVATE_KEY', undefined)
const GOVERNOR_PRIVATE_KEY = vars.get('GOVERNOR_PRIVATE_KEY', undefined)
const getTestnetAccounts = () => {
const accounts: string[] = []
if (DEPLOYER_PRIVATE_KEY) accounts.push(DEPLOYER_PRIVATE_KEY)
if (GOVERNOR_PRIVATE_KEY) accounts.push(GOVERNOR_PRIVATE_KEY)
return accounts.length > 0 ? accounts : undefined
}
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: {
optimizer: {
enabled: true,
runs: 1,
},
},
}

export const projectPathsUserConfig: ProjectPathsUserConfig = {
artifacts: './build/contracts',
sources: './contracts',
}

export const etherscanUserConfig: Partial<EtherscanConfig> = {
apiKey: {
arbitrumSepolia: ARBISCAN_API_KEY,
},
customChains: [
{
network: 'arbitrumSepolia',
chainId: 421614,
urls: { apiURL: 'https://api-sepolia.arbiscan.io/api', browserURL: 'https://sepolia.arbiscan.io/' },
},
],
}

// In general:
// - hardhat is used for unit tests
// - localhost is used for local development on a hardhat network or fork
// - virtualArbitrumSepolia is for Tenderly Virtual Testnet
export const networksUserConfig: NetworksUserConfig = {
hardhat: {
chainId: 31337,
accounts: getHardhatAccounts(),
},
localhost: {
chainId: 31337,
url: 'http://localhost:8545',
accounts: getTestnetAccounts(),
},
arbitrumSepolia: {
chainId: 421614,
url: ARBITRUM_SEPOLIA_RPC,
secureAccounts: {
enabled: true,
},
},
...(VIRTUAL_ARBITRUM_SEPOLIA_RPC && {
virtualArbitrumSepolia: {
chainId: 421615,
url: VIRTUAL_ARBITRUM_SEPOLIA_RPC,
accounts: getTestnetAccounts(),
},
}),
}

export const hardhatBaseConfig: HardhatUserConfig & { etherscan: Partial<EtherscanConfig> } = {
solidity: solidityUserConfig,
paths: projectPathsUserConfig,
secureAccounts: {
enabled: false,
},
networks: networksUserConfig,
graph: {
deployments: {
horizon: {
addressBook: 'addresses.json',
},
},
},
etherscan: etherscanUserConfig,
}

export default hardhatBaseConfig
4 changes: 2 additions & 2 deletions packages/hardhat-graph-protocol/src/sdk/ignition/ignition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import path from 'path'

export function loadConfig(configPath: string, prefix: string, networkName: string): any {
const configFileCandidates = [
path.join(require.main?.path ?? '', configPath, `${prefix}.${networkName}.json5`),
path.join(require.main?.path ?? '', configPath, `${prefix}.default.json5`),
path.resolve(process.cwd(), configPath, `${prefix}.${networkName}.json5`),
path.resolve(process.cwd(), configPath, `${prefix}.default.json5`),
]

const configFile = configFileCandidates.find(file => fs.existsSync(file))
Expand Down
4 changes: 3 additions & 1 deletion packages/hardhat-graph-protocol/src/sdk/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { loadConfig, saveAddressBook } from './ignition/ignition'
import { hardhatBaseConfig } from './hardhat.base.config'

export const IgnitionHelper = { saveAddressBook, loadConfig }
const IgnitionHelper = { saveAddressBook, loadConfig }
export { hardhatBaseConfig, IgnitionHelper }
18 changes: 12 additions & 6 deletions packages/horizon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ Graph Horizon is the next evolution of the Graph Protocol.

The following environment variables might be required:

- `ETHERSCAN_API_KEY`: Etherscan API key
| 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:

```bash
npx hardhat vars set ETHERSCAN_API_KEY
npx hardhat vars set <variable>
```

## Build
Expand All @@ -23,20 +29,20 @@ yarn build

## Deploy

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.

### New deployment
To deploy Graph Horizon from scratch run the following command:

```bash
npx hardhat run scripts/deploy.ts --network hardhat
```

Note that this will deploy a standalone version of Graph Horizon contracts, meaning the Subgraph Service or any other data service will not be deployed. If you want to deploy the Subgraph Service please refer to the [Subgraph Service README](../subgraph-service/README.md) for deploy instructions.

### Upgrade deployment
To upgrade an existing deployment of the original Graph Protocol to Graph Horizon, run the following command:

```bash
npx hardhat run scripts/migrate.ts --network hardhat
npx hardhat run scripts/migrate.ts --network localhost
```

Note that this will deploy a standalone version of Graph Horizon contracts, meaning the Subgraph Service or any other data service will not be deployed. If you want to deploy the Subgraph Service please refer to the [Subgraph Service README](../subgraph-service/README.md) for deploy instructions.
Usually you would run this against a network (or a fork) where the original Graph Protocol was previously deployed.
90 changes: 2 additions & 88 deletions packages/horizon/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,101 +1,15 @@
import { vars } from 'hardhat/config'

import type { HardhatUserConfig } from 'hardhat/config'
import { hardhatBaseConfig } from 'hardhat-graph-protocol/sdk'

// Hardhat plugins
import '@nomicfoundation/hardhat-foundry'
import '@nomicfoundation/hardhat-toolbox'
import '@nomicfoundation/hardhat-ignition-ethers'
import '@tenderly/hardhat-tenderly'
import 'hardhat-storage-layout'
import 'hardhat-contract-sizer'
import 'hardhat-secure-accounts'

// Environment variables
const ETHERSCAN_API_KEY = vars.get('ETHERSCAN_API_KEY', '')
const ARBITRUM_VIRTUAL_TESTNET_URL = vars.get('ARBITRUM_VIRTUAL_TESTNET_URL', '')
const DEPLOYER_PRIVATE_KEY = vars.get('DEPLOYER_PRIVATE_KEY')
const GOVERNOR_PRIVATE_KEY = vars.get('GOVERNOR_PRIVATE_KEY')

const getNetworkAccounts = () => {
const accounts: string[] = []
if (vars.has('DEPLOYER_PRIVATE_KEY')) accounts.push(DEPLOYER_PRIVATE_KEY)
if (vars.has('GOVERNOR_PRIVATE_KEY')) accounts.push(GOVERNOR_PRIVATE_KEY)
return accounts.length > 0 ? accounts : undefined
}

if (process.env.BUILD_RUN !== 'true') {
require('hardhat-graph-protocol')
}

const config: HardhatUserConfig = {
solidity: {
version: '0.8.27',
settings: {
optimizer: {
enabled: true,
runs: 1,
},
},
},
paths: {
artifacts: './build/contracts',
sources: './contracts',
},
secureAccounts: {
enabled: false,
},
networks: {
hardhat: {
chainId: 31337,
accounts: {
mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect',
},
},
localhost: {
chainId: 31337,
url: 'http://localhost:8545',
accounts: getNetworkAccounts(),
},
arbitrumSepolia: {
chainId: 421614,
secureAccounts: {
enabled: true,
},
url: 'https://sepolia-rollup.arbitrum.io/rpc',
},
arbitrumVirtualTestnet: {
chainId: 421615,
url: ARBITRUM_VIRTUAL_TESTNET_URL,
accounts: getNetworkAccounts(),
},
},
tenderly: {
project: 'graph-network',
username: 'graphprotocol',
},
graph: {
deployments: {
horizon: {
addressBook: 'addresses.json',
},
},
},
etherscan: {
apiKey: {
arbitrumSepolia: ETHERSCAN_API_KEY,
},
customChains: [
{
network: 'arbitrumSepolia',
chainId: 421614,
urls: {
apiURL: 'https://api-sepolia.arbiscan.io/api',
browserURL: 'https://sepolia.arbiscan.io/',
},
},
],
},
}

export default config
export default hardhatBaseConfig
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
{
"$global": {
"governor": "0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0",
"pauseGuardian": "0x95cED938F7991cd0dFcb48F0a06a40FA1aF46EBC",
"subgraphAvailabilityOracle": "0xd03ea8624C8C5987235048901fB614fDcA89b117",
// Placeholder address for a standalone Horizon deployment, see README.md for more details
"subgraphServiceAddress": "0x0000000000000000000000000000000000000000"
},
"RewardsManager": {
"subgraphAvailabilityOracle": "0xd03ea8624C8C5987235048901fB614fDcA89b117",
"issuancePerBlock": "114155251141552511415n"
},
"EpochManager": {
Expand Down
6 changes: 6 additions & 0 deletions packages/horizon/ignition/modules/core/GraphPayments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default buildModule('GraphPayments', (m) => {
const { Controller } = m.useModule(GraphPeripheryModule)
const { GraphPaymentsProxyAdmin, GraphPaymentsProxy } = m.useModule(HorizonProxiesModule)

const governor = m.getAccount(1)
const protocolPaymentCut = m.getParameter('protocolPaymentCut')

// Deploy GraphPayments implementation - requires periphery and proxies to be registered in the controller
Expand All @@ -30,13 +31,16 @@ export default buildModule('GraphPayments', (m) => {
initArgs: [],
})

m.call(GraphPaymentsProxyAdmin, 'transferOwnership', [governor], { after: [GraphPayments] })

return { GraphPayments, GraphPaymentsProxyAdmin }
})

export const MigrateGraphPaymentsModule = buildModule('GraphPayments', (m) => {
const { GraphPaymentsProxyAdmin, GraphPaymentsProxy } = m.useModule(MigrateHorizonProxiesModule)
const { Controller } = m.useModule(MigratePeripheryModule)

const governor = m.getAccount(1)
const protocolPaymentCut = m.getParameter('protocolPaymentCut')

// Deploy GraphPayments implementation
Expand All @@ -56,5 +60,7 @@ export const MigrateGraphPaymentsModule = buildModule('GraphPayments', (m) => {
initArgs: [],
})

m.call(GraphPaymentsProxyAdmin, 'transferOwnership', [governor], { after: [GraphPayments] })

return { GraphPayments, GraphPaymentsProxyAdmin }
})
6 changes: 6 additions & 0 deletions packages/horizon/ignition/modules/core/PaymentsEscrow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default buildModule('PaymentsEscrow', (m) => {
const { Controller } = m.useModule(GraphPeripheryModule)
const { PaymentsEscrowProxyAdmin, PaymentsEscrowProxy } = m.useModule(HorizonProxiesModule)

const governor = m.getAccount(1)
const withdrawEscrowThawingPeriod = m.getParameter('withdrawEscrowThawingPeriod')

// Deploy PaymentsEscrow implementation - requires periphery and proxies to be registered in the controller
Expand All @@ -30,13 +31,16 @@ export default buildModule('PaymentsEscrow', (m) => {
initArgs: [],
})

m.call(PaymentsEscrowProxyAdmin, 'transferOwnership', [governor], { after: [PaymentsEscrow] })

return { PaymentsEscrow, PaymentsEscrowProxyAdmin }
})

export const MigratePaymentsEscrowModule = buildModule('PaymentsEscrow', (m) => {
const { PaymentsEscrowProxyAdmin, PaymentsEscrowProxy } = m.useModule(MigrateHorizonProxiesModule)
const { Controller } = m.useModule(MigratePeripheryModule)

const governor = m.getAccount(1)
const withdrawEscrowThawingPeriod = m.getParameter('withdrawEscrowThawingPeriod')

// Deploy PaymentsEscrow implementation
Expand All @@ -56,5 +60,7 @@ export const MigratePaymentsEscrowModule = buildModule('PaymentsEscrow', (m) =>
initArgs: [],
})

m.call(PaymentsEscrowProxyAdmin, 'transferOwnership', [governor], { after: [PaymentsEscrow] })

return { PaymentsEscrow, PaymentsEscrowProxyAdmin }
})
10 changes: 10 additions & 0 deletions packages/horizon/ignition/modules/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ export default buildModule('GraphHorizon_Deploy', (m) => {
TAPCollector,
} = m.useModule(GraphHorizonCoreModule)

const governor = m.getAccount(1)

// BUG?: acceptOwnership should be called after everything in GraphHorizonCoreModule and GraphPeripheryModule is resolved
// but it seems that it's not waiting for interal calls. Waiting on HorizonStaking seems to fix the issue for some reason
// Removing HorizonStaking from the after list will trigger the bug

// Accept ownership of Graph Governed based contracts
m.call(Controller, 'acceptOwnership', [], { from: governor, after: [GraphPeripheryModule, GraphHorizonCoreModule, HorizonStaking] })
m.call(GraphProxyAdmin, 'acceptOwnership', [], { from: governor, after: [GraphPeripheryModule, GraphHorizonCoreModule, HorizonStaking] })

return {
Controller,
L2Curation,
Expand Down
Loading

0 comments on commit 4799228

Please sign in to comment.