Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No network issue fix #951

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,16 @@ interface NetworkConfig {
}

const networkConfigs: NetworkConfig[] = [
{ network: 'mainnet', chainId: 1 },
{ network: 'ropsten', chainId: 3 },
{ network: 'rinkeby', chainId: 4 },
{ network: 'goerli', chainId: 5 },
{ network: 'sepolia', chainId: 11155111 },
{
network: 'mainnet',
chainId: 1,
url: `https://rpc.ankr.com/eth/${ANKR_KEY}`,
},
{
network: 'sepolia',
chainId: 11155111,
url: `https://rpc.ankr.com/eth_sepolia/${ANKR_KEY}`,
},
{
network: 'polygon',
chainId: 137,
Expand Down
55 changes: 45 additions & 10 deletions plugins/scenario/Runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,37 @@ export class Runner<T, U, R> {
}
}


async function retry(fn: () => Promise<any>, retries: number = 10, timeLimit?: number, wait: number = 100) {
try {
return await asyncCallWithTimeout(fn(), timeLimit);
} catch (e) {
if (retries === 0) throw e;
if(e.reason !== 'could not detect network')
throw e;

console.warn(`Retrying in ${wait}ms...`);

await new Promise(ok => setTimeout(ok, wait));
return retry(fn, retries - 1, timeLimit, wait >= 10000 ? 10000 : wait * 2);
}
}
async function asyncCallWithTimeout(asyncPromise: Promise<any>, timeLimit: number = 5000_000) {
let timeoutHandle: string | number | NodeJS.Timeout;

const timeoutPromise = new Promise((_resolve, reject) => {
timeoutHandle = setTimeout(
() => reject(new Error('Async call timeout limit reached')),
timeLimit
);
});

return Promise.race([asyncPromise, timeoutPromise]).then(result => {
clearTimeout(timeoutHandle);
return result;
});
}

export async function runScenarios(bases: ForkSpec[]) {
const loader = await Loader.load();
const [runningScenarios, skippedScenarios] = loader.splitScenarios();
Expand All @@ -161,16 +192,20 @@ export async function runScenarios(bases: ForkSpec[]) {
const results: Result[] = [];

for (const base of bases) {
const world = new World(base), dm = world.deploymentManager;
const delta = await dm.runDeployScript({ allMissing: true });
console.log(`[${base.name}] Deployed ${dm.counter} contracts, spent ${dm.spent} to initialize world 🗺`);
console.log(`[${base.name}]\n${dm.diffDelta(delta)}`);

if (world.auxiliaryDeploymentManager) {
await world.auxiliaryDeploymentManager.spider();
}

const runner = new Runner(base, world);
let runner: Runner<unknown, unknown, unknown>;
await retry(async () => {
const world = new World(base);
await world.initialize(base);
const dm = world.deploymentManager;
const delta = await dm.runDeployScript({ allMissing: true });
console.log(`[${base.name}] Deployed ${dm.counter} contracts, spent ${dm.spent} to initialize world 🗺`);
console.log(`[${base.name}]\n${dm.diffDelta(delta)}`);

if (world.auxiliaryDeploymentManager) {
await world.auxiliaryDeploymentManager.spider();
}
runner = new Runner(base, world);
});

// NB: contexts are (still) a bit awkward
// they prob dont even really need to get passed through here currently
Expand Down
10 changes: 6 additions & 4 deletions plugins/scenario/World.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,17 @@ export class World {
snapshotAuxiliaryDeploymentManager?: DeploymentManager;

constructor(base: ForkSpec) {
// Q: should we really need to fork/snapshot the deployment manager?
const hre = hreForBase(base);
this.base = base;
}

async initialize(base: ForkSpec) {
const hre = await hreForBase(base);
this.deploymentManager = new DeploymentManager(base.network, base.deployment, hre);
// Q: should we really need to fork/snapshot the deployment manager?
this.snapshotDeploymentManager = this.deploymentManager;

if (this.base.auxiliaryBase) {
const auxiliaryBase = hre.config.scenario.bases.find(b => b.name === this.base.auxiliaryBase);
this.auxiliaryDeploymentManager = new DeploymentManager(auxiliaryBase.network, auxiliaryBase.deployment, hreForBase(auxiliaryBase));
this.auxiliaryDeploymentManager = new DeploymentManager(auxiliaryBase.network, auxiliaryBase.deployment, await hreForBase(auxiliaryBase));
this.snapshotAuxiliaryDeploymentManager = this.auxiliaryDeploymentManager;
}
}
Expand Down
16 changes: 11 additions & 5 deletions plugins/scenario/utils/hreForBase.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ethers } from 'ethers';
import { ethers } from 'ethers';
import type { HardhatEthersHelpers } from '@nomiclabs/hardhat-ethers/types';
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import { HardhatContext } from 'hardhat/internal/context';
Expand Down Expand Up @@ -36,7 +36,7 @@ declare module 'hardhat/internal/core/runtime-environment' {
}
}

export function nonForkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment {
export async function nonForkedHreForBase(base: ForkSpec): Promise<HardhatRuntimeEnvironment> {
const ctx: HardhatContext = HardhatContext.getHardhatContext();

const hardhatArguments = getEnvHardhatArguments(
Expand All @@ -61,7 +61,7 @@ export function nonForkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment {
);
}

export function forkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment {
export async function forkedHreForBase(base: ForkSpec): Promise<HardhatRuntimeEnvironment> {
const ctx: HardhatContext = HardhatContext.getHardhatContext();

const hardhatArguments = getEnvHardhatArguments(HARDHAT_PARAM_DEFINITIONS, process.env);
Expand All @@ -73,6 +73,12 @@ export function forkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment {

const baseNetwork = networks[base.network] as HttpNetworkUserConfig;

const provider = new ethers.providers.JsonRpcProvider(baseNetwork.url);

// noNetwork otherwise
if(!base.blockNumber)
base.blockNumber = await provider.getBlockNumber() - 210; // arbitrary number of blocks to go back, about 1 hour

if (!baseNetwork) {
throw new Error(`cannot find network config for network: ${base.network}`);
}
Expand All @@ -96,7 +102,7 @@ export function forkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment {
defaultNetwork: 'hardhat',
networks: {
hardhat: forkedNetwork,
localhost
localhost: localhost
},
},
};
Expand All @@ -111,7 +117,7 @@ export function forkedHreForBase(base: ForkSpec): HardhatRuntimeEnvironment {
);
}

export default function hreForBase(base: ForkSpec, fork = true): HardhatRuntimeEnvironment {
export default async function hreForBase(base: ForkSpec, fork = true): Promise<HardhatRuntimeEnvironment> {
if (fork) {
return forkedHreForBase(base);
} else {
Expand Down
14 changes: 7 additions & 7 deletions tasks/deployment_manager/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { impersonateAddress } from '../../plugins/scenario/utils';
import hreForBase from '../../plugins/scenario/utils/hreForBase';

// TODO: Don't depend on scenario's hreForBase
function getForkEnv(env: HardhatRuntimeEnvironment, deployment: string): HardhatRuntimeEnvironment {
async function getForkEnv(env: HardhatRuntimeEnvironment, deployment: string): Promise<HardhatRuntimeEnvironment> {
const base = env.config.scenario.bases.find(b => b.network == env.network.name && b.deployment == deployment);
if (!base) {
throw new Error(`No fork spec for ${env.network.name}`);
}
return hreForBase(base);
return await hreForBase(base);
}

function getDefaultDeployment(config: HardhatConfig, network: string): string {
Expand Down Expand Up @@ -65,7 +65,7 @@ task('deploy', 'Deploys market')
.addFlag('overwrite', 'overwrites cache')
.addParam('deployment', 'The deployment to deploy')
.setAction(async ({ simulate, noDeploy, noVerify, noVerifyImpl, overwrite, deployment }, env) => {
const maybeForkEnv = simulate ? getForkEnv(env, deployment) : env;
const maybeForkEnv = simulate ? await getForkEnv(env, deployment) : env;
const network = env.network.name;
const tag = `${network}/${deployment}`;
const dm = new DeploymentManager(
Expand Down Expand Up @@ -174,7 +174,7 @@ task('migrate', 'Runs migration')
.addFlag('overwrite', 'overwrites artifact if exists, fails otherwise')
.setAction(
async ({ migration: migrationName, prepare, enact, noEnacted, simulate, overwrite, deployment, impersonate }, env) => {
const maybeForkEnv = simulate ? getForkEnv(env, deployment) : env;
const maybeForkEnv = simulate ? await getForkEnv(env, deployment) : env;
const network = env.network.name;
const dm = new DeploymentManager(
network,
Expand All @@ -193,7 +193,7 @@ task('migrate', 'Runs migration')
const governanceBase = isBridgedDeployment ? env.config.scenario.bases.find(b => b.name === base.auxiliaryBase) : undefined;

if (governanceBase) {
const governanceEnv = hreForBase(governanceBase, simulate);
const governanceEnv = await hreForBase(governanceBase, simulate);
governanceDm = new DeploymentManager(
governanceBase.network,
governanceBase.deployment,
Expand Down Expand Up @@ -246,7 +246,7 @@ task('deploy_and_migrate', 'Runs deploy and migration')
.addParam('deployment', 'The deployment to deploy')
.setAction(
async ({ migration: migrationName, prepare, enact, noEnacted, simulate, overwrite, deployment, impersonate, noDeploy, noVerify, noVerifyImpl }, env) => {
const maybeForkEnv = simulate ? getForkEnv(env, deployment) : env;
const maybeForkEnv = simulate ? await getForkEnv(env, deployment) : env;
const network = env.network.name;
const tag = `${network}/${deployment}`;
const dm = new DeploymentManager(
Expand Down Expand Up @@ -314,7 +314,7 @@ task('deploy_and_migrate', 'Runs deploy and migration')
const governanceBase = isBridgedDeployment ? env.config.scenario.bases.find(b => b.name === base.auxiliaryBase) : undefined;

if (governanceBase) {
const governanceEnv = hreForBase(governanceBase, simulate);
const governanceEnv = await hreForBase(governanceBase, simulate);
governanceDm = new DeploymentManager(
governanceBase.network,
governanceBase.deployment,
Expand Down
2 changes: 1 addition & 1 deletion tasks/scenario/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ task('scenario:spider', 'Runs spider in preparation for scenarios')
const bases: ForkSpec[] = getBasesFromTaskArgs(taskArgs.bases, env);
await Promise.all(bases.map(async (base) => {
if (base.network !== 'hardhat') {
let hre = hreForBase(base);
let hre = await hreForBase(base);
let dm = new DeploymentManager(
base.name,
base.deployment,
Expand Down