From 045cc06a865daf0b8788cfab698bfc22a52921e1 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Fri, 23 May 2025 12:04:48 +0900 Subject: [PATCH] examples: add receive executor config for LZ v1 --- examples/lzapp-migration/layerzero.config.ts | 1 + examples/lzapp-migration/lzapp.config.ts | 1 + .../tasks/common/taskHelper.ts | 79 ++++++++++++++++++- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/examples/lzapp-migration/layerzero.config.ts b/examples/lzapp-migration/layerzero.config.ts index d2aee5e90..50033efbb 100644 --- a/examples/lzapp-migration/layerzero.config.ts +++ b/examples/lzapp-migration/layerzero.config.ts @@ -95,6 +95,7 @@ const config: OAppOmniGraphHardhat = { // Optional Receive Configuration // @dev Controls how the `from` chain receives messages from the `to` chain. receiveConfig: { + executorConfig: '0x718B92b5CB0a5552039B593faF724D182A881eDA', ulnConfig: { // The number of block confirmations to expect from the `to` chain. confirmations: BigInt(15), diff --git a/examples/lzapp-migration/lzapp.config.ts b/examples/lzapp-migration/lzapp.config.ts index 282695042..b5ef241a9 100644 --- a/examples/lzapp-migration/lzapp.config.ts +++ b/examples/lzapp-migration/lzapp.config.ts @@ -45,6 +45,7 @@ const config: OAppOmniGraphHardhat = { }, }, receiveConfig: { + executorConfig: '0x718B92b5CB0a5552039B593faF724D182A881eDA', ulnConfig: { confirmations: BigInt(1), requiredDVNs: ['0x53f488e93b4f1b60e8e83aa374dbe1780a1ee8a8'], // LayerZero Labs DVN for Arbitrum Sepolia diff --git a/examples/lzapp-migration/tasks/common/taskHelper.ts b/examples/lzapp-migration/tasks/common/taskHelper.ts index f92d96383..157b0263f 100644 --- a/examples/lzapp-migration/tasks/common/taskHelper.ts +++ b/examples/lzapp-migration/tasks/common/taskHelper.ts @@ -5,7 +5,7 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types' import { OmniAddress, OmniPoint, OmniTransaction, flattenTransactions } from '@layerzerolabs/devtools' import { createGetHreByEid } from '@layerzerolabs/devtools-evm-hardhat' import { createModuleLogger } from '@layerzerolabs/io-devtools' -import { EndpointId } from '@layerzerolabs/lz-definitions' +import { EndpointId, endpointIdToVersion } from '@layerzerolabs/lz-definitions' import { addressToBytes32 } from '@layerzerolabs/lz-v2-utilities' import { Uln302ExecutorConfig, Uln302UlnConfig } from '@layerzerolabs/protocol-devtools' import { LzAppOmniGraph, OAppEdgeConfig } from '@layerzerolabs/ua-devtools' @@ -153,6 +153,34 @@ export async function getEpv1ReceiveUlnConfig( } } +/** + * Get the Receive Executor address for EPV1 (EVM-based) OApp + * @param hre {HardhatRuntimeEnvironment} Hardhat runtime environment + * @param eid {EndpointId} Remote Endpoint ID + * @param address {OmniAddress} Address of the OApp + * @returns Executor address or undefined + */ +export async function getEpv1ReceiveExecutorConfig( + hre: HardhatRuntimeEnvironment, + eid: EndpointId, + address: OmniAddress +): Promise { + try { + const receiveUlnDeployment = await hre.deployments.get('ReceiveUln301') + const signer: Signer = hre.ethers.provider.getSigner() + + const receiveUlnContract = new Contract(receiveUlnDeployment.address, receiveUlnDeployment.abi, signer) + const configBytes: string = await receiveUlnContract.getConfig(eid, address, CONFIG_TYPE_EXECUTOR) + + const [executorAddress] = ethers.utils.defaultAbiCoder.decode(['address'], configBytes) + return executorAddress + } catch (error) { + const moduleLogger = createModuleLogger('LzApp') + moduleLogger.error(`Error fetching EPV1 receive executor config: ${(error as Error).message}`) + return undefined + } +} + /** * Get the send library address for EPV1 (EVM-based) OApp * @param hre {HardhatRuntimeEnvironment} Hardhat runtime environment @@ -677,6 +705,33 @@ export async function setExecutorConfig( } } +/** + * Sets the Receive Executor Config on the LzApp contract and returns the transaction. + */ +export async function setReceiveExecutorConfig( + hre: HardhatRuntimeEnvironment, + lzApp: OmniPoint, + lzAppConfig: OAppEdgeConfig, + eid: EndpointId +): Promise { + const lzAppDeployment = await hre.deployments.get(lzApp.contractName || lzApp.address) + const lzAppContract = new Contract(lzAppDeployment.address, lzAppDeployment.abi, hre.ethers.provider.getSigner()) + const receiveUlnIndex = await getLibraryIndex(hre, lzAppConfig.receiveLibraryConfig?.receiveLibrary!) + const encodedAddress = ethers.utils.defaultAbiCoder.encode(['address'], [lzAppConfig.receiveConfig?.executorConfig]) + + const data = lzAppContract.interface.encodeFunctionData('setConfig', [ + receiveUlnIndex, + eid, + CONFIG_TYPE_EXECUTOR, + encodedAddress, + ]) + return { + point: lzApp, + data, + description: `Set Receive Executor Config for Endpoint ID ${eid}`, + } +} + /** * Sets the ULN Config on the LzApp contract and returns the transaction. */ @@ -848,7 +903,8 @@ export const configureLzAppGraph = async ( !typedConfig.receiveLibraryConfig?.receiveLibrary || !typedConfig.sendConfig?.executorConfig || !typedConfig.sendConfig?.ulnConfig || - !typedConfig.receiveConfig?.ulnConfig + !typedConfig.receiveConfig?.ulnConfig || + (endpointIdToVersion(to.eid) === 'v1' && !typedConfig.receiveConfig?.executorConfig) ) { logger.error(`Missing configuration properties for connection from ${from.eid} to ${to.eid}`) return [] @@ -928,6 +984,25 @@ export const configureLzAppGraph = async ( if (executorTx) transactions.push(executorTx) } + if (endpointIdToVersion(to.eid) === 'v1') { + const currentReceiveExecutor = await getEpv1ReceiveExecutorConfig( + hreForEid, + to.eid, + LzApp.address + ) + if (!currentReceiveExecutor) { + throw new Error(`Failed to retrieve receive executor config for ${LzApp.address}`) + } + + if ( + currentReceiveExecutor.toLowerCase() !== + typedConfig.receiveConfig!.executorConfig!.toLowerCase() + ) { + const recvExecTx = await setReceiveExecutorConfig(hreForEid, from, typedConfig, to.eid) + if (recvExecTx) transactions.push(recvExecTx) + } + } + const getSendUlnConfig = await getEpv1SendUlnConfig(hreForEid, to.eid, LzApp.address) const getReceiveUlnConfig = await getEpv1ReceiveUlnConfig(hreForEid, to.eid, LzApp.address)