|
|
|
@ -1,12 +1,11 @@ |
|
|
|
|
import { providers } from 'ethers'; |
|
|
|
|
|
|
|
|
|
import { ChainName, MultiProvider } from '@hyperlane-xyz/sdk'; |
|
|
|
|
import { Address, isValidAddressEvm } from '@hyperlane-xyz/utils'; |
|
|
|
|
import { Address, isValidAddressEvm, rootLogger } from '@hyperlane-xyz/utils'; |
|
|
|
|
|
|
|
|
|
import { logGray, logGreen } from '../logger.js'; |
|
|
|
|
import { warnYellow } from '../logger.js'; |
|
|
|
|
import { MultiProvider } from '../providers/MultiProvider.js'; |
|
|
|
|
import { ChainName } from '../types.js'; |
|
|
|
|
|
|
|
|
|
import { ENV } from './env.js'; |
|
|
|
|
const logger = rootLogger.child({ module: 'fork-utils' }); |
|
|
|
|
|
|
|
|
|
const ENDPOINT_PREFIX = 'http'; |
|
|
|
|
const DEFAULT_ANVIL_ENDPOINT = 'http://127.0.0.1:8545'; |
|
|
|
@ -19,12 +18,12 @@ export enum ANVIL_RPC_METHODS { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Resets the local node to it's original start (anvil [31337] at block zero). |
|
|
|
|
* Resets the local node to it's original state (anvil [31337] at block zero). |
|
|
|
|
*/ |
|
|
|
|
export const resetFork = async () => { |
|
|
|
|
logGray(`Resetting forked network...`); |
|
|
|
|
export const resetFork = async (anvilIPAddr?: string, anvilPort?: number) => { |
|
|
|
|
logger.info(`Resetting forked network...`); |
|
|
|
|
|
|
|
|
|
const provider = getLocalProvider(); |
|
|
|
|
const provider = getLocalProvider(anvilIPAddr, anvilPort); |
|
|
|
|
await provider.send(ANVIL_RPC_METHODS.RESET, [ |
|
|
|
|
{ |
|
|
|
|
forking: { |
|
|
|
@ -33,7 +32,7 @@ export const resetFork = async () => { |
|
|
|
|
}, |
|
|
|
|
]); |
|
|
|
|
|
|
|
|
|
logGreen(`✅ Successfully reset forked network`); |
|
|
|
|
logger.info(`✅ Successfully reset forked network`); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -44,10 +43,12 @@ export const resetFork = async () => { |
|
|
|
|
export const setFork = async ( |
|
|
|
|
multiProvider: MultiProvider, |
|
|
|
|
chain: ChainName | number, |
|
|
|
|
anvilIPAddr?: string, |
|
|
|
|
anvilPort?: number, |
|
|
|
|
) => { |
|
|
|
|
logGray(`Forking ${chain} for dry-run...`); |
|
|
|
|
logger.info(`Forking ${chain} for dry-run...`); |
|
|
|
|
|
|
|
|
|
const provider = getLocalProvider(); |
|
|
|
|
const provider = getLocalProvider(anvilIPAddr, anvilPort); |
|
|
|
|
const currentChainMetadata = multiProvider.metadata[chain]; |
|
|
|
|
|
|
|
|
|
await provider.send(ANVIL_RPC_METHODS.RESET, [ |
|
|
|
@ -60,7 +61,7 @@ export const setFork = async ( |
|
|
|
|
|
|
|
|
|
multiProvider.setProvider(chain, provider); |
|
|
|
|
|
|
|
|
|
logGreen(`✅ Successfully forked ${chain} for dry-run`); |
|
|
|
|
logger.info(`✅ Successfully forked ${chain} for dry-run`); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -70,13 +71,15 @@ export const setFork = async ( |
|
|
|
|
*/ |
|
|
|
|
export const impersonateAccount = async ( |
|
|
|
|
address: Address, |
|
|
|
|
anvilIPAddr?: string, |
|
|
|
|
anvilPort?: number, |
|
|
|
|
): Promise<providers.JsonRpcSigner> => { |
|
|
|
|
logGray(`Impersonating account (${address})...`); |
|
|
|
|
logger.info(`Impersonating account (${address})...`); |
|
|
|
|
|
|
|
|
|
const provider = getLocalProvider(); |
|
|
|
|
const provider = getLocalProvider(anvilIPAddr, anvilPort); |
|
|
|
|
await provider.send(ANVIL_RPC_METHODS.IMPERSONATE_ACCOUNT, [address]); |
|
|
|
|
|
|
|
|
|
logGreen(`✅ Successfully impersonated account (${address})`); |
|
|
|
|
logger.info(`✅ Successfully impersonated account (${address})`); |
|
|
|
|
|
|
|
|
|
return provider.getSigner(address); |
|
|
|
|
}; |
|
|
|
@ -85,20 +88,24 @@ export const impersonateAccount = async ( |
|
|
|
|
* Stops account impersonation. |
|
|
|
|
* @param address the address to stop impersonating |
|
|
|
|
*/ |
|
|
|
|
export const stopImpersonatingAccount = async (address: Address) => { |
|
|
|
|
logGray(`Stopping account impersonation for address (${address})...`); |
|
|
|
|
export const stopImpersonatingAccount = async ( |
|
|
|
|
address: Address, |
|
|
|
|
anvilIPAddr?: string, |
|
|
|
|
anvilPort?: number, |
|
|
|
|
) => { |
|
|
|
|
logger.info(`Stopping account impersonation for address (${address})...`); |
|
|
|
|
|
|
|
|
|
if (isValidAddressEvm(address)) |
|
|
|
|
throw new Error( |
|
|
|
|
`Cannot stop account impersonation: invalid address format: ${address}`, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const provider = getLocalProvider(); |
|
|
|
|
const provider = getLocalProvider(anvilIPAddr, anvilPort); |
|
|
|
|
await provider.send(ANVIL_RPC_METHODS.STOP_IMPERSONATING_ACCOUNT, [ |
|
|
|
|
address.substring(2), |
|
|
|
|
]); |
|
|
|
|
|
|
|
|
|
logGreen( |
|
|
|
|
logger.info( |
|
|
|
|
`✅ Successfully stopped account impersonation for address (${address})`, |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
@ -109,14 +116,16 @@ export const stopImpersonatingAccount = async (address: Address) => { |
|
|
|
|
* @returns a local JSON-RPC provider |
|
|
|
|
*/ |
|
|
|
|
export const getLocalProvider = ( |
|
|
|
|
anvilIPAddr?: string, |
|
|
|
|
anvilPort?: number, |
|
|
|
|
urlOverride?: string, |
|
|
|
|
): providers.JsonRpcProvider => { |
|
|
|
|
let envUrl; |
|
|
|
|
if (ENV.ANVIL_IP_ADDR && ENV.ANVIL_PORT) |
|
|
|
|
envUrl = `${ENDPOINT_PREFIX}${ENV.ANVIL_IP_ADDR}:${ENV.ANVIL_PORT}`; |
|
|
|
|
if (anvilIPAddr && anvilPort) |
|
|
|
|
envUrl = `${ENDPOINT_PREFIX}${anvilIPAddr}:${anvilPort}`; |
|
|
|
|
|
|
|
|
|
if (urlOverride && !urlOverride.startsWith(ENDPOINT_PREFIX)) { |
|
|
|
|
warnYellow( |
|
|
|
|
logger.warn( |
|
|
|
|
`⚠️ Provided URL override (${urlOverride}) does not begin with ${ENDPOINT_PREFIX}. Defaulting to ${ |
|
|
|
|
envUrl ?? DEFAULT_ANVIL_ENDPOINT |
|
|
|
|
}`,
|