diff --git a/.example.env b/.example.env index 72916eb..4b5f6ff 100644 --- a/.example.env +++ b/.example.env @@ -9,3 +9,4 @@ ETHERSCAN_API_KEY= ARBISCAN_API_KEY= POLYGON_RPC_URL= ARBITRUM_RPC_URL= +ADDRESS_BOOK="addresses.json" diff --git a/addresses-staging.json b/addresses-staging.json new file mode 100644 index 0000000..7cb2b53 --- /dev/null +++ b/addresses-staging.json @@ -0,0 +1,16 @@ +{ + "421614": { + "L2GraphToken": "0xf8c05dCF59E8B28BFD5eed176C562bEbcfc7Ac04", + "L2GraphTokenGateway": "0xB24Ce0f8c18c4DdDa584A7EeC132F49C966813bb", + "collector": "0x66FFdb62688deA21A0031Db7CD4C219C82e9B315", + "governor": "0x97B47D976b9ddD2608D61E77Ab10DAf05d17cbF9", + "Billing": "0x1AbcE187d2401687520dBf720210a0ec84C0690D" + }, + "11155111": { + "ArbitrumInbox": "0xaAe29B0366299461418F5324a79Afc425BE5ae21", + "GraphToken": "0xCA59cCeb39bE1808d7aA607153f4A5062daF3a83", + "L1GraphTokenGateway": "0x549DCB0b510Ee7C8d6E8e346ab9aC75E22DD78B3", + "governor": "0x20cFA0e7Db2ECd14032784075A4c686befc76758", + "BillingConnector": "0xf9B9FCf0d603e6bead3335953EB5Bcf876990043" + } +} diff --git a/scripts/deployAll b/scripts/deployAll index 45b83c7..11ba83a 100755 --- a/scripts/deployAll +++ b/scripts/deployAll @@ -50,41 +50,46 @@ else error_exit "Please set a valid L2_CHAINID in .env" fi -collector=$(jq -r ".[\"$L2_CHAINID\"].collector" addresses.json || echo "null") +ADDRESS_BOOK=${ADDRESS_BOOK:-"addresses.json"} + +echo "Using address book: $ADDRESS_BOOK" + +collector=$(jq -r ".[\"$L2_CHAINID\"].collector" $ADDRESS_BOOK || echo "null") if [[ "$collector" = "null" ]]; then - error_exit "Please set a collector for chainID $L2_CHAINID in addresses.json" + error_exit "Please set a collector for chainID $L2_CHAINID in $ADDRESS_BOOK" fi -L2GraphToken=$(jq -r ".[\"$L2_CHAINID\"].L2GraphToken" addresses.json || echo "null") +L2GraphToken=$(jq -r ".[\"$L2_CHAINID\"].L2GraphToken" $ADDRESS_BOOK || echo "null") if [[ "$L2GraphToken" = "null" ]]; then - error_exit "Please set an L2GraphToken for chainID $L2_CHAINID in addresses.json" + error_exit "Please set an L2GraphToken for chainID $L2_CHAINID in $ADDRESS_BOOK" fi -l2Governor=$(jq -r ".[\"$L2_CHAINID\"].governor" addresses.json || echo "null") +l2Governor=$(jq -r ".[\"$L2_CHAINID\"].governor" $ADDRESS_BOOK || echo "null") if [[ "$l2Governor" = "null" ]]; then - error_exit "Please set a governor for chainID $L2_CHAINID in addresses.json" + error_exit "Please set a governor for chainID $L2_CHAINID in $ADDRESS_BOOK" fi -L2GraphTokenGateway=$(jq -r ".[\"$L2_CHAINID\"].L2GraphTokenGateway" addresses.json || echo "null") +L2GraphTokenGateway=$(jq -r ".[\"$L2_CHAINID\"].L2GraphTokenGateway" $ADDRESS_BOOK || echo "null") if [[ "$L2GraphTokenGateway" = "null" ]]; then - error_exit "Please set an L2GraphTokenGateway for chainID $L2_CHAINID in addresses.json" + error_exit "Please set an L2GraphTokenGateway for chainID $L2_CHAINID in $ADDRESS_BOOK" fi - export MNEMONIC="$L2_MNEMONIC" +export MNEMONIC="$L2_MNEMONIC" l2Deployer=$(npx hardhat print-account --network $L2_NETWORK --num 0) echo "Using L2 deployer $l2Deployer" echo "Deploying Billing:" npx hardhat deploy-billing --network $L2_NETWORK \ + --address-book $ADDRESS_BOOK \ --collector $collector \ --token $L2GraphToken \ --governor $l2Deployer \ --tokengateway $L2GraphTokenGateway -Billing=$(jq -r ".[\"$L2_CHAINID\"].Billing" addresses.json || echo "null") +Billing=$(jq -r ".[\"$L2_CHAINID\"].Billing" $ADDRESS_BOOK || echo "null") if [[ "$Billing" = "null" ]]; then - error_exit "Could not get new Billing address from addresses.json" + error_exit "Could not get new Billing address from $ADDRESS_BOOK" else echo "Billing deployed to $Billing" fi @@ -105,24 +110,24 @@ if ! verify_billing; then verify_billing fi -GraphToken=$(jq -r ".[\"$L1_CHAINID\"].GraphToken" addresses.json || echo "null") +GraphToken=$(jq -r ".[\"$L1_CHAINID\"].GraphToken" $ADDRESS_BOOK || echo "null") if [[ "$GraphToken" = "null" ]]; then - error_exit "Please set a GraphToken for chainID $L1_CHAINID in addresses.json" + error_exit "Please set a GraphToken for chainID $L1_CHAINID in $ADDRESS_BOOK" fi -l1Governor=$(jq -r ".[\"$L1_CHAINID\"].governor" addresses.json || echo "null") +l1Governor=$(jq -r ".[\"$L1_CHAINID\"].governor" $ADDRESS_BOOK || echo "null") if [[ "$l1Governor" = "null" ]]; then - error_exit "Please set a governor for chainID $L1_CHAINID in addresses.json" + error_exit "Please set a governor for chainID $L1_CHAINID in $ADDRESS_BOOK" fi -L1GraphTokenGateway=$(jq -r ".[\"$L1_CHAINID\"].L1GraphTokenGateway" addresses.json || echo "null") +L1GraphTokenGateway=$(jq -r ".[\"$L1_CHAINID\"].L1GraphTokenGateway" $ADDRESS_BOOK || echo "null") if [[ "$L1GraphTokenGateway" = "null" ]]; then - error_exit "Please set an L1GraphTokenGateway for chainID $L1_CHAINID in addresses.json" + error_exit "Please set an L1GraphTokenGateway for chainID $L1_CHAINID in $ADDRESS_BOOK" fi -ArbitrumInbox=$(jq -r ".[\"$L1_CHAINID\"].ArbitrumInbox" addresses.json || echo "null") +ArbitrumInbox=$(jq -r ".[\"$L1_CHAINID\"].ArbitrumInbox" $ADDRESS_BOOK || echo "null") if [[ "$ArbitrumInbox" = "null" ]]; then - error_exit "Please set an ArbitrumInbox for chainID $L1_CHAINID in addresses.json" + error_exit "Please set an ArbitrumInbox for chainID $L1_CHAINID in $ADDRESS_BOOK" fi l1Deployer=$(MNEMONIC=$L1_MNEMONIC npx hardhat print-account --network $L1_NETWORK --num 0) @@ -132,15 +137,16 @@ echo "Using L1 deployer $l1Deployer" export MNEMONIC="$L1_MNEMONIC" echo "Deploying BillingConnector:" npx hardhat deploy-billing-connector --network $L1_NETWORK \ + --address-book $ADDRESS_BOOK \ --tokengateway $L1GraphTokenGateway \ --billing $Billing \ --token $GraphToken \ --governor $l1Governor \ --inbox $ArbitrumInbox -BillingConnector=$(jq -r ".[\"$L1_CHAINID\"].BillingConnector" addresses.json || echo "null") +BillingConnector=$(jq -r ".[\"$L1_CHAINID\"].BillingConnector" $ADDRESS_BOOK || echo "null") if [[ "$BillingConnector" = "null" ]]; then - error_exit "Could not get new BillingConnector address from addresses.json" + error_exit "Could not get new BillingConnector address from $ADDRESS_BOOK" fi function verify_billing_connector() { @@ -163,6 +169,7 @@ fi export MNEMONIC="$L2_MNEMONIC" echo "Connecting Billing to BillingConnector, and (optionally) transferring ownership:" npx hardhat configure-billing --network $L2_NETWORK \ + --address-book $ADDRESS_BOOK \ --governor $l2Governor \ --billingconnector $BillingConnector diff --git a/tasks/deployment/banxa.ts b/tasks/deployment/banxa.ts index 381d3ff..2e89bf1 100644 --- a/tasks/deployment/banxa.ts +++ b/tasks/deployment/banxa.ts @@ -2,12 +2,13 @@ import { Wallet } from 'ethers' import { task } from 'hardhat/config' import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { getAddressBook } from '../../utils/addressBook' import { deployBanxaWrapper } from '../../utils/deploy' -import addresses from '../../addresses.json' import { promises as fs } from 'fs' task('deploy-banxa', 'Deploy the banxa wrapper contract (use L2 network!)') + .addParam('addressBook', 'Addressese json file name', process.env.ADDRESS_BOOK) .addParam('billing', 'Address of the billing contract') .addParam('token', 'Address of the token') .addParam('governor', 'Address of the governor, leave empty to use the deployer') @@ -18,6 +19,7 @@ task('deploy-banxa', 'Deploy the banxa wrapper contract (use L2 network!)') [taskArgs.token, taskArgs.billing, taskArgs.governor ?? accounts[0].address], accounts[0] as unknown as Wallet, ) + const addresses = getAddressBook(taskArgs.addressBook, chainId) addresses[chainId]['BanxaWrapper'] = banxaWrapper.address - return fs.writeFile('addresses.json', JSON.stringify(addresses, null, 2)) + return fs.writeFile(taskArgs.addressBook, JSON.stringify(addresses, null, 2)) }) diff --git a/tasks/deployment/billing.ts b/tasks/deployment/billing.ts index 575995b..720c0b7 100644 --- a/tasks/deployment/billing.ts +++ b/tasks/deployment/billing.ts @@ -5,12 +5,13 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types' import { deployBilling } from '../../utils/deploy' import { logger } from '../../utils/logging' -import addresses from '../../addresses.json' +import { getAddressBook } from '../../utils/addressBook' import { getContractAt } from '../../utils/contracts' import { Billing } from '../../build/types' import { promises as fs } from 'fs' task('deploy-billing', 'Deploy the billing contract (use L2 network!)') + .addParam('addressBook', 'Addressese json file name', process.env.ADDRESS_BOOK) .addParam('collector', 'Address of the collector') .addParam('token', 'Address of the token') .addParam('governor', 'Address of the governor, leave empty to use the deployer') @@ -22,19 +23,22 @@ task('deploy-billing', 'Deploy the billing contract (use L2 network!)') [taskArgs.collector, taskArgs.token, taskArgs.governor ?? accounts[0].address, taskArgs.tokengateway], accounts[0] as unknown as Wallet, ) + const addresses = getAddressBook(taskArgs.addressBook, chainId) addresses[chainId]['Billing'] = billing.address - return fs.writeFile('addresses.json', JSON.stringify(addresses, null, 2)) + return fs.writeFile(taskArgs.addressBook, JSON.stringify(addresses, null, 2)) }) task( 'configure-billing', 'Configure the billing contract to set billing connector address and transfer ownership to the governor (use L2 network!)', ) + .addParam('addressBook', 'Addressese json file name', process.env.ADDRESS_BOOK) .addParam('governor', 'Address of the governor') .addParam('billingconnector', 'Address of the BillingConnector on L1') .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { const accounts = await hre.ethers.getSigners() const chainId = (hre.network.config.chainId as number).toString() + const addresses = getAddressBook(taskArgs.addressBook, chainId) const addressBook = addresses[chainId] const wallet = accounts[0] as unknown as Wallet const billing = getContractAt('Billing', addressBook['Billing'], wallet) as unknown as Billing diff --git a/tasks/deployment/billingConnector.ts b/tasks/deployment/billingConnector.ts index 8f3242f..1cc9a5f 100644 --- a/tasks/deployment/billingConnector.ts +++ b/tasks/deployment/billingConnector.ts @@ -2,11 +2,12 @@ import { Wallet } from 'ethers' import { task } from 'hardhat/config' import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { getAddressBook } from '../../utils/addressBook' import { deployBillingConnector } from '../../utils/deploy' -import addresses from '../../addresses.json' import { promises as fs } from 'fs' task('deploy-billing-connector', 'Deploy the billing connector contract (use L1 network!)') + .addParam('addressBook', 'Addressese json file name', process.env.ADDRESS_BOOK) .addParam('tokengateway', 'Address of the L1GraphTokenGateway') .addParam('billing', 'Address of the Billing contract on L2') .addParam('token', 'Address of the token') @@ -15,10 +16,11 @@ task('deploy-billing-connector', 'Deploy the billing connector contract (use L1 .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { const accounts = await hre.ethers.getSigners() const chainId = (hre.network.config.chainId as number).toString() + const addresses = getAddressBook(taskArgs.addressBook, chainId) const billingConnector = await deployBillingConnector( [taskArgs.tokengateway, taskArgs.billing, taskArgs.token, taskArgs.governor, taskArgs.inbox], accounts[0] as unknown as Wallet, ) addresses[chainId]['BillingConnector'] = billingConnector.address - return fs.writeFile('addresses.json', JSON.stringify(addresses, null, 2)) + return fs.writeFile(taskArgs.addressBook, JSON.stringify(addresses, null, 2)) }) diff --git a/tasks/extendContracts.ts b/tasks/extendContracts.ts index 4dec675..9e3cdf1 100644 --- a/tasks/extendContracts.ts +++ b/tasks/extendContracts.ts @@ -2,7 +2,7 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types' import { extendEnvironment } from 'hardhat/config' import { lazyObject } from 'hardhat/plugins' -import addresses from '../addresses.json' +import { getAddressBook } from '../utils/addressBook' import { BillingContracts, loadContracts } from '../utils/contracts' declare module 'hardhat/types/runtime' { @@ -12,8 +12,10 @@ declare module 'hardhat/types/runtime' { } extendEnvironment((hre: HardhatRuntimeEnvironment) => { - const chainId = hre.network.config.chainId - const addressBook = addresses[chainId as number] + const chainId = (hre.network.config.chainId as number).toString() + const addressBookPath = process.env.ADDRESS_BOOK || 'addresses.json' + const addresses = getAddressBook(addressBookPath, chainId) + const addressBook = addresses[chainId as unknown as number] hre['contracts'] = lazyObject(() => { return loadContracts( addressBook?.Billing, diff --git a/utils/addressBook.ts b/utils/addressBook.ts new file mode 100644 index 0000000..ca987ce --- /dev/null +++ b/utils/addressBook.ts @@ -0,0 +1,14 @@ +import fs from 'fs' + +export const getAddressBook = (path: string, chainId: string): any => { + if (!path) throw new Error(`A path to the address book file is required.`) + if (!chainId) throw new Error(`A chainId is required.`) + + const addressBook = JSON.parse(fs.readFileSync(path, 'utf8') || '{}') + + if (!addressBook[chainId]) { + addressBook[chainId] = {} + } + + return addressBook +}