diff --git a/packages/ua-utils-evm-hardhat-test/hardhat.config.ts b/packages/ua-utils-evm-hardhat-test/hardhat.config.ts index b4dd9ad33..0e7fafb3a 100644 --- a/packages/ua-utils-evm-hardhat-test/hardhat.config.ts +++ b/packages/ua-utils-evm-hardhat-test/hardhat.config.ts @@ -3,6 +3,7 @@ import 'hardhat-deploy-ethers' import { withLayerZeroArtifacts } from '@layerzerolabs/utils-evm-hardhat' import { EndpointId } from '@layerzerolabs/lz-definitions' import { HardhatUserConfig } from 'hardhat/types' +import '@layerzerolabs/ua-utils-evm-hardhat/tasks' const MNEMONIC = 'test test test test test test test test test test test test' diff --git a/packages/ua-utils-evm-hardhat-test/test/config.test.ts b/packages/ua-utils-evm-hardhat-test/test/config.test.ts index 9d9ca6527..48b8109ac 100644 --- a/packages/ua-utils-evm-hardhat-test/test/config.test.ts +++ b/packages/ua-utils-evm-hardhat-test/test/config.test.ts @@ -2,25 +2,172 @@ import { expect } from 'chai' import { describe } from 'mocha' import { getNetworkRuntimeEnvironment } from '@layerzerolabs/utils-evm-hardhat' import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { BigNumber, Contract, ethers, Wallet } from 'ethers' const NETWORK_NAMES = ['vengaboys', 'britney'] +type SetDefaultExecutorConfigParam = { + eid: number + config: ExecutorConfig +} + +type ExecutorConfig = { + maxMessageSize: number + executor: string +} + +type SetDefaultUlnConfigParam = { + eid: number + config: UlnConfig +} + +type UlnConfig = { + confirmations: number + requiredVerifiersCount: number + optionalVerifiersCount: number + optionalVerifiersThreshold: number + requiredVerifiers: string[] + optionalVerifiers: string[] +} describe('config', () => { - NETWORK_NAMES.forEach((networkName) => { - describe(`Network '${networkName}`, () => { - let environment: HardhatRuntimeEnvironment + describe(`Setting default configs for two endpoints`, () => { + let environment_A: HardhatRuntimeEnvironment + let sendUln302_A: Contract + let receiveUln302_A: Contract + let endpoint_A: Contract + let endpointId_A: number + let executerWallet_A: Wallet + let executerAddress_A: string + let verifierWallet_A: Wallet + let verifierAddress_A: string + + let environment_B: HardhatRuntimeEnvironment + let sendUln302_B: Contract + let receiveUln302_B: Contract + let endpoint_B: Contract + let endpointId_B: number + let executerWallet_B: Wallet + let executerAddress_B: string + let verifierWallet_B: Wallet + let verifierAddress_B: string + + before(async () => { + environment_A = await getNetworkRuntimeEnvironment('vengaboys') + endpoint_A = await environment_A.ethers.getContract('EndpointV2') + endpointId_A = await endpoint_A.eid() + + environment_B = await getNetworkRuntimeEnvironment('britney') + endpoint_B = await environment_B.ethers.getContract('EndpointV2') + endpointId_B = await endpoint_B.eid() + + expect(await endpoint_A.defaultSendLibrary(endpointId_B)).to.be.eql( + environment_A.ethers.constants.AddressZero + ) + expect(await endpoint_A.defaultSendLibrary(endpointId_B)).to.be.eql( + environment_A.ethers.constants.AddressZero + ) + expect(await endpoint_B.defaultSendLibrary(endpointId_A)).to.be.eql( + environment_B.ethers.constants.AddressZero + ) + expect(await endpoint_B.defaultSendLibrary(endpointId_A)).to.be.eql( + environment_B.ethers.constants.AddressZero + ) + }) + + it('should set two endpoints up', async () => { + sendUln302_A = await environment_A.ethers.getContract('SendUln302') + receiveUln302_A = await environment_A.ethers.getContract('ReceiveUln302') + + executerWallet_A = await environment_A.ethers.Wallet.createRandom() + executerAddress_A = executerWallet_A.address + + verifierWallet_A = await environment_A.ethers.Wallet.createRandom() + verifierAddress_A = verifierWallet_A.address - before(async () => { - environment = await getNetworkRuntimeEnvironment(networkName) - }) + executerWallet_B = await environment_B.ethers.Wallet.createRandom() + executerAddress_B = executerWallet_B.address - it('should have an endpoint deployed', async () => { - const endpoint = await environment.ethers.getContract('EndpointV2') - const eid = await endpoint.eid() + verifierWallet_B = await environment_B.ethers.Wallet.createRandom() + verifierAddress_B = verifierWallet_B.address - expect(environment.network.config.eid).to.be.a('number') - expect(eid).to.eql(environment.network.config.eid) - }) + let executorConfig = createExecutorConfig(1024, executerAddress_B) + let setDefaultExecutorConfigParam = createSetDefaultExecutorConfigParam(endpointId_B, executorConfig) + await sendUln302_A.setDefaultExecutorConfigs([setDefaultExecutorConfigParam]) + + let ulnConfig = createUlnConfig(1, 1, 0, 0, [verifierAddress_B], []) + let setDefaultUlnConfigParam = createSetDefaultUlnConfigParam(endpointId_B, ulnConfig) + await sendUln302_A.setDefaultUlnConfigs([setDefaultUlnConfigParam]) + + await endpoint_A.registerLibrary(sendUln302_A.address) + await endpoint_A.setDefaultSendLibrary(endpointId_B, sendUln302_A.address) + + ulnConfig = createUlnConfig(1, 1, 0, 0, [verifierAddress_A], []) + setDefaultUlnConfigParam = createSetDefaultUlnConfigParam(endpointId_B, ulnConfig) + await receiveUln302_A.setDefaultUlnConfigs([setDefaultUlnConfigParam]) + + await endpoint_A.registerLibrary(receiveUln302_A.address) + await endpoint_A.setDefaultReceiveLibrary(endpointId_B, receiveUln302_A.address, 0) + + // sendUln302_B = await environment_B.ethers.getContract("SendUln302") + // receiveUln302_B = await environment_B.ethers.getContract("ReceiveUln302") + // + // executorConfig = createExecutorConfig(1000, executerAddress_A); + // setDefaultExecutorConfigParam = createSetDefaultExecutorConfigParam(endpointId_A, executorConfig) + // await sendUln302_B.setDefaultExecutorConfigs([setDefaultExecutorConfigParam]); + // + // ulnConfig = createUlnConfig(2,1,0,0, [verifierAddress_A], []); + // setDefaultUlnConfigParam = createSetDefaultUlnConfigParam(endpointId_A, ulnConfig) + // await sendUln302_B.setDefaultUlnConfigs([setDefaultUlnConfigParam]); + // + // await endpoint_B.registerLibrary(sendUln302_B.address); + // await endpoint_B.setDefaultSendLibrary(endpointId_A, sendUln302_B.address); + + expect(await endpoint_A.defaultSendLibrary(endpointId_B)).to.be.eql(sendUln302_A.address) + expect(await endpoint_A.defaultReceiveLibrary(endpointId_B)).to.be.eql(receiveUln302_A.address) + // expect(await endpoint_B.defaultSendLibrary(endpointId_A)).to.be.eql(sendUln302_B.address) + // expect(await endpoint_B.defaultReceiveLibrary(endpointId_A)).to.be.eql(sendUln302_B.address) + + let getDefaultConfigTask = await environment_A.run('getDefaultConfig', { networks: 'vengaboys,britney' }) + console.log({ getDefaultConfigTask }) }) }) }) + +function createExecutorConfig(maxMessageSize: number, executor: string): ExecutorConfig { + return { + maxMessageSize, + executor, + } +} + +function createSetDefaultExecutorConfigParam(eid: number, config: ExecutorConfig): SetDefaultExecutorConfigParam { + return { + eid, + config, + } +} + +function createUlnConfig( + confirmations: number, + requiredVerifiersCount: number, + optionalVerifiersCount: number, + optionalVerifiersThreshold: number, + requiredVerifiers: string[], + optionalVerifiers: string[] +): UlnConfig { + return { + confirmations, + requiredVerifiersCount, + optionalVerifiersCount, + optionalVerifiersThreshold, + requiredVerifiers, + optionalVerifiers, + } +} + +function createSetDefaultUlnConfigParam(eid: number, config: UlnConfig): SetDefaultUlnConfigParam { + return { + eid, + config, + } +} diff --git a/packages/ua-utils-evm-hardhat/src/tasks/getDefaultConfig.ts b/packages/ua-utils-evm-hardhat/src/tasks/getDefaultConfig.ts index 55dfbb0f0..34731c01d 100644 --- a/packages/ua-utils-evm-hardhat/src/tasks/getDefaultConfig.ts +++ b/packages/ua-utils-evm-hardhat/src/tasks/getDefaultConfig.ts @@ -1,34 +1,139 @@ +import { ActionType } from 'hardhat/types' +import { task } from 'hardhat/config' +import 'hardhat-deploy-ethers/internal/type-extensions' import { ethers } from 'ethers' -import { getProvider, getLayerZeroChainId, getEndpointAddress } from '@/utils/crossChainHelper' -import { ENDPOINT_ABI, MESSAGING_LIBRARY_ABI } from '@/constants/abi' +import { getNetworkRuntimeEnvironment } from '@layerzerolabs/utils-evm-hardhat' -export default async (taskArgs: any, hre: any) => { +const CONFIG_TYPE_EXECUTOR = 1 +const CONFIG_TYPE_ULN = 2 +interface TaskArgs { + networks: string +} +export const getDefaultConfig: ActionType = async (taskArgs, hre) => { + // TODO add logging + // const logger = createLogger() + console.log(taskArgs) const networks = taskArgs.networks.split(',') - const configByNetwork = await Promise.all( networks.map(async (network: string) => { - const provider = getProvider(hre, network) - console.log() - const endpoint = new ethers.Contract(getEndpointAddress(network), ENDPOINT_ABI, provider) - const sendVersion = await endpoint.defaultSendVersion() - const receiveVersion = await endpoint.defaultReceiveVersion() - const sendLibraryAddress = await endpoint.defaultSendLibrary() - const messagingLibrary = new ethers.Contract(sendLibraryAddress, MESSAGING_LIBRARY_ABI, provider) - const config = await messagingLibrary.defaultAppConfig(getLayerZeroChainId(network)) - - return { - network, - sendVersion, - receiveVersion, - inboundProofLibraryVersion: config.inboundProofLibraryVersion, - inboundBlockConfirmations: config.inboundBlockConfirmations.toNumber(), - relayer: config.relayer, - outboundProofType: config.outboundProofType, - outboundBlockConfirmations: config.outboundBlockConfirmations.toNumber(), - oracle: config.oracle, - } + console.log({ network }) + const environment = await getNetworkRuntimeEnvironment(network) + const endpointV2 = await environment.ethers.getContract('EndpointV2') + const eid = await endpointV2.eid() + + await Promise.all( + networks.map(async (remoteNetwork) => { + // skip wiring itself + if (network === remoteNetwork) return + + const remoteEnvironment = await getNetworkRuntimeEnvironment(remoteNetwork) + const remoteEndpointV2 = await remoteEnvironment.ethers.getContract('EndpointV2') + const remoteEid = await remoteEndpointV2.eid() + + const defaultSendLibrary = await endpointV2.defaultSendLibrary(remoteEid) + const defaultReceiveLibrary = await endpointV2.defaultReceiveLibrary(remoteEid) + + const sendUln302Factory = await environment.ethers.getContractFactory('SendUln302') + const sendUln302 = sendUln302Factory.attach(defaultSendLibrary) + + const receiveUln302Factory = await environment.ethers.getContractFactory('ReceiveUln302') + const receiveUln302 = receiveUln302Factory.attach(defaultReceiveLibrary) + + let sendExecutorConfigBytes = await sendUln302.getConfig( + remoteEid, + remoteEnvironment.ethers.constants.AddressZero, + 1 + ) + let [maxMessageSize, executor] = ethers.utils.defaultAbiCoder.decode( + ['uint32', 'address'], + sendExecutorConfigBytes + ) + + let sendUlnConfigBytes = await sendUln302.getConfig( + remoteEid, + remoteEnvironment.ethers.constants.AddressZero, + 2 + ) + let [ + confirmations, + requiredVerifiersCount, + optionalVerifiersCount, + optionalVerifiersThreshold, + requiredVerifiers, + optionalVerifiers, + ] = ethers.utils.defaultAbiCoder.decode( + ['uint64', 'uint8', 'uint8', 'uint8', 'address[]', 'address[]'], + sendUlnConfigBytes + ) + + let sendUln = { + maxMessageSize: maxMessageSize, + executor: executor, + confirmations: confirmations, + requiredVerifiersCount: requiredVerifiersCount, + optionalVerifiersCount: optionalVerifiersCount, + optionalVerifiersThreshold: optionalVerifiersThreshold, + requiredVerifiers: requiredVerifiers, + optionalVerifiers: optionalVerifiers, + } + + let receiveUlnConfigBytes = await receiveUln302.getConfig( + remoteEid, + remoteEnvironment.ethers.constants.AddressZero, + 2 + ) + ;[ + confirmations, + requiredVerifiersCount, + optionalVerifiersCount, + optionalVerifiersThreshold, + requiredVerifiers, + optionalVerifiers, + ] = ethers.utils.defaultAbiCoder.decode( + ['uint64', 'uint8', 'uint8', 'uint8', 'address[]', 'address[]'], + receiveUlnConfigBytes + ) + + let receiveUln = { + confirmations: confirmations, + requiredVerifiersCount: requiredVerifiersCount, + optionalVerifiersCount: optionalVerifiersCount, + optionalVerifiersThreshold: optionalVerifiersThreshold, + requiredVerifiers: requiredVerifiers, + optionalVerifiers: optionalVerifiers, + } + + // const consoleTableDefaultConfig = { + // network, + // defaultSendLibrary, + // defaultReceiveLibrary, + // maxMessageSize: maxMessageSize[0], + // outboundConfirmations: outboundConfirmations[0].toNumber(), + // executor: executor.toString(), + // inboundBlockConfirmations: inboundConfirmations[0].toNumber(), + // verifiers: verifiers[0].toString(), + // optionalVerifiers, + // optionalVerifierThreshold, + // } + return { + network, + remoteNetwork, + defaultSendLibrary, + defaultReceiveLibrary, + sendUln: sendUln, + receiveUln: receiveUln, + } + }) + ) }) ) - - console.table(configByNetwork) + console.log(configByNetwork) + return configByNetwork } + +task( + 'getDefaultConfig', + 'outputs the default Send and Receive Messaging Library versions and the default application config' +) + .addParam('networks', 'comma separated list of networks') + .setAction(getDefaultConfig) diff --git a/packages/ua-utils-evm-hardhat/src/tasks/index.ts b/packages/ua-utils-evm-hardhat/src/tasks/index.ts index 83bc4ce8f..edfb64bc4 100644 --- a/packages/ua-utils-evm-hardhat/src/tasks/index.ts +++ b/packages/ua-utils-evm-hardhat/src/tasks/index.ts @@ -1,73 +1 @@ -import { task, types } from 'hardhat/config' -import wireAll from './wireAll' -import setConfig from './setConfig' -import getDefaultConfig from './getDefaultConfig' -import getConfig from './getConfig' -import checkWireAllConfig from './checkWireAllConfig' - -task( - 'setConfig', - 'sets Send and Receive Messaging Library versions and a custom application config for contracts implementing ILayerZeroUserApplicationConfig interface', - setConfig -) - .addParam('configPath', 'the application config file path') - .addOptionalParam( - 'name', - 'name of the deployed contracts. Should be specified if the same contract deployed on different chains and the deployment information is located in the deployments folder' - ) - .addOptionalParam( - 'address', - 'address of the deployed contracts. Should be specified if the contract address is the same on all chains' - ) - .addOptionalParam( - 'gnosisConfigPath', - 'the path to a file with Gnosis config. If specified, the transactions will be sent to Gnosis' - ) - .addOptionalParam('gasLimit', 'override execution gasLimit') - -task( - 'getDefaultConfig', - 'outputs the default Send and Receive Messaging Library versions and the default application config', - getDefaultConfig -).addParam('networks', 'comma separated list of networks') - -task( - 'getConfig', - "outputs the application's Send and Receive Messaging Library versions and the config for remote networks", - getConfig -) - .addParam('remoteNetworks', 'comma separated list of remote networks') - .addOptionalParam( - 'name', - 'name of the deployed contract. Should be specified only if the deployment information is located in the deployments folder' - ) - .addOptionalParam('address', 'the contract address') - -task('checkWireAllConfig', '', checkWireAllConfig) - .addParam('e', 'the environment ie: mainnet, testnet or sandbox') - .addFlag('u', 'show use custom adapter params') - .addFlag('t', 'show trusted remote lookup') - .addFlag('m', 'show min destination gas lookup') - .addParam('chains', 'comma separated list of networks') - .addOptionalParam('contract', 'name of contract') - .addOptionalParam('addresses', 'addresses of contracts in same order as chains') - .addOptionalParam('proxyContract', 'name of proxy contract') - .addOptionalParam('proxyChain', 'name of proxy chain') - -task('wireAll', '', wireAll) - .addParam('e', 'the environment ie: mainnet, testnet or sandbox') - .addOptionalParam('noPrompt', 'no prompt', false, types.boolean) - .addOptionalParam( - 'configPath', - 'Optional config path. Default: ./constants/wireUpConfig.json', - './constants/wireUpConfig.json', - types.string - ) - .addOptionalParam('n', 'send to gnosis', false, types.boolean) - .addOptionalParam('gasLimit', 'override execution gasLimit') - .addOptionalParam( - 'gnosisConfigPath', - 'Optional config path. Default: ./constants/gnosisConfig.json', - './constants/gnosisConfig.json', - types.string - ) +import './getDefaultConfig'