Deploy helloworld to mainnet (#622)

* Ensure contracts are connected at end of deploy

* Updates for hello world

* Use promise.allSettled for concurrent networks

* Simplify core transferOwnership

* Return all transfer ownership receipts
pull/645/head
Yorke Rhodes 2 years ago committed by GitHub
parent 1321b9808b
commit 0239ed764d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 43
      typescript/deploy/src/core/deploy.ts
  2. 68
      typescript/deploy/src/deploy.ts
  3. 5
      typescript/deploy/src/router/deploy.ts
  4. 23
      typescript/infra/config/environments/mainnet/helloworld/addresses.json
  5. 2
      typescript/infra/config/environments/mainnet/index.ts
  6. 40
      typescript/infra/scripts/helloworld/deploy.ts
  7. 34
      typescript/infra/scripts/helloworld/kathy.ts

@ -1,7 +1,7 @@
import debug from 'debug';
import { ethers } from 'ethers';
import { Inbox } from '@abacus-network/core';
import { Inbox, Ownable } from '@abacus-network/core';
import {
AbacusCore,
BeaconProxyAddresses,
@ -215,37 +215,24 @@ export class AbacusCoreDeployer<Chain extends ChainName> extends AbacusDeployer<
coreContracts: CoreContracts<Chain, Local>,
owner: types.Address,
chainConnection: ChainConnection,
): Promise<ethers.ContractReceipt> {
await coreContracts.outboxValidatorManager.transferOwnership(
owner,
chainConnection.overrides,
);
await coreContracts.abacusConnectionManager.transferOwnership(
owner,
chainConnection.overrides,
);
await coreContracts.upgradeBeaconController.transferOwnership(
owner,
chainConnection.overrides,
);
const inboxContracts = Object.values<InboxContracts>(coreContracts.inboxes);
await Promise.all(
inboxContracts.map(async (inbox) => {
await inbox.inboxValidatorManager.transferOwnership(
owner,
chainConnection.overrides,
);
await inbox.inbox.contract.transferOwnership(
): Promise<ethers.ContractReceipt[]> {
const ownables: Ownable[] = [
coreContracts.outbox.contract,
coreContracts.outboxValidatorManager,
coreContracts.abacusConnectionManager,
coreContracts.upgradeBeaconController,
...Object.values<InboxContracts>(coreContracts.inboxes).flatMap(
(inbox) => [inbox.inbox.contract, inbox.inboxValidatorManager],
),
];
return Promise.all(
ownables.map(async (ownable) => {
const response = await ownable.transferOwnership(
owner,
chainConnection.overrides,
);
return response.wait(chainConnection.confirmations);
}),
);
const tx = await coreContracts.outbox.contract.transferOwnership(
owner,
chainConnection.overrides,
);
return tx.wait(chainConnection.confirmations);
}
}

@ -13,6 +13,7 @@ import {
ChainName,
MultiProvider,
ProxiedContract,
connectContracts,
objMap,
serializeContracts,
} from '@abacus-network/sdk';
@ -55,7 +56,20 @@ export abstract class AbacusDeployer<
partialDeployment: Partial<Record<Chain, Contracts>> = this
.deployedContracts,
): Promise<Record<Chain, Contracts>> {
const deployedChains = Object.keys(partialDeployment);
objMap(
partialDeployment as ChainMap<Chain, Contracts>,
(chain, contracts) => {
this.logger(
`Recovering contracts for ${chain} from partial deployment`,
);
const chainConnection = this.multiProvider.getChainConnection(chain);
this.deployedContracts[chain] = connectContracts(
contracts,
chainConnection.signer!,
);
},
);
const deployedChains = Object.keys(this.deployedContracts);
const configChains = Object.keys(this.configMap);
const targetChains = this.multiProvider
.chains()
@ -63,35 +77,29 @@ export abstract class AbacusDeployer<
(chain) =>
configChains.includes(chain) && !deployedChains.includes(chain),
);
this.logger(
`Start deploy to ${targetChains} ${
deployedChains.length > 0
? `(already deployed to ${deployedChains})`
: ''
}`,
);
for (const chain of targetChains) {
const chainConnection = this.multiProvider.getChainConnection(chain);
this.logger(
`Deploying to ${chain} from ${await chainConnection.getAddressUrl()}...`,
);
this.deployedContracts[chain] = await this.deployContracts(
chain,
this.configMap[chain],
);
// TODO: remove these logs once we have better timeouts
this.logger(
JSON.stringify(
serializeContracts(this.deployedContracts[chain] ?? {}),
null,
2,
),
);
}
return { ...partialDeployment, ...this.deployedContracts } as Record<
Chain,
Contracts
>;
this.logger(`Start deploy to ${targetChains}`);
// wait until all promises are resolved / rejected
await Promise.allSettled(
targetChains.map(async (chain) => {
const chainConnection = this.multiProvider.getChainConnection(chain);
this.logger(
`Deploying to ${chain} from ${await chainConnection.getAddressUrl()}...`,
);
this.deployedContracts[chain] = await this.deployContracts(
chain,
this.configMap[chain],
);
// TODO: remove these logs once we have better timeouts
this.logger(
JSON.stringify(
serializeContracts(this.deployedContracts[chain] ?? {}),
null,
2,
),
);
}),
);
return this.deployedContracts as ChainMap<Chain, Contracts>;
}
async deployContract<K extends keyof Factories>(

@ -49,6 +49,7 @@ export abstract class AbacusRouterDeployer<
chainConnection.overrides,
);
this.logger(`Pending init ${chainConnection.getTxUrl(response)}`);
await response.wait(chainConnection.confirmations);
return router;
}
@ -90,8 +91,8 @@ export abstract class AbacusRouterDeployer<
);
}
async deploy() {
const contractsMap = await super.deploy();
async deploy(partialDeployment: Partial<Record<Chain, Contracts>>) {
const contractsMap = await super.deploy(partialDeployment);
await this.enrollRemoteRouters(contractsMap);
await this.transferOwnership(contractsMap);

@ -0,0 +1,23 @@
{
"bsc": {
"router": "0xFC62DeF1f08793aBf0E67f69257c6be258194F72"
},
"avalanche": {
"router": "0x82825C0884558C9c5A94B545e7563c95aBA49197"
},
"polygon": {
"router": "0x0054D19613f20dD72721A146ED408971a2CCA9BD"
},
"arbitrum": {
"router": "0xb3d652BA393f83c0Cf7eF5e0Fc30532ebd49d45B"
},
"optimism": {
"router": "0x8249cD1275855F2BB20eE71f0B9fA3c9155E5FaB"
},
"ethereum": {
"router": "0x8202df0d3a5ba6d65fabe63122fAaCC1529E054F"
},
"celo": {
"router": "0x0054D19613f20dD72721A146ED408971a2CCA9BD"
}
}

@ -4,6 +4,7 @@ import { CoreEnvironmentConfig } from '../../../src/config';
import { agent } from './agent';
import { MainnetChains, mainnetConfigs } from './chains';
import { core } from './core';
import helloWorldAddresses from './helloworld/addresses.json';
import { infrastructure } from './infrastructure';
export const environment: CoreEnvironmentConfig<MainnetChains> = {
@ -13,4 +14,5 @@ export const environment: CoreEnvironmentConfig<MainnetChains> = {
agent,
core,
infra: infrastructure,
helloWorldAddresses,
};

@ -1,9 +1,18 @@
import path from 'path';
import { HelloWorldDeployer } from '@abacus-network/helloworld';
import { AbacusCore, serializeContracts } from '@abacus-network/sdk';
import {
HelloWorldContracts,
helloWorldFactories,
} from '@abacus-network/helloworld/dist/sdk/contracts';
import {
AbacusCore,
ChainMap,
buildContracts,
serializeContracts,
} from '@abacus-network/sdk';
import { writeJSON } from '../../src/utils/utils';
import { readJSON, writeJSON } from '../../src/utils/utils';
import {
getCoreEnvironmentConfig,
getEnvironment,
@ -19,9 +28,32 @@ async function main() {
const configMap = await getConfiguration(environment, multiProvider);
const core = AbacusCore.fromEnvironment(environment, multiProvider as any);
const deployer = new HelloWorldDeployer(multiProvider, configMap, core);
const contracts = await deployer.deploy();
const dir = path.join(getEnvironmentDirectory(environment), 'helloworld');
writeJSON(dir, 'addresses.json', serializeContracts(contracts));
let partialContracts: ChainMap<any, HelloWorldContracts>;
try {
const addresses = readJSON(dir, 'partial_addresses.json');
partialContracts = buildContracts(addresses, helloWorldFactories) as any;
} catch (e) {
partialContracts = {};
}
try {
const contracts = await deployer.deploy(partialContracts);
writeJSON(dir, 'addresses.json', serializeContracts(contracts));
writeJSON(
dir,
'verification.json',
JSON.stringify(deployer.verificationInputs),
);
} catch (e) {
console.error(e);
writeJSON(
dir,
'partial_addresses.json',
serializeContracts(deployer.deployedContracts as any),
);
}
}
main()

@ -1,5 +1,5 @@
import { HelloWorldApp } from '@abacus-network/helloworld';
import { ChainName } from '@abacus-network/sdk';
import { ChainName, Chains } from '@abacus-network/sdk';
import { getCoreEnvironmentConfig, getEnvironment } from '../utils';
@ -9,17 +9,20 @@ async function main() {
const environment = await getEnvironment();
const coreConfig = getCoreEnvironmentConfig(environment);
const app = await getApp(coreConfig);
const sources = app.chains();
await Promise.all(
sources.map((source) => {
const destinations = sources.slice().filter((d) => d !== source);
return Promise.all(
destinations.map((destination) =>
sendMessage(app, source, destination),
),
);
}),
);
const chains = app.chains() as Chains[];
const skip = process.env.NETWORKS_TO_SKIP?.split(',');
const invalidChain = chains.find((chain) => skip && !skip.includes(chain));
if (invalidChain) {
throw new Error(`Invalid chain to skip ${invalidChain}`);
}
const sources = chains.filter((chain) => !skip || !skip.includes(chain));
for (const source of sources) {
for (const destination of sources.slice().filter((d) => d !== source)) {
await sendMessage(app, source, destination);
}
}
}
async function sendMessage(
@ -27,11 +30,8 @@ async function sendMessage(
source: ChainName,
destination: ChainName,
) {
const receipt = await app.sendHelloWorld(
source,
destination,
`Hello from ${source} to ${destination}!`,
);
console.log(`Sending message from ${source} to ${destination}`);
const receipt = await app.sendHelloWorld(source, destination, `Hello!`);
console.log(JSON.stringify(receipt.events || receipt.logs));
}

Loading…
Cancel
Save