From f444b7c4e2c7d27fe3a9753d28359a11f169eef3 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Mon, 2 Dec 2024 18:06:02 -0800 Subject: [PATCH 01/47] feat: added UniswapV3Composer example --- examples/oft-composer-library/.env.example | 15 + examples/oft-composer-library/.eslintignore | 10 + examples/oft-composer-library/.eslintrc.js | 10 + examples/oft-composer-library/.gitignore | 24 + examples/oft-composer-library/.nvmrc | 1 + examples/oft-composer-library/.prettierignore | 10 + examples/oft-composer-library/.prettierrc.js | 3 + examples/oft-composer-library/CHANGELOG.md | 270 +++++++++ examples/oft-composer-library/README.md | 528 ++++++++++++++++++ .../oft-composer-library/contracts/MyOFT.sol | 14 + .../contracts/UniswapV3Composer.sol | 141 +++++ .../contracts/mocks/MyOFTMock.sol | 18 + examples/oft-composer-library/deploy/MyOFT.ts | 53 ++ examples/oft-composer-library/foundry.toml | 33 ++ .../oft-composer-library/hardhat.config.ts | 83 +++ .../oft-composer-library/layerzero.config.ts | 60 ++ examples/oft-composer-library/package.json | 80 +++ .../oft-composer-library/solhint.config.js | 1 + .../tasks/createUniswapPool.ts | 135 +++++ examples/oft-composer-library/tasks/send.ts | 112 ++++ .../test/foundry/MyOFT.t.sol | 160 ++++++ .../test/hardhat/MyOFT.test.ts | 101 ++++ .../test/mocks/ERC20Mock.sol | 12 + .../test/mocks/OFTComposerMock.sol | 27 + .../test/mocks/OFTMock.sol | 59 ++ examples/oft-composer-library/tsconfig.json | 13 + .../oft-alt-evm/artifacts/IOFT.sol/IOFT.json | 10 +- 27 files changed, 1978 insertions(+), 5 deletions(-) create mode 100644 examples/oft-composer-library/.env.example create mode 100644 examples/oft-composer-library/.eslintignore create mode 100644 examples/oft-composer-library/.eslintrc.js create mode 100644 examples/oft-composer-library/.gitignore create mode 100644 examples/oft-composer-library/.nvmrc create mode 100644 examples/oft-composer-library/.prettierignore create mode 100644 examples/oft-composer-library/.prettierrc.js create mode 100644 examples/oft-composer-library/CHANGELOG.md create mode 100644 examples/oft-composer-library/README.md create mode 100644 examples/oft-composer-library/contracts/MyOFT.sol create mode 100644 examples/oft-composer-library/contracts/UniswapV3Composer.sol create mode 100644 examples/oft-composer-library/contracts/mocks/MyOFTMock.sol create mode 100644 examples/oft-composer-library/deploy/MyOFT.ts create mode 100644 examples/oft-composer-library/foundry.toml create mode 100644 examples/oft-composer-library/hardhat.config.ts create mode 100644 examples/oft-composer-library/layerzero.config.ts create mode 100644 examples/oft-composer-library/package.json create mode 100644 examples/oft-composer-library/solhint.config.js create mode 100644 examples/oft-composer-library/tasks/createUniswapPool.ts create mode 100644 examples/oft-composer-library/tasks/send.ts create mode 100644 examples/oft-composer-library/test/foundry/MyOFT.t.sol create mode 100644 examples/oft-composer-library/test/hardhat/MyOFT.test.ts create mode 100644 examples/oft-composer-library/test/mocks/ERC20Mock.sol create mode 100644 examples/oft-composer-library/test/mocks/OFTComposerMock.sol create mode 100644 examples/oft-composer-library/test/mocks/OFTMock.sol create mode 100644 examples/oft-composer-library/tsconfig.json diff --git a/examples/oft-composer-library/.env.example b/examples/oft-composer-library/.env.example new file mode 100644 index 000000000..197ba1d67 --- /dev/null +++ b/examples/oft-composer-library/.env.example @@ -0,0 +1,15 @@ +# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.- +# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ +# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' +# +# Example environment configuration +# +# .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.-. .-.- +# / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ \ / / \ +# `-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' `-`-' + +# By default, the examples support both mnemonic-based and private key-based authentication +# +# You don't need to set both of these values, just pick the one that you prefer and set that one +MNEMONIC= +PRIVATE_KEY= \ No newline at end of file diff --git a/examples/oft-composer-library/.eslintignore b/examples/oft-composer-library/.eslintignore new file mode 100644 index 000000000..ee9f768fd --- /dev/null +++ b/examples/oft-composer-library/.eslintignore @@ -0,0 +1,10 @@ +artifacts +cache +dist +node_modules +out +*.log +*.sol +*.yaml +*.lock +package-lock.json \ No newline at end of file diff --git a/examples/oft-composer-library/.eslintrc.js b/examples/oft-composer-library/.eslintrc.js new file mode 100644 index 000000000..f0ea891fd --- /dev/null +++ b/examples/oft-composer-library/.eslintrc.js @@ -0,0 +1,10 @@ +require('@rushstack/eslint-patch/modern-module-resolution'); + +module.exports = { + extends: ['@layerzerolabs/eslint-config-next/recommended'], + rules: { + // @layerzerolabs/eslint-config-next defines rules for turborepo-based projects + // that are not relevant for this particular project + 'turbo/no-undeclared-env-vars': 'off', + }, +}; diff --git a/examples/oft-composer-library/.gitignore b/examples/oft-composer-library/.gitignore new file mode 100644 index 000000000..e2face954 --- /dev/null +++ b/examples/oft-composer-library/.gitignore @@ -0,0 +1,24 @@ +node_modules +.env +coverage +coverage.json +typechain +typechain-types + +# Hardhat files +cache +artifacts + + +# LayerZero specific files +.layerzero + +# foundry test compilation files +out + +# pnpm +pnpm-error.log + +# Editor and OS files +.DS_Store +.idea diff --git a/examples/oft-composer-library/.nvmrc b/examples/oft-composer-library/.nvmrc new file mode 100644 index 000000000..b714151ef --- /dev/null +++ b/examples/oft-composer-library/.nvmrc @@ -0,0 +1 @@ +v18.18.0 \ No newline at end of file diff --git a/examples/oft-composer-library/.prettierignore b/examples/oft-composer-library/.prettierignore new file mode 100644 index 000000000..6e8232f5a --- /dev/null +++ b/examples/oft-composer-library/.prettierignore @@ -0,0 +1,10 @@ +artifacts/ +cache/ +dist/ +node_modules/ +out/ +*.log +*ignore +*.yaml +*.lock +package-lock.json \ No newline at end of file diff --git a/examples/oft-composer-library/.prettierrc.js b/examples/oft-composer-library/.prettierrc.js new file mode 100644 index 000000000..6f55b4019 --- /dev/null +++ b/examples/oft-composer-library/.prettierrc.js @@ -0,0 +1,3 @@ +module.exports = { + ...require('@layerzerolabs/prettier-config-next'), +}; diff --git a/examples/oft-composer-library/CHANGELOG.md b/examples/oft-composer-library/CHANGELOG.md new file mode 100644 index 000000000..4d5e63961 --- /dev/null +++ b/examples/oft-composer-library/CHANGELOG.md @@ -0,0 +1,270 @@ +# @layerzerolabs/oft-example + +## 0.5.1 + +### Patch Changes + +- 447af65: Use concurrently for parallel compilation task + +## 0.5.0 + +### Minor Changes + +- e2395b5: Add OApp Read Example + +## 0.4.0 + +### Minor Changes + +- aa37daf: Update layerzerolabs packages to 3.0.12 + +## 0.3.1 + +### Patch Changes + +- 9ab480a: foundry.toml QOL improvements + +## 0.3.0 + +### Minor Changes + +- b4a12d3: Update hardhat runtime environment factory to match the new environment constuctor + +## 0.2.15 + +### Patch Changes + +- 893ad66: Update @LayerZero-Labs dependencies to 2.3.39 + +## 0.2.14 + +### Patch Changes + +- d126c52: Update monorepo dependencies and typescript version + +## 0.2.13 + +### Patch Changes + +- 40aebd3: Fix avalanche-testnet url + +## 0.2.12 + +### Patch Changes + +- 218ab72: OpenZeppelin Contracts/Contracts-Upgradeable Upgraded to 5.0.2 + +## 0.2.11 + +### Patch Changes + +- 658ba47: Update to use @layerzerolabs/oapp-evm + +## 0.2.10 + +### Patch Changes + +- 7c4b031: Fix network name suffix in examples + +## 0.2.9 + +### Patch Changes + +- d2ff651: Use @layerzerolabs/oft-evm OFT version + +## 0.2.8 + +### Patch Changes + +- 141d067: Update cache paths + +## 0.2.7 + +### Patch Changes + +- 3ec2912: Fixing changeset race condition in the PR's updating them all +- 58cbd3e: Update to latest lz dependencies + +## 0.2.6 + +### Patch Changes + +- 938ac3d: Improve error reporting on UIntBigIntSchema + +## 0.2.5 + +### Patch Changes + +- f865318: Update @LayerZero-Labs dependencies to 2.3.3 + +## 0.2.4 + +### Patch Changes + +- 835cdbe: Replace Mumbai with Amoy + +## 0.2.3 + +### Patch Changes + +- e16c864: Update @LayerZero-Labs dependencies to 2.1.27 +- e16c864: Update executor config schema & types after update to 2.1.27 + +## 0.2.2 + +### Patch Changes + +- c09680a: Update @LayerZero-Labs dependencies to 2.1.25 +- c09680a: Add eslint-plugin-jest-extended to examples + +## 0.2.1 + +### Patch Changes + +- a6f2fef: Re-export useful types from toolbox-hardhat + +## 0.2.0 + +### Minor Changes + +- a4093ab: Adapt LayerZero package updates, including OApp version 2 + +## 0.1.10 + +### Patch Changes + +- ff6427c: Update @LayerZero-Labs dependencies to 2.1.18 + +## 0.1.9 + +### Patch Changes + +- a5c185f: Take RPC URLs from the environment in the examples + +## 0.1.8 + +### Patch Changes + +- 54cf16e: Silence bigint-buffer warning + +## 0.1.7 + +### Patch Changes + +- e7ef1aa: Update @layerzero-labs dependencies to 2.1.15 + +## 0.1.6 + +### Patch Changes + +- b93a018: Update @layerzero-labs dependencies to 2.1.13 + +## 0.1.5 + +### Patch Changes + +- 855fa36: Update to latest layerzerolabsmonorepo dependencies + +## 0.1.4 + +### Patch Changes + +- c6e3b45: Lock versions of ethers & @openzeppelin/contracts in packages; Put pnpm first in create-lz-oapp + +## 0.1.3 + +### Patch Changes + +- 491b5a5: Upgrade contract Dependencies to 2.1.7 + +## 0.1.2 + +### Patch Changes + +- c8f1739: Fix OFT example tests + +## 0.1.1 + +### Patch Changes + +- 71e355c: Update "@layerzerolabs/\*" dependencies + +## 0.1.0 + +### Minor Changes + +- 6e464f2: Specify EndpointV2 with the "V2" suffix wherever appropriate + +## 0.0.12 + +### Patch Changes + +- 8227742: Update @layerzero-labs dependencies to 2.1.4 +- 9996f00: Updated Readmes and the example rpcs used in createLZOApp + +## 0.0.11 + +### Patch Changes + +- 2007d55: Update example configs; Use dotenv in examples; Use layerzero.config without an extension as a default value for --oapp-config + +## 0.0.10 + +### Patch Changes + +- 151a92e: Improve error handling and introduce node engine specifiers + +## 0.0.9 + +### Patch Changes + +- 5c58d69: Update @layerzerolabs dependencies to 2.1.3 + +## 0.0.8 + +### Patch Changes + +- f0036c5: Use monorepo 2.1.2 released dependencies + +## 0.0.7 + +### Patch Changes + +- 7aaf750: Fix compile & tests scripts for npm + +## 0.0.6 + +### Patch Changes + +- 0877186: Update @layerzerolabs dependencies to 2.0.25 and 2.0.26-rc1 + +## 0.0.5 + +### Patch Changes + +- 1e375c9: Adding EVM testing abilities for hardhat and foundry + +## 0.0.4 + +### Patch Changes + +- af8cc25: Update dependencies + +## 0.0.3 + +### Patch Changes + +- 73b37d0: Include solidity-bytes-utils in toolbox-foundry + +## 0.0.2 + +### Patch Changes + +- 6483544: Update dependency versions +- 70646b4: Add missing dependencies + +## 0.0.1 + +### Patch Changes + +- b74afbe: Initial 0.0.1 version diff --git a/examples/oft-composer-library/README.md b/examples/oft-composer-library/README.md new file mode 100644 index 000000000..6edc40dc3 --- /dev/null +++ b/examples/oft-composer-library/README.md @@ -0,0 +1,528 @@ +

+ + LayerZero + +

+ +

+ Homepage | Docs | Developers +

+ +

Omnichain Fungible Token (OFT) Example

+ +

+ Quickstart | Configuration | Message Execution Options | Endpoint, MessageLib, & Executor Addresses | DVN Addresses +

+ +

Template project for getting started with LayerZero's OFT contract standard.

+ +

+ +This standard works by combining the LayerZero OApp Contract Standard with the ERC20 [`_burn`](https://github.com/LayerZero-Labs/LayerZero-v2/blob/main/packages/layerzero-v2/evm/oapp/contracts/oft/OFT.sol#L80) method, to initiate omnichain send transfers on the source chain, sending a message via the LayerZero protocol, and delivering a function call to the destination contract to [`_mint`](https://github.com/LayerZero-Labs/LayerZero-v2/blob/main/packages/layerzero-v2/evm/oapp/contracts/oft/OFT.sol#L96) the same number of tokens burned, creating a unified supply across all networks connected. + +Read more about what you can do with OFTs by reading the [OFT Quickstart](https://docs.layerzero.network/v2/developers/evm/oft/quickstart) in the LayerZero Documentation. + +## LayerZero Hardhat Helper Tasks + +LayerZero Devtools provides several helper hardhat tasks to easily deploy, verify, configure, connect, and send OFTs cross-chain. + +

+ npx hardhat lz:deploy + +
+ +Deploys your contract to any of the available networks in your [`hardhat.config.ts`](./hardhat.config.ts) when given a deploy tag (by default contract name) and returns a list of available networks to select for the deployment. For specifics around all deployment options, please refer to the [Deploying Contracts](https://docs.layerzero.network/v2/developers/evm/create-lz-oapp/deploying) section of the documentation. LayerZero's `lz:deploy` utilizes `hardhat-deploy`. + +```yml +'arbitrum-sepolia': { + eid: EndpointId.ARBSEP_V2_TESTNET, + url: process.env.RPC_URL_ARBSEP_TESTNET, + accounts, +}, +'base-sepolia': { + eid: EndpointId.BASESEP_V2_TESTNET, + url: process.env.RPC_URL_BASE_TESTNET, + accounts, +}, +``` + +
+ +
+ npx hardhat lz:oapp:config:init --oapp-config YOUR_OAPP_CONFIG --contract-name CONTRACT_NAME + +
+ +Initializes a `layerzero.config.ts` file for all available pathways between your hardhat networks with the current LayerZero default placeholder settings. This task can be incredibly useful for correctly formatting your config file. + +You can run this task by providing the `contract-name` you want to set for the config and `file-name` you want to generate: + +```bash +npx hardhat lz:oapp:config:init --contract-name CONTRACT_NAME --oapp-config FILE_NAME +``` + +This will create a `layerzero.config.ts` in your working directory populated with your contract name and connections for every pathway possible between your hardhat networks: + +```yml +import { EndpointId } from '@layerzerolabs/lz-definitions' + +const arbsepContract = { + eid: EndpointId.ARBSEP_V2_TESTNET, + contractName: 'MyOFT', +} +const sepoliaContract = { + eid: EndpointId.SEPOLIA_V2_TESTNET, + contractName: 'MyOFT', +} + +export default { + contracts: [{ contract: arbsepContract }, { contract: sepoliaContract }], + connections: [ + { + from: arbsepContract, + to: sepoliaContract, + config: { + sendLibrary: '0x4f7cd4DA19ABB31b0eC98b9066B9e857B1bf9C0E', + receiveLibraryConfig: { receiveLibrary: '0x75Db67CDab2824970131D5aa9CECfC9F69c69636', gracePeriod: 0 }, + sendConfig: { + executorConfig: { maxMessageSize: 10000, executor: '0x5Df3a1cEbBD9c8BA7F8dF51Fd632A9aef8308897' }, + ulnConfig: { + confirmations: 1, + requiredDVNs: ['0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8'], + optionalDVNs: [], + optionalDVNThreshold: 0, + }, + }, + // receiveConfig: { + // ulnConfig: { + // confirmations: 2, + // requiredDVNs: ['0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8'], + // optionalDVNs: [], + // optionalDVNThreshold: 0, + // }, + // }, + }, + }, + { + from: sepoliaContract, + to: arbsepContract, + config: { + sendLibrary: '0xcc1ae8Cf5D3904Cef3360A9532B477529b177cCE', + receiveLibraryConfig: { receiveLibrary: '0xdAf00F5eE2158dD58E0d3857851c432E34A3A851', gracePeriod: 0 }, + // sendConfig: { + // executorConfig: { maxMessageSize: 10000, executor: '0x718B92b5CB0a5552039B593faF724D182A881eDA' }, + // ulnConfig: { + // confirmations: 2, + // requiredDVNs: ['0x8eebf8b423B73bFCa51a1Db4B7354AA0bFCA9193'], + // optionalDVNs: [], + // optionalDVNThreshold: 0, + // }, + // }, + receiveConfig: { + ulnConfig: { + confirmations: 1, + requiredDVNs: ['0x8eebf8b423B73bFCa51a1Db4B7354AA0bFCA9193'], + optionalDVNs: [], + optionalDVNThreshold: 0, + }, + }, + }, + }, + ], +} +``` + +
+ +
+ npx hardhat lz:oapp:config:wire --oapp-config YOUR_OAPP_CONFIG + +
+ +Calls the configuration functions between your deployed OApp contracts on every chain based on the provided `layerzero.config.ts`. + +Running `lz:oapp:wire` will make the following function calls per pathway connection for a fully defined config file using your specified settings and your environment variables (Private Keys and RPCs): + +- function setPeer(uint32 \_eid, bytes32 \_peer) public virtual onlyOwner {} + +- function setConfig(address \_oapp, address \_lib, SetConfigParam[] calldata \_params) external onlyRegistered(\_lib) {} + +- function setEnforcedOptions(EnforcedOptionParam[] calldata \_enforcedOptions) public virtual onlyOwner {} + +- function setSendLibrary(address \_oapp, uint32 \_eid, address \_newLib) external onlyRegisteredOrDefault(\_newLib) isSendLib(\_newLib) onlySupportedEid(\_newLib, \_eid) {} + +- function setReceiveLibrary(address \_oapp, uint32 \_eid, address \_newLib, uint256 \_gracePeriod) external onlyRegisteredOrDefault(\_newLib) isReceiveLib(\_newLib) onlySupportedEid(\_newLib, \_eid) {} + +To use this task, run: + +```bash +npx hardhat lz:oapp:wire --oapp-config YOUR_LAYERZERO_CONFIG_FILE +``` + +Whenever you make changes to the configuration, run `lz:oapp:wire` again. The task will check your current configuration, and only apply NEW changes. + +To use a Gnosis Safe multisig as the signer for these transactions, add the following to each network in your `hardhat.config.ts` and add the `--safe` flag to `lz:oapp:wire --safe`: + +```yml +// hardhat.config.ts + +networks: { + // Include configurations for other networks as needed + fuji: { + /* ... */ + // Network-specific settings + safeConfig: { + safeUrl: 'http://something', // URL of the Safe API, not the Safe itself + safeAddress: 'address' + } + } +} +``` + +
+
+ npx hardhat lz:oapp:config:get --oapp-config YOUR_OAPP_CONFIG + +
+ +Returns your current OApp's configuration for each chain and pathway in 3 columns: + +- **Custom Configuration**: the changes that your `layerzero.config.ts` currently has set + +- **Default Configuration**: the default placeholder configuration that LayerZero provides + +- **Active Configuration**: the active configuration that applies to the message pathway (Defaults + Custom Values) + +If you do NOT explicitly set each configuration parameter, your OApp will fallback to the placeholder parameters in the default config. + +```bash +┌────────────────────┬───────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┐ +│ │ Custom OApp Config │ Default OApp Config │ Active OApp Config │ +├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ +│ localNetworkName │ arbsep │ arbsep │ arbsep │ +├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ +│ remoteNetworkName │ sepolia │ sepolia │ sepolia │ +├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ +│ sendLibrary │ 0x4f7cd4DA19ABB31b0eC98b9066B9e857B1bf9C0E │ 0x4f7cd4DA19ABB31b0eC98b9066B9e857B1bf9C0E │ 0x4f7cd4DA19ABB31b0eC98b9066B9e857B1bf9C0E │ +├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ +│ receiveLibrary │ 0x75Db67CDab2824970131D5aa9CECfC9F69c69636 │ 0x75Db67CDab2824970131D5aa9CECfC9F69c69636 │ 0x75Db67CDab2824970131D5aa9CECfC9F69c69636 │ +├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ +│ sendUlnConfig │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ +│ │ │ confirmations │ 1 │ │ │ confirmations │ 1 │ │ │ confirmations │ 1 │ │ +│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ +│ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ +│ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ +│ │ │ │ └───┴────────────────────────────────────────────┘ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ +│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ +│ │ │ optionalDVNs │ │ │ │ optionalDVNs │ │ │ │ optionalDVNs │ │ │ +│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ +│ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNThreshold │ 0 │ │ +│ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ +│ │ │ │ │ +├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ +│ sendExecutorConfig │ ┌────────────────┬────────────────────────────────────────────┐ │ ┌────────────────┬────────────────────────────────────────────┐ │ ┌────────────────┬────────────────────────────────────────────┐ │ +│ │ │ executor │ 0x5Df3a1cEbBD9c8BA7F8dF51Fd632A9aef8308897 │ │ │ executor │ 0x5Df3a1cEbBD9c8BA7F8dF51Fd632A9aef8308897 │ │ │ executor │ 0x5Df3a1cEbBD9c8BA7F8dF51Fd632A9aef8308897 │ │ +│ │ ├────────────────┼────────────────────────────────────────────┤ │ ├────────────────┼────────────────────────────────────────────┤ │ ├────────────────┼────────────────────────────────────────────┤ │ +│ │ │ maxMessageSize │ 10000 │ │ │ maxMessageSize │ 10000 │ │ │ maxMessageSize │ 10000 │ │ +│ │ └────────────────┴────────────────────────────────────────────┘ │ └────────────────┴────────────────────────────────────────────┘ │ └────────────────┴────────────────────────────────────────────┘ │ +│ │ │ │ │ +├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ +│ receiveUlnConfig │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ +│ │ │ confirmations │ 2 │ │ │ confirmations │ 2 │ │ │ confirmations │ 2 │ │ +│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ +│ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ +│ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ +│ │ │ │ └───┴────────────────────────────────────────────┘ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │ +│ │ │ │ │ │ │ │ │ │ │ │ │ │ +│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ +│ │ │ optionalDVNs │ │ │ │ optionalDVNs │ │ │ │ optionalDVNs │ │ │ +│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ +│ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNThreshold │ 0 │ │ +│ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ +│ │ │ │ │ +└────────────────────┴───────────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┘ +``` + +
+
+ npx hardhat lz:oapp:config:get:executor --oapp-config YOUR_OAPP_CONFIG + +
+ +Returns the LayerZero Executor config for each network in your `hardhat.config.ts`. You can use this method to see the max destination gas in wei (`nativeCap`) you can request in your [`execution options`](https://docs.layerzero.network/v2/developers/evm/gas-settings/options). + +```bash +┌───────────────────┬────────────────────────────────────────────┐ +│ localNetworkName │ mantle │ +├───────────────────┼────────────────────────────────────────────┤ +│ remoteNetworkName │ polygon │ +├───────────────────┼────────────────────────────────────────────┤ +│ executorDstConfig │ ┌────────────────┬───────────────────────┐ │ +│ │ │ baseGas │ 85000 │ │ +│ │ ├────────────────┼───────────────────────┤ │ +│ │ │ multiplierBps │ 12000 │ │ +│ │ ├────────────────┼───────────────────────┤ │ +│ │ │ floorMarginUSD │ 5000000000000000000 │ │ +│ │ ├────────────────┼───────────────────────┤ │ +│ │ │ nativeCap │ 681000000000000000000 │ │ +│ │ └────────────────┴───────────────────────┘ │ +│ │ │ +└───────────────────┴────────────────────────────────────────────┘ +``` + +
+ +## Developing Contracts + +#### Installing dependencies + +We recommend using `pnpm` as a package manager (but you can of course use a package manager of your choice): + +```bash +pnpm install +``` + +#### Compiling your contracts + +This project supports both `hardhat` and `forge` compilation. By default, the `compile` command will execute both: + +```bash +pnpm compile +``` + +If you prefer one over the other, you can use the tooling-specific commands: + +```bash +pnpm compile:forge +pnpm compile:hardhat +``` + +Or adjust the `package.json` to for example remove `forge` build: + +```diff +- "compile": "$npm_execpath run compile:forge && $npm_execpath run compile:hardhat", +- "compile:forge": "forge build", +- "compile:hardhat": "hardhat compile", ++ "compile": "hardhat compile" +``` + +#### Running tests + +Similarly to the contract compilation, we support both `hardhat` and `forge` tests. By default, the `test` command will execute both: + +```bash +pnpm test +``` + +If you prefer one over the other, you can use the tooling-specific commands: + +```bash +pnpm test:forge +pnpm test:hardhat +``` + +Or adjust the `package.json` to for example remove `hardhat` tests: + +```diff +- "test": "$npm_execpath test:forge && $npm_execpath test:hardhat", +- "test:forge": "forge test", +- "test:hardhat": "$npm_execpath hardhat test" ++ "test": "forge test" +``` + +## Deploying Contracts + +Set up deployer wallet/account: + +- Rename `.env.example` -> `.env` +- Choose your preferred means of setting up your deployer wallet/account: + +``` +MNEMONIC="test test test test test test test test test test test junk" +or... +PRIVATE_KEY="0xabc...def" +``` + +- Fund this address with the corresponding chain's native tokens you want to deploy to. + +To deploy your contracts to your desired blockchains, run the following command in your project's folder: + +```bash +npx hardhat lz:deploy +``` + +More information about available CLI arguments can be found using the `--help` flag: + +```bash +npx hardhat lz:deploy --help +``` + +By following these steps, you can focus more on creating innovative omnichain solutions and less on the complexities of cross-chain communication. + +

+ +## Connecting Contracts + +### Ethereum Configurations + +Fill out your `layerzero.config.ts` with the contracts you want to connect. You can generate the default config file for your declared hardhat networks by running: + +```bash +npx hardhat lz:oapp:config:init --contract-name [YOUR_CONTRACT_NAME] --oapp-config [CONFIG_NAME] +``` + +> [!NOTE] +> You may need to change the contract name if you're deploying multiple OApp contracts on different chains (e.g., OFT and OFT Adapter). + +
+ +```typescript +const ethereumContract: OmniPointHardhat = { + eid: EndpointId.ETHEREUM_V2_MAINNET, + contractName: "MyOFTAdapter", +}; + +const arbitrumContract: OmniPointHardhat = { + eid: EndpointId.ARBITRUM_V2_MAINNET, + contractName: "MyOFT", +}; +``` + +Then define the pathway you want to create from and to each contract: + +```typescript +connections: [ + // ETH <--> ARB PATHWAY: START + { + from: ethereumContract, + to: arbitrumContract, + }, + { + from: arbitrumContract, + to: ethereumContract, + }, + // ETH <--> ARB PATHWAY: END +]; +``` + +Finally, define the config settings for each direction of the pathway: + +```typescript +connections: [ + // ETH <--> ARB PATHWAY: START + { + from: ethereumContract, + to: arbitrumContract, + config: { + sendLibrary: contractsConfig.ethereum.sendLib302, + receiveLibraryConfig: { + receiveLibrary: contractsConfig.ethereum.receiveLib302, + gracePeriod: BigInt(0), + }, + // Optional Receive Library Timeout for when the Old Receive Library Address will no longer be valid + receiveLibraryTimeoutConfig: { + lib: "0x0000000000000000000000000000000000000000", + expiry: BigInt(0), + }, + // Optional Send Configuration + // @dev Controls how the `from` chain sends messages to the `to` chain. + sendConfig: { + executorConfig: { + maxMessageSize: 10000, + // The configured Executor address + executor: contractsConfig.ethereum.executor, + }, + ulnConfig: { + // The number of block confirmations to wait on BSC before emitting the message from the source chain. + confirmations: BigInt(15), + // The address of the DVNs you will pay to verify a sent message on the source chain ). + // The destination tx will wait until ALL `requiredDVNs` verify the message. + requiredDVNs: [ + contractsConfig.ethereum.horizenDVN, // Horizen + contractsConfig.ethereum.polyhedraDVN, // Polyhedra + contractsConfig.ethereum.animocaBlockdaemonDVN, // Animoca-Blockdaemon (only available on ETH <-> Arbitrum One) + contractsConfig.ethereum.lzDVN, // LayerZero Labs + ], + // The address of the DVNs you will pay to verify a sent message on the source chain ). + // The destination tx will wait until the configured threshold of `optionalDVNs` verify a message. + optionalDVNs: [], + // The number of `optionalDVNs` that need to successfully verify the message for it to be considered Verified. + optionalDVNThreshold: 0, + }, + }, + // Optional Receive Configuration + // @dev Controls how the `from` chain receives messages from the `to` chain. + receiveConfig: { + ulnConfig: { + // The number of block confirmations to expect from the `to` chain. + confirmations: BigInt(20), + // The address of the DVNs your `receiveConfig` expects to receive verifications from on the `from` chain ). + // The `from` chain's OApp will wait until the configured threshold of `requiredDVNs` verify the message. + requiredDVNs: [ + contractsConfig.ethereum.lzDVN, // LayerZero Labs DVN + contractsConfig.ethereum.animocaBlockdaemonDVN, // Blockdaemon-Animoca + contractsConfig.ethereum.horizenDVN, // Horizen Labs + contractsConfig.ethereum.polyhedraDVN, // Polyhedra + ], + // The address of the `optionalDVNs` you expect to receive verifications from on the `from` chain ). + // The destination tx will wait until the configured threshold of `optionalDVNs` verify the message. + optionalDVNs: [], + // The number of `optionalDVNs` that need to successfully verify the message for it to be considered Verified. + optionalDVNThreshold: 0, + }, + }, + // Optional Enforced Options Configuration + // @dev Controls how much gas to use on the `to` chain, which the user pays for on the source `from` chain. + enforcedOptions: [ + { + msgType: 1, + optionType: ExecutorOptionType.LZ_RECEIVE, + gas: 65000, + value: 0, + }, + { + msgType: 2, + optionType: ExecutorOptionType.LZ_RECEIVE, + gas: 65000, + value: 0, + }, + { + msgType: 2, + optionType: ExecutorOptionType.COMPOSE, + index: 0, + gas: 50000, + value: 0, + }, + ], + }, + }, + { + from: arbitrumContract, + to: ethereumContract, + }, + // ETH <--> ARB PATHWAY: END +]; +``` + +To set these config settings, run: + +```bash +npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts +``` + +

+ Join our community on Discord | Follow us on Twitter +

diff --git a/examples/oft-composer-library/contracts/MyOFT.sol b/examples/oft-composer-library/contracts/MyOFT.sol new file mode 100644 index 000000000..f8bc7b47f --- /dev/null +++ b/examples/oft-composer-library/contracts/MyOFT.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.22; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { OFT } from "@layerzerolabs/oft-evm/contracts/OFT.sol"; + +contract MyOFT is OFT { + constructor( + string memory _name, + string memory _symbol, + address _lzEndpoint, + address _delegate + ) OFT(_name, _symbol, _lzEndpoint, _delegate) Ownable(_delegate) {} +} diff --git a/examples/oft-composer-library/contracts/UniswapV3Composer.sol b/examples/oft-composer-library/contracts/UniswapV3Composer.sol new file mode 100644 index 000000000..54d6eb5d1 --- /dev/null +++ b/examples/oft-composer-library/contracts/UniswapV3Composer.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// Import necessary interfaces and libraries +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; + +import { IOAppComposer } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppComposer.sol"; +import { IOFT } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; +import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol"; + +/** + * @title UniswapV3Composer + * @author + * @notice Handles cross-chain OFT token swaps using Uniswap V3 upon receiving tokens via LayerZero. + * @dev This contract inherits from IOAppComposer and interacts with Uniswap V3's SwapRouter to execute token swaps. + */ +contract UniswapV3Composer is IOAppComposer { + using SafeERC20 for IERC20; + + /// @notice The Uniswap V3 SwapRouter used to perform token swaps. + ISwapRouter public immutable swapRouter; + + /// @notice The LayerZero Endpoint address for cross-chain communication. + address public immutable endpoint; + + /// @notice The address of the OFT on the receiving chain. + address public immutable oft; + + /// @notice Emitted when a token swap is successfully executed. + /// @param user The address of the user initiating the swap. + /// @param tokenIn The address of the ERC20 token being swapped from (OFT). + /// @param tokenOut The address of the ERC20 token being swapped to. + /// @param amountIn The amount of `tokenIn` being swapped. + /// @param amountOut The amount of `tokenOut` received from the swap. + event SwapExecuted( + address indexed user, + address tokenIn, + address tokenOut, + uint256 amountIn, + uint256 amountOut + ); + + /** + * @notice Initializes the UniswapV3Composer contract with necessary parameters. + * @param _swapRouter The address of the Uniswap V3 SwapRouter. + * @param _endpoint The LayerZero Endpoint address for cross-chain communication. + * @param _oft The address of the originating OFT that sends composed messages. + * + * Requirements: + * + * - `_swapRouter` cannot be the zero address. + * - `_endpoint` cannot be the zero address. + * - `_oft` cannot be the zero address. + */ + constructor( + address _swapRouter, + address _endpoint, + address _oft + ) { + require(_swapRouter != address(0), "Invalid SwapRouter address"); + require(_endpoint != address(0), "Invalid Endpoint address"); + require(_oft != address(0), "Invalid OFT address"); + + swapRouter = ISwapRouter(_swapRouter); + endpoint = _endpoint; + oft = _oft; + } + + /** + * @notice Handles incoming composed messages from LayerZero to execute token swaps on Uniswap V3. + * + * @param _oft The address of the originating OFT. + * @param _message The encoded message content in the format of OFTComposeMsgCodec. + * @dev _executor The address of the executor (unused in this context). + * @dev _guid The globally unique identifier of the message (unused in this context). + * @dev _executorData Additional data for the executor (unused in this context). + * @dev + * This function decodes the incoming message to extract swap parameters and executes the token swap using Uniswap V3. + * It ensures that only the authorized OFT and the LayerZero Endpoint can invoke this function. + * + * Emits a {SwapExecuted} event upon successful execution of the swap. + * + * Requirements: + * + * - `_oft` must match the authorized OFT address. + * - The caller must be the authorized LayerZero Endpoint. + * + * Reverts if any of the above conditions are not met. + */ + function lzCompose( + address _oft, + bytes32 /*_guid*/, + bytes calldata _message, + address /*_executor*/, + bytes calldata /*_extraData*/ + ) external payable override { + require(_oft == address(oft), "Unauthorized OFT"); + require(msg.sender == endpoint, "Unauthorized Endpoint"); + + // Decode the composed message using OFTComposeMsgCodec + ( + address user, + address tokenOut, + uint24 fee, + address recipient + ) = abi.decode( + OFTComposeMsgCodec.composeMsg(_message), + (address, address, uint24, address) + ); + + // Decode the amountIn from the message amount received + uint256 amountIn = OFTComposeMsgCodec.amountLD(_message); + + // Reference to the ERC20 token used by the OFT + address tokenIn = IOFT(oft).token(); + + // Approve the SwapRouter to spend tokenIn + IERC20(tokenIn).approve(address(swapRouter), amountIn); + + // Set up Uniswap V3 swap parameters + ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ + tokenIn: tokenIn, + tokenOut: tokenOut, + fee: fee, + recipient: recipient, + deadline: block.timestamp + 300, // 5 minutes deadline + amountIn: amountIn, + amountOutMinimum: 0, // Consider setting a minimum amount out to protect against slippage + sqrtPriceLimitX96: 0 // No price limit + }); + + // Execute the swap on Uniswap V3 + uint256 amountOut = swapRouter.exactInputSingle(params); + + // Emit an event to log the swap details + emit SwapExecuted(user, tokenIn, tokenOut, amountIn, amountOut); + } +} diff --git a/examples/oft-composer-library/contracts/mocks/MyOFTMock.sol b/examples/oft-composer-library/contracts/mocks/MyOFTMock.sol new file mode 100644 index 000000000..3ebb888d4 --- /dev/null +++ b/examples/oft-composer-library/contracts/mocks/MyOFTMock.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.22; + +import { MyOFT } from "../MyOFT.sol"; + +// @dev WARNING: This is for testing purposes only +contract MyOFTMock is MyOFT { + constructor( + string memory _name, + string memory _symbol, + address _lzEndpoint, + address _delegate + ) MyOFT(_name, _symbol, _lzEndpoint, _delegate) {} + + function mint(address _to, uint256 _amount) public { + _mint(_to, _amount); + } +} diff --git a/examples/oft-composer-library/deploy/MyOFT.ts b/examples/oft-composer-library/deploy/MyOFT.ts new file mode 100644 index 000000000..bcbdeb19b --- /dev/null +++ b/examples/oft-composer-library/deploy/MyOFT.ts @@ -0,0 +1,53 @@ +import assert from 'assert' + +import { type DeployFunction } from 'hardhat-deploy/types' + +const contractName = 'MyOFT' + +const deploy: DeployFunction = async (hre) => { + const { getNamedAccounts, deployments } = hre + + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + + assert(deployer, 'Missing named deployer account') + + console.log(`Network: ${hre.network.name}`) + console.log(`Deployer: ${deployer}`) + + // This is an external deployment pulled in from @layerzerolabs/lz-evm-sdk-v2 + // + // @layerzerolabs/toolbox-hardhat takes care of plugging in the external deployments + // from @layerzerolabs packages based on the configuration in your hardhat config + // + // For this to work correctly, your network config must define an eid property + // set to `EndpointId` as defined in @layerzerolabs/lz-definitions + // + // For example: + // + // networks: { + // fuji: { + // ... + // eid: EndpointId.AVALANCHE_V2_TESTNET + // } + // } + const endpointV2Deployment = await hre.deployments.get('EndpointV2') + + const { address } = await deploy(contractName, { + from: deployer, + args: [ + 'MyOFT', // name + 'MOFT', // symbol + endpointV2Deployment.address, // LayerZero's EndpointV2 address + deployer, // owner + ], + log: true, + skipIfAlreadyDeployed: false, + }) + + console.log(`Deployed contract: ${contractName}, network: ${hre.network.name}, address: ${address}`) +} + +deploy.tags = [contractName] + +export default deploy diff --git a/examples/oft-composer-library/foundry.toml b/examples/oft-composer-library/foundry.toml new file mode 100644 index 000000000..7af2bea24 --- /dev/null +++ b/examples/oft-composer-library/foundry.toml @@ -0,0 +1,33 @@ +[profile.default] +solc-version = '0.8.22' +src = 'contracts' +out = 'out' +test = 'test/foundry' +cache_path = 'cache/foundry' +verbosity = 3 +libs = [ + # We provide a set of useful contract utilities + # in the lib directory of @layerzerolabs/toolbox-foundry: + # + # - forge-std + # - ds-test + # - solidity-bytes-utils + 'node_modules/@layerzerolabs/toolbox-foundry/lib', + 'node_modules', +] + +remappings = [ + # Due to a misconfiguration of solidity-bytes-utils, an outdated version + # of forge-std is being dragged in + # + # To remedy this, we'll remap the ds-test and forge-std imports to our own versions + 'ds-test/=node_modules/@layerzerolabs/toolbox-foundry/lib/ds-test', + 'forge-std/=node_modules/@layerzerolabs/toolbox-foundry/lib/forge-std', + '@layerzerolabs/=node_modules/@layerzerolabs/', + '@openzeppelin/=node_modules/@openzeppelin/', + '@uniswap/v3-periphery/=node_modules/@uniswap/v3-periphery/', + '@uniswap/v3-core/=node_modules/@uniswap/v3-core/', +] + +[fuzz] +runs = 1000 diff --git a/examples/oft-composer-library/hardhat.config.ts b/examples/oft-composer-library/hardhat.config.ts new file mode 100644 index 000000000..85c1ae8ff --- /dev/null +++ b/examples/oft-composer-library/hardhat.config.ts @@ -0,0 +1,83 @@ +// Get the environment configuration from .env file +// +// To make use of automatic environment setup: +// - Duplicate .env.example file and name it .env +// - Fill in the environment variables +import 'dotenv/config' + +import 'hardhat-deploy' +import 'hardhat-contract-sizer' +import '@nomiclabs/hardhat-ethers' +import '@layerzerolabs/toolbox-hardhat' +import { HardhatUserConfig, HttpNetworkAccountsUserConfig } from 'hardhat/types' + +import { EndpointId } from '@layerzerolabs/lz-definitions' +import './tasks/send.ts' + +// Set your preferred authentication method +// +// If you prefer using a mnemonic, set a MNEMONIC environment variable +// to a valid mnemonic +const MNEMONIC = process.env.MNEMONIC + +// If you prefer to be authenticated using a private key, set a PRIVATE_KEY environment variable +const PRIVATE_KEY = process.env.PRIVATE_KEY + +const accounts: HttpNetworkAccountsUserConfig | undefined = MNEMONIC + ? { mnemonic: MNEMONIC } + : PRIVATE_KEY + ? [PRIVATE_KEY] + : undefined + +if (accounts == null) { + console.warn( + 'Could not find MNEMONIC or PRIVATE_KEY environment variables. It will not be possible to execute transactions in your example.' + ) +} + +const config: HardhatUserConfig = { + paths: { + cache: 'cache/hardhat', + }, + solidity: { + compilers: [ + { + version: '0.8.22', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + ], + }, + networks: { + 'sepolia-testnet': { + eid: EndpointId.SEPOLIA_V2_TESTNET, + url: process.env.RPC_URL_SEPOLIA || 'https://rpc.sepolia.org/', + accounts, + }, + 'avalanche-testnet': { + eid: EndpointId.AVALANCHE_V2_TESTNET, + url: process.env.RPC_URL_FUJI || 'https://rpc.ankr.com/avalanche_fuji', + accounts, + }, + 'amoy-testnet': { + eid: EndpointId.AMOY_V2_TESTNET, + url: process.env.RPC_URL_AMOY || 'https://polygon-amoy-bor-rpc.publicnode.com', + accounts, + }, + hardhat: { + // Need this for testing because TestHelperOz5.sol is exceeding the compiled contract size limit + allowUnlimitedContractSize: true, + }, + }, + namedAccounts: { + deployer: { + default: 0, // wallet address of index[0], of the mnemonic in .env + }, + }, +} + +export default config diff --git a/examples/oft-composer-library/layerzero.config.ts b/examples/oft-composer-library/layerzero.config.ts new file mode 100644 index 000000000..5a239c8ed --- /dev/null +++ b/examples/oft-composer-library/layerzero.config.ts @@ -0,0 +1,60 @@ +import { EndpointId } from '@layerzerolabs/lz-definitions' + +import type { OAppOmniGraphHardhat, OmniPointHardhat } from '@layerzerolabs/toolbox-hardhat' + +const sepoliaContract: OmniPointHardhat = { + eid: EndpointId.SEPOLIA_V2_TESTNET, + contractName: 'MyOFT', +} + +const fujiContract: OmniPointHardhat = { + eid: EndpointId.AVALANCHE_V2_TESTNET, + contractName: 'MyOFT', +} + +const amoyContract: OmniPointHardhat = { + eid: EndpointId.AMOY_V2_TESTNET, + contractName: 'MyOFT', +} + +const config: OAppOmniGraphHardhat = { + contracts: [ + { + contract: fujiContract, + }, + { + contract: sepoliaContract, + }, + { + contract: amoyContract, + }, + ], + connections: [ + { + from: fujiContract, + to: sepoliaContract, + }, + { + from: fujiContract, + to: amoyContract, + }, + { + from: sepoliaContract, + to: fujiContract, + }, + { + from: sepoliaContract, + to: amoyContract, + }, + { + from: amoyContract, + to: sepoliaContract, + }, + { + from: amoyContract, + to: fujiContract, + }, + ], +} + +export default config diff --git a/examples/oft-composer-library/package.json b/examples/oft-composer-library/package.json new file mode 100644 index 000000000..0041b015f --- /dev/null +++ b/examples/oft-composer-library/package.json @@ -0,0 +1,80 @@ +{ + "name": "@layerzerolabs/oft-composer-library-example", + "version": "0.5.1", + "private": true, + "license": "MIT", + "scripts": { + "clean": "rm -rf artifacts cache out", + "compile": "concurrently -c auto --names forge,hardhat '$npm_execpath run compile:forge' '$npm_execpath run compile:hardhat'", + "compile:forge": "forge build", + "compile:hardhat": "hardhat compile", + "lint": "$npm_execpath run lint:js && $npm_execpath run lint:sol", + "lint:fix": "eslint --fix '**/*.{js,ts,json}' && prettier --write . && solhint 'contracts/**/*.sol' --fix --noPrompt", + "lint:js": "eslint '**/*.{js,ts,json}' && prettier --check .", + "lint:sol": "solhint 'contracts/**/*.sol'", + "test": "$npm_execpath run test:forge && $npm_execpath run test:hardhat", + "test:forge": "forge test", + "test:hardhat": "hardhat test" + }, + "resolutions": { + "ethers": "^5.7.2", + "hardhat-deploy": "^0.12.1" + }, + "dependencies": { + "@uniswap/v3-core": "^1.0.1" + }, + "devDependencies": { + "@babel/core": "^7.23.9", + "@layerzerolabs/devtools-evm-hardhat": "^2.0.1", + "@layerzerolabs/eslint-config-next": "~2.3.39", + "@layerzerolabs/lz-definitions": "^3.0.12", + "@layerzerolabs/lz-evm-messagelib-v2": "^3.0.12", + "@layerzerolabs/lz-evm-protocol-v2": "^3.0.12", + "@layerzerolabs/lz-evm-v1-0.7": "^3.0.12", + "@layerzerolabs/lz-v2-utilities": "^3.0.12", + "@layerzerolabs/oapp-evm": "^0.3.0", + "@layerzerolabs/oft-evm": "^3.0.0", + "@layerzerolabs/prettier-config-next": "^2.3.39", + "@layerzerolabs/solhint-config": "^3.0.12", + "@layerzerolabs/test-devtools-evm-foundry": "~5.1.0", + "@layerzerolabs/toolbox-foundry": "~0.1.9", + "@layerzerolabs/toolbox-hardhat": "~0.6.0", + "@nomicfoundation/hardhat-ethers": "^3.0.5", + "@nomiclabs/hardhat-ethers": "^2.2.3", + "@openzeppelin/contracts": "^5.0.2", + "@openzeppelin/contracts-upgradeable": "^5.0.2", + "@rushstack/eslint-patch": "^1.7.0", + "@types/chai": "^4.3.11", + "@types/mocha": "^10.0.6", + "@types/node": "~18.18.14", + "@uniswap/v3-periphery": "^1.4.4", + "chai": "^4.4.1", + "concurrently": "~9.1.0", + "dotenv": "^16.4.1", + "eslint": "^8.55.0", + "eslint-plugin-jest-extended": "~2.0.0", + "ethers": "^5.7.2", + "hardhat": "^2.22.10", + "hardhat-contract-sizer": "^2.10.0", + "hardhat-deploy": "^0.12.1", + "mocha": "^10.2.0", + "prettier": "^3.2.5", + "solhint": "^4.1.1", + "solidity-bytes-utils": "^0.8.2", + "ts-node": "^10.9.2", + "typescript": "^5.4.4" + }, + "engines": { + "node": ">=18.16.0" + }, + "pnpm": { + "overrides": { + "ethers": "^5.7.2", + "hardhat-deploy": "^0.12.1" + } + }, + "overrides": { + "ethers": "^5.7.2", + "hardhat-deploy": "^0.12.1" + } +} diff --git a/examples/oft-composer-library/solhint.config.js b/examples/oft-composer-library/solhint.config.js new file mode 100644 index 000000000..52efe629c --- /dev/null +++ b/examples/oft-composer-library/solhint.config.js @@ -0,0 +1 @@ +module.exports = require('@layerzerolabs/solhint-config'); diff --git a/examples/oft-composer-library/tasks/createUniswapPool.ts b/examples/oft-composer-library/tasks/createUniswapPool.ts new file mode 100644 index 000000000..b678492b4 --- /dev/null +++ b/examples/oft-composer-library/tasks/createUniswapPool.ts @@ -0,0 +1,135 @@ +// tasks/createUniswapV3Pool.ts + +import IUniswapV3FactoryABI from '@uniswap/v3-core/artifacts/contracts/interfaces/IUniswapV3Factory.sol/IUniswapV3Factory.json' +import INonfungiblePositionManagerABI from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json' +import { Contract } from 'ethers' +import { task } from 'hardhat/config' +import { HardhatRuntimeEnvironment } from 'hardhat/types' + +// Import ABIs for Uniswap V3 Factory and Position Manager + +// Define the Hardhat task +task('create-uniswapv3-pool', 'Creates a Uniswap V3 pool for your OFT token and USDC on Arbitrum Sepolia').setAction( + async (taskArgs: any, hre: HardhatRuntimeEnvironment) => { + // Destructure necessary objects from Hardhat Runtime Environment + const { ethers, deployments } = hre + + // ====== Configuration ====== + + // Replace these addresses with actual deployed contract addresses on Arbitrum Sepolia + const UNISWAP_V3_FACTORY_ADDRESS = '0xYourUniswapV3FactoryAddress' // e.g., '0x1F98431c8aD98523631AE4a59f267346ea31F984' + const NONFUNGIBLE_POSITION_MANAGER_ADDRESS = '0xYourPositionManagerAddress' // e.g., '0xC36442b4a4522E871399CD717aBDD847Ab11FE88' + const YOUR_OFT_ADDRESS = '0xYourOFTTokenAddress' // Replace with your OFT token address + const USDC_ADDRESS = '0xYourUSDCAddress' // Replace with USDC token address on Arbitrum Sepolia + + // Define the fee tier for the pool (e.g., 3000 = 0.3%) + const FEE_TIER = 3000 + + // Define the amount of OFT and USDC to add as initial liquidity + const AMOUNT_OFT_DESIRED = ethers.utils.parseUnits('1000', 18) // Adjust decimals if your OFT has different decimals + const AMOUNT_USDC_DESIRED = ethers.utils.parseUnits('1000', 6) // USDC typically has 6 decimals + + // Define slippage parameters (set min amounts equal to desired amounts for zero slippage) + const AMOUNT_OFT_MIN = AMOUNT_OFT_DESIRED + const AMOUNT_USDC_MIN = AMOUNT_USDC_DESIRED + + // Define the recipient and deadline for the liquidity provision + const signer = (await ethers.getSigners())[0] + const recipient = signer.address + const deadline = Math.floor(Date.now() / 1000) + 60 * 20 // 20 minutes from now + + // ====== Instantiate Contracts ====== + + // Instantiate Uniswap V3 Factory + const factory = new Contract(UNISWAP_V3_FACTORY_ADDRESS, IUniswapV3FactoryABI.abi, signer) + + // Instantiate Nonfungible Position Manager + const positionManager = new Contract( + NONFUNGIBLE_POSITION_MANAGER_ADDRESS, + INonfungiblePositionManagerABI.abi, + signer + ) + + // Instantiate your OFT token contract + const oftContract = new Contract( + YOUR_OFT_ADDRESS, + [ + 'function approve(address spender, uint256 amount) external returns (bool)', + 'function decimals() view returns (uint8)', + ], + signer + ) + + // Instantiate USDC token contract + const usdcContract = new Contract( + USDC_ADDRESS, + [ + 'function approve(address spender, uint256 amount) external returns (bool)', + 'function decimals() view returns (uint8)', + ], + signer + ) + + // ====== Approve Position Manager to Spend Tokens ====== + + console.log('Approving Position Manager to spend OFT tokens...') + const approveOftTx = await oftContract.approve(NONFUNGIBLE_POSITION_MANAGER_ADDRESS, AMOUNT_OFT_DESIRED) + await approveOftTx.wait() + console.log('OFT token approval completed.') + + console.log('Approving Position Manager to spend USDC tokens...') + const approveUsdcTx = await usdcContract.approve(NONFUNGIBLE_POSITION_MANAGER_ADDRESS, AMOUNT_USDC_DESIRED) + await approveUsdcTx.wait() + console.log('USDC token approval completed.') + + // ====== Check if Pool Exists ====== + + console.log('Checking if the pool already exists...') + const poolAddress = await factory.getPool(YOUR_OFT_ADDRESS, USDC_ADDRESS, FEE_TIER) + if (poolAddress !== ethers.constants.AddressZero) { + console.log(`Pool already exists at address: ${poolAddress}`) + return + } + console.log('Pool does not exist. It will be created upon adding liquidity.') + + // ====== Define Tick Ranges ====== + + // For demonstration purposes, use wide tick ranges to cover all possible prices + const tickSpacing = await factory.tickSpacing(FEE_TIER) // Get tick spacing for the fee tier + const tickLower = -887220 // Minimum tick + const tickUpper = 887220 // Maximum tick + + // ====== Add Liquidity (Create Pool) ====== + + console.log('Adding liquidity to create the pool...') + const mintTx = await positionManager.mint({ + token0: YOUR_OFT_ADDRESS, + token1: USDC_ADDRESS, + fee: FEE_TIER, + tickLower: tickLower, + tickUpper: tickUpper, + amount0Desired: AMOUNT_OFT_DESIRED, + amount1Desired: AMOUNT_USDC_DESIRED, + amount0Min: AMOUNT_OFT_MIN, + amount1Min: AMOUNT_USDC_MIN, + recipient: recipient, + deadline: deadline, + }) + + const receipt = await mintTx.wait() + console.log(`Liquidity added successfully. Transaction hash: ${receipt.transactionHash}`) + + // ====== Retrieve Pool Address ====== + + const newPoolAddress = await factory.getPool(YOUR_OFT_ADDRESS, USDC_ADDRESS, FEE_TIER) + console.log(`New Pool Address: ${newPoolAddress}`) + + // ====== Confirm Pool Creation ====== + + if (newPoolAddress !== ethers.constants.AddressZero) { + console.log('Pool created successfully!') + } else { + console.error('Failed to create the pool.') + } + } +) diff --git a/examples/oft-composer-library/tasks/send.ts b/examples/oft-composer-library/tasks/send.ts new file mode 100644 index 000000000..aeabedfe5 --- /dev/null +++ b/examples/oft-composer-library/tasks/send.ts @@ -0,0 +1,112 @@ +import { BigNumberish, BytesLike } from 'ethers' +import { task } from 'hardhat/config' + +import { getNetworkNameForEid, types } from '@layerzerolabs/devtools-evm-hardhat' +import { EndpointId } from '@layerzerolabs/lz-definitions' +import { Options, addressToBytes32 } from '@layerzerolabs/lz-v2-utilities' + +// Define the interface for task arguments +interface Args { + amount: string + to: string + toEid: EndpointId + tokenOut: string + fee: number +} + +// Define the interface for SendParam as per your requirements +interface SendParam { + dstEid: EndpointId // Destination endpoint ID, represented as a number. + to: BytesLike // Recipient address, represented as bytes. + amountLD: BigNumberish // Amount to send in local decimals. + minAmountLD: BigNumberish // Minimum amount to send in local decimals. + extraOptions: BytesLike // Additional options supplied by the caller to be used in the LayerZero message. + composeMsg: BytesLike // The composed message for the send() operation. + oftCmd: BytesLike // The OFT command to be executed, unused in default OFT implementations. +} + +// Define the Hardhat task +task('lz:oft:send-and-swap', 'Sends tokens via OFT and performs a swap with UniswapV3Composer on the destination chain') + .addParam('to', 'Contract address on the destination network', undefined, types.string) + .addParam('toEid', 'Destination endpoint ID', undefined, types.eid) + .addParam('amount', 'Amount to transfer in token decimals', undefined, types.string) + .addParam('tokenOut', 'Address of the token to swap to on the destination chain', undefined, types.string) + .addParam('fee', 'Uniswap V3 pool fee (e.g., 3000 for 0.3%)', undefined, types.int) + .setAction(async (taskArgs: Args, { ethers, deployments }) => { + // Extract task arguments + const toAddress = taskArgs.to + const eidB = taskArgs.toEid + const tokenOut = taskArgs.tokenOut + const fee = taskArgs.fee + + // Define gas limit and msg.value for the swap on the destination chain + // These values should be estimated based on the swap complexity and network specifics + const swapGasLimit = 300000 // Example gas limit; adjust as needed + const swapMsgValue = ethers.utils.parseEther('0.01') // Example ETH value for gas; adjust as needed + + // Retrieve the OFT deployment information + const oftDeployment = await deployments.get('MyOFT') + + // Get the signer (deployer) account + const [signer] = await ethers.getSigners() + + // Instantiate the OFT contract + const oftContract = new ethers.Contract(oftDeployment.address, oftDeployment.abi, signer) + + // Retrieve the token decimals from the OFT contract + const decimals = await oftContract.decimals() + + // Parse the amount to transfer into the correct units + const amount = ethers.utils.parseUnits(taskArgs.amount, decimals) + + // Initialize the options with existing executor options (e.g., LzReceive) + // and add the new executor option for LzCompose with the gas limit and msg.value + const options = Options.newOptions() + .addExecutorComposeOption(0, swapGasLimit, swapMsgValue.toBigInt()) // New LzCompose option + .toBytes() + + // Define the user initiating the swap as the signer + const user = await signer.getAddress() + + // Define the recipient of the swap on the destination chain + const recipient = toAddress + + // Encode the swap parameters into the composeMsg bytes using abi.encode + const composeMsg = ethers.utils.defaultAbiCoder.encode( + ['address', 'address', 'uint24', 'address'], + [user, tokenOut, fee, recipient] + ) + + // Construct the SendParam object with all required parameters + const sendParam: SendParam = { + dstEid: eidB, + to: addressToBytes32(toAddress), + amountLD: amount, + minAmountLD: amount, // Adjust minAmountLD based on slippage tolerance + extraOptions: options, + composeMsg: composeMsg, // Encoded swap parameters + oftCmd: ethers.utils.arrayify('0x'), // Assuming no OFT command is needed; adjust if necessary + } + + // Obtain the fee quote for the send operation + const feeQuote = await oftContract.quoteSend(sendParam, false) + const nativeFee = feeQuote.nativeFee + + console.log( + `Sending ${taskArgs.amount} token(s) to network ${getNetworkNameForEid(eidB)} (Endpoint ID: ${eidB})` + ) + + // Optionally, approve the amount to be spent by the OFT contract + // This step may be unnecessary if the OFT contract already has the required allowance + /* + const erc20 = IERC20(await oftContract.token()); + await erc20.approve(oftDeployment.address, amount); + */ + + // Execute the send operation with the composed parameters and required fees + const tx = await oftContract.send(sendParam, { nativeFee: nativeFee, lzTokenFee: 0 }, recipient, { + value: nativeFee, // Include the native fee; adjust if lzTokenFee is used + }) + + console.log(`Send transaction initiated. View on LayerZero Scan: https://layerzeroscan.com/tx/${tx.hash}`) + }) diff --git a/examples/oft-composer-library/test/foundry/MyOFT.t.sol b/examples/oft-composer-library/test/foundry/MyOFT.t.sol new file mode 100644 index 000000000..b00e0f449 --- /dev/null +++ b/examples/oft-composer-library/test/foundry/MyOFT.t.sol @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +// Mock imports +import { OFTMock } from "../mocks/OFTMock.sol"; +import { ERC20Mock } from "../mocks/ERC20Mock.sol"; +import { OFTComposerMock } from "../mocks/OFTComposerMock.sol"; + +// OApp imports +import { IOAppOptionsType3, EnforcedOptionParam } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol"; +import { OptionsBuilder } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol"; + +// OFT imports +import { IOFT, SendParam, OFTReceipt } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; +import { MessagingFee, MessagingReceipt } from "@layerzerolabs/oft-evm/contracts/OFTCore.sol"; +import { OFTMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol"; +import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol"; + +// OZ imports +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +// Forge imports +import "forge-std/console.sol"; + +// DevTools imports +import { TestHelperOz5 } from "@layerzerolabs/test-devtools-evm-foundry/contracts/TestHelperOz5.sol"; + +contract MyOFTTest is TestHelperOz5 { + using OptionsBuilder for bytes; + + uint32 private aEid = 1; + uint32 private bEid = 2; + + OFTMock private aOFT; + OFTMock private bOFT; + + address private userA = makeAddr("userA"); + address private userB = makeAddr("userB"); + uint256 private initialBalance = 100 ether; + + function setUp() public virtual override { + vm.deal(userA, 1000 ether); + vm.deal(userB, 1000 ether); + + super.setUp(); + setUpEndpoints(2, LibraryType.UltraLightNode); + + aOFT = OFTMock( + _deployOApp(type(OFTMock).creationCode, abi.encode("aOFT", "aOFT", address(endpoints[aEid]), address(this))) + ); + + bOFT = OFTMock( + _deployOApp(type(OFTMock).creationCode, abi.encode("bOFT", "bOFT", address(endpoints[bEid]), address(this))) + ); + + // config and wire the ofts + address[] memory ofts = new address[](2); + ofts[0] = address(aOFT); + ofts[1] = address(bOFT); + this.wireOApps(ofts); + + // mint tokens + aOFT.mint(userA, initialBalance); + bOFT.mint(userB, initialBalance); + } + + function test_constructor() public { + assertEq(aOFT.owner(), address(this)); + assertEq(bOFT.owner(), address(this)); + + assertEq(aOFT.balanceOf(userA), initialBalance); + assertEq(bOFT.balanceOf(userB), initialBalance); + + assertEq(aOFT.token(), address(aOFT)); + assertEq(bOFT.token(), address(bOFT)); + } + + function test_send_oft() public { + uint256 tokensToSend = 1 ether; + bytes memory options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(200000, 0); + SendParam memory sendParam = SendParam( + bEid, + addressToBytes32(userB), + tokensToSend, + tokensToSend, + options, + "", + "" + ); + MessagingFee memory fee = aOFT.quoteSend(sendParam, false); + + assertEq(aOFT.balanceOf(userA), initialBalance); + assertEq(bOFT.balanceOf(userB), initialBalance); + + vm.prank(userA); + aOFT.send{ value: fee.nativeFee }(sendParam, fee, payable(address(this))); + verifyPackets(bEid, addressToBytes32(address(bOFT))); + + assertEq(aOFT.balanceOf(userA), initialBalance - tokensToSend); + assertEq(bOFT.balanceOf(userB), initialBalance + tokensToSend); + } + + function test_send_oft_compose_msg() public { + uint256 tokensToSend = 1 ether; + + OFTComposerMock composer = new OFTComposerMock(); + + bytes memory options = OptionsBuilder + .newOptions() + .addExecutorLzReceiveOption(200000, 0) + .addExecutorLzComposeOption(0, 500000, 0); + bytes memory composeMsg = hex"1234"; + SendParam memory sendParam = SendParam( + bEid, + addressToBytes32(address(composer)), + tokensToSend, + tokensToSend, + options, + composeMsg, + "" + ); + MessagingFee memory fee = aOFT.quoteSend(sendParam, false); + + assertEq(aOFT.balanceOf(userA), initialBalance); + assertEq(bOFT.balanceOf(address(composer)), 0); + + vm.prank(userA); + (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) = aOFT.send{ value: fee.nativeFee }( + sendParam, + fee, + payable(address(this)) + ); + verifyPackets(bEid, addressToBytes32(address(bOFT))); + + // lzCompose params + uint32 dstEid_ = bEid; + address from_ = address(bOFT); + bytes memory options_ = options; + bytes32 guid_ = msgReceipt.guid; + address to_ = address(composer); + bytes memory composerMsg_ = OFTComposeMsgCodec.encode( + msgReceipt.nonce, + aEid, + oftReceipt.amountReceivedLD, + abi.encodePacked(addressToBytes32(userA), composeMsg) + ); + this.lzCompose(dstEid_, from_, options_, guid_, to_, composerMsg_); + + assertEq(aOFT.balanceOf(userA), initialBalance - tokensToSend); + assertEq(bOFT.balanceOf(address(composer)), tokensToSend); + + assertEq(composer.from(), from_); + assertEq(composer.guid(), guid_); + assertEq(composer.message(), composerMsg_); + assertEq(composer.executor(), address(this)); + assertEq(composer.extraData(), composerMsg_); // default to setting the extraData to the message as well to test + } + + // TODO import the rest of oft tests? +} diff --git a/examples/oft-composer-library/test/hardhat/MyOFT.test.ts b/examples/oft-composer-library/test/hardhat/MyOFT.test.ts new file mode 100644 index 000000000..257bc5218 --- /dev/null +++ b/examples/oft-composer-library/test/hardhat/MyOFT.test.ts @@ -0,0 +1,101 @@ +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { expect } from 'chai' +import { Contract, ContractFactory } from 'ethers' +import { deployments, ethers } from 'hardhat' + +import { Options } from '@layerzerolabs/lz-v2-utilities' + +describe('MyOFT Test', function () { + // Constant representing a mock Endpoint ID for testing purposes + const eidA = 1 + const eidB = 2 + // Declaration of variables to be used in the test suite + let MyOFT: ContractFactory + let EndpointV2Mock: ContractFactory + let ownerA: SignerWithAddress + let ownerB: SignerWithAddress + let endpointOwner: SignerWithAddress + let myOFTA: Contract + let myOFTB: Contract + let mockEndpointV2A: Contract + let mockEndpointV2B: Contract + + // Before hook for setup that runs once before all tests in the block + before(async function () { + // Contract factory for our tested contract + // + // We are using a derived contract that exposes a mint() function for testing purposes + MyOFT = await ethers.getContractFactory('MyOFTMock') + + // Fetching the first three signers (accounts) from Hardhat's local Ethereum network + const signers = await ethers.getSigners() + + ;[ownerA, ownerB, endpointOwner] = signers + + // The EndpointV2Mock contract comes from @layerzerolabs/test-devtools-evm-hardhat package + // and its artifacts are connected as external artifacts to this project + // + // Unfortunately, hardhat itself does not yet provide a way of connecting external artifacts, + // so we rely on hardhat-deploy to create a ContractFactory for EndpointV2Mock + // + // See https://github.com/NomicFoundation/hardhat/issues/1040 + const EndpointV2MockArtifact = await deployments.getArtifact('EndpointV2Mock') + EndpointV2Mock = new ContractFactory(EndpointV2MockArtifact.abi, EndpointV2MockArtifact.bytecode, endpointOwner) + }) + + // beforeEach hook for setup that runs before each test in the block + beforeEach(async function () { + // Deploying a mock LZEndpoint with the given Endpoint ID + mockEndpointV2A = await EndpointV2Mock.deploy(eidA) + mockEndpointV2B = await EndpointV2Mock.deploy(eidB) + + // Deploying two instances of MyOFT contract with different identifiers and linking them to the mock LZEndpoint + myOFTA = await MyOFT.deploy('aOFT', 'aOFT', mockEndpointV2A.address, ownerA.address) + myOFTB = await MyOFT.deploy('bOFT', 'bOFT', mockEndpointV2B.address, ownerB.address) + + // Setting destination endpoints in the LZEndpoint mock for each MyOFT instance + await mockEndpointV2A.setDestLzEndpoint(myOFTB.address, mockEndpointV2B.address) + await mockEndpointV2B.setDestLzEndpoint(myOFTA.address, mockEndpointV2A.address) + + // Setting each MyOFT instance as a peer of the other in the mock LZEndpoint + await myOFTA.connect(ownerA).setPeer(eidB, ethers.utils.zeroPad(myOFTB.address, 32)) + await myOFTB.connect(ownerB).setPeer(eidA, ethers.utils.zeroPad(myOFTA.address, 32)) + }) + + // A test case to verify token transfer functionality + it('should send a token from A address to B address via each OFT', async function () { + // Minting an initial amount of tokens to ownerA's address in the myOFTA contract + const initialAmount = ethers.utils.parseEther('100') + await myOFTA.mint(ownerA.address, initialAmount) + + // Defining the amount of tokens to send and constructing the parameters for the send operation + const tokensToSend = ethers.utils.parseEther('1') + + // Defining extra message execution options for the send operation + const options = Options.newOptions().addExecutorLzReceiveOption(200000, 0).toHex().toString() + + const sendParam = [ + eidB, + ethers.utils.zeroPad(ownerB.address, 32), + tokensToSend, + tokensToSend, + options, + '0x', + '0x', + ] + + // Fetching the native fee for the token send operation + const [nativeFee] = await myOFTA.quoteSend(sendParam, false) + + // Executing the send operation from myOFTA contract + await myOFTA.send(sendParam, [nativeFee, 0], ownerA.address, { value: nativeFee }) + + // Fetching the final token balances of ownerA and ownerB + const finalBalanceA = await myOFTA.balanceOf(ownerA.address) + const finalBalanceB = await myOFTB.balanceOf(ownerB.address) + + // Asserting that the final balances are as expected after the send operation + expect(finalBalanceA).eql(initialAmount.sub(tokensToSend)) + expect(finalBalanceB).eql(tokensToSend) + }) +}) diff --git a/examples/oft-composer-library/test/mocks/ERC20Mock.sol b/examples/oft-composer-library/test/mocks/ERC20Mock.sol new file mode 100644 index 000000000..6ce17e418 --- /dev/null +++ b/examples/oft-composer-library/test/mocks/ERC20Mock.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract ERC20Mock is ERC20 { + constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {} + + function mint(address _to, uint256 _amount) public { + _mint(_to, _amount); + } +} diff --git a/examples/oft-composer-library/test/mocks/OFTComposerMock.sol b/examples/oft-composer-library/test/mocks/OFTComposerMock.sol new file mode 100644 index 000000000..fdd5c2426 --- /dev/null +++ b/examples/oft-composer-library/test/mocks/OFTComposerMock.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import { IOAppComposer } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppComposer.sol"; + +contract OFTComposerMock is IOAppComposer { + // default empty values for testing a lzCompose received message + address public from; + bytes32 public guid; + bytes public message; + address public executor; + bytes public extraData; + + function lzCompose( + address _from, + bytes32 _guid, + bytes calldata _message, + address _executor, + bytes calldata /*_extraData*/ + ) external payable { + from = _from; + guid = _guid; + message = _message; + executor = _executor; + extraData = _message; + } +} diff --git a/examples/oft-composer-library/test/mocks/OFTMock.sol b/examples/oft-composer-library/test/mocks/OFTMock.sol new file mode 100644 index 000000000..cef8770f5 --- /dev/null +++ b/examples/oft-composer-library/test/mocks/OFTMock.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { OFT } from "@layerzerolabs/oft-evm/contracts/OFT.sol"; +import { SendParam } from "@layerzerolabs/oft-evm/contracts/OFTCore.sol"; + +contract OFTMock is OFT { + constructor( + string memory _name, + string memory _symbol, + address _lzEndpoint, + address _delegate + ) Ownable(_delegate) OFT(_name, _symbol, _lzEndpoint, _delegate) {} + + function mint(address _to, uint256 _amount) public { + _mint(_to, _amount); + } + + // @dev expose internal functions for testing purposes + function debit( + uint256 _amountToSendLD, + uint256 _minAmountToCreditLD, + uint32 _dstEid + ) public returns (uint256 amountDebitedLD, uint256 amountToCreditLD) { + return _debit(msg.sender, _amountToSendLD, _minAmountToCreditLD, _dstEid); + } + + function debitView( + uint256 _amountToSendLD, + uint256 _minAmountToCreditLD, + uint32 _dstEid + ) public view returns (uint256 amountDebitedLD, uint256 amountToCreditLD) { + return _debitView(_amountToSendLD, _minAmountToCreditLD, _dstEid); + } + + function removeDust(uint256 _amountLD) public view returns (uint256 amountLD) { + return _removeDust(_amountLD); + } + + function toLD(uint64 _amountSD) public view returns (uint256 amountLD) { + return _toLD(_amountSD); + } + + function toSD(uint256 _amountLD) public view returns (uint64 amountSD) { + return _toSD(_amountLD); + } + + function credit(address _to, uint256 _amountToCreditLD, uint32 _srcEid) public returns (uint256 amountReceivedLD) { + return _credit(_to, _amountToCreditLD, _srcEid); + } + + function buildMsgAndOptions( + SendParam calldata _sendParam, + uint256 _amountToCreditLD + ) public view returns (bytes memory message, bytes memory options) { + return _buildMsgAndOptions(_sendParam, _amountToCreditLD); + } +} diff --git a/examples/oft-composer-library/tsconfig.json b/examples/oft-composer-library/tsconfig.json new file mode 100644 index 000000000..027ad0f3f --- /dev/null +++ b/examples/oft-composer-library/tsconfig.json @@ -0,0 +1,13 @@ +{ + "exclude": ["node_modules"], + "include": ["deploy", "tasks", "test", "hardhat.config.ts"], + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true + } +} diff --git a/packages/oft-alt-evm/artifacts/IOFT.sol/IOFT.json b/packages/oft-alt-evm/artifacts/IOFT.sol/IOFT.json index 9f52ba02a..0c12bdaef 100644 --- a/packages/oft-alt-evm/artifacts/IOFT.sol/IOFT.json +++ b/packages/oft-alt-evm/artifacts/IOFT.sol/IOFT.json @@ -359,7 +359,7 @@ "sharedDecimals()": "857749b0", "token()": "fc0c546a" }, - "rawMetadata": "{\"compiler\":{\"version\":\"0.8.22+commit.4fc1097e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InvalidLocalDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"}],\"name\":\"SlippageExceeded\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"srcEid\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"name\":\"OFTReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"name\":\"OFTSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"approvalRequired\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oftVersion\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"},{\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"}],\"name\":\"quoteOFT\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxAmountLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTLimit\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"int256\",\"name\":\"feeAmountLD\",\"type\":\"int256\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"internalType\":\"struct OFTFeeDetail[]\",\"name\":\"oftFeeDetails\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTReceipt\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"_payInLzToken\",\"type\":\"bool\"}],\"name\":\"quoteSend\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"_fee\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"_refundAddress\",\"type\":\"address\"}],\"name\":\"send\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"fee\",\"type\":\"tuple\"}],\"internalType\":\"struct MessagingReceipt\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTReceipt\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sharedDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface for the OftChain (OFT) token.Does not inherit ERC20 to accommodate usage by OFTAdapter as well.This specific interface ID is '0x02e49c2c'.\",\"kind\":\"dev\",\"methods\":{\"approvalRequired()\":{\"details\":\"Allows things like wallet implementers to determine integration requirements, without understanding the underlying token implementation.\",\"returns\":{\"_0\":\"requiresApproval Needs approval of the underlying token implementation.\"}},\"oftVersion()\":{\"details\":\"interfaceId: This specific interface ID is '0x02e49c2c'.version: Indicates a cross-chain compatible msg encoding with other OFTs.If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented. ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)\",\"returns\":{\"interfaceId\":\"The interface ID.\",\"version\":\"The version.\"}},\"quoteOFT((uint32,bytes32,uint256,uint256,bytes,bytes,bytes))\":{\"params\":{\"_sendParam\":\"The parameters for the send operation.\"},\"returns\":{\"_0\":\"limit The OFT limit information.\",\"_2\":\"receipt The OFT receipt information.\",\"oftFeeDetails\":\"The details of OFT fees.\"}},\"quoteSend((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),bool)\":{\"details\":\"MessagingFee: LayerZero msg fee - nativeFee: The native fee. - lzTokenFee: The lzToken fee.\",\"params\":{\"_payInLzToken\":\"Flag indicating whether the caller is paying in the LZ token.\",\"_sendParam\":\"The parameters for the send() operation.\"},\"returns\":{\"_0\":\"fee The calculated LayerZero messaging fee from the send() operation.\"}},\"send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\":{\"details\":\"MessagingReceipt: LayerZero msg receipt - guid: The unique identifier for the sent message. - nonce: The nonce of the sent message. - fee: The LayerZero fee incurred for the message.\",\"params\":{\"_fee\":\"The fee information supplied by the caller. - nativeFee: The native fee. - lzTokenFee: The lzToken fee.\",\"_refundAddress\":\"The address to receive any excess funds from fees etc. on the src.\",\"_sendParam\":\"The parameters for the send operation.\"},\"returns\":{\"_0\":\"receipt The LayerZero messaging receipt from the send() operation.\",\"_1\":\"oftReceipt The OFT receipt information.\"}},\"sharedDecimals()\":{\"returns\":{\"_0\":\"sharedDecimals The shared decimals of the OFT.\"}},\"token()\":{\"returns\":{\"_0\":\"token The address of the ERC20 token implementation.\"}}},\"title\":\"IOFT\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"approvalRequired()\":{\"notice\":\"Indicates whether the OFT contract requires approval of the 'token()' to send.\"},\"oftVersion()\":{\"notice\":\"Retrieves interfaceID and the version of the OFT.\"},\"quoteOFT((uint32,bytes32,uint256,uint256,bytes,bytes,bytes))\":{\"notice\":\"Provides a quote for OFT-related operations.\"},\"quoteSend((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),bool)\":{\"notice\":\"Provides a quote for the send() operation.\"},\"send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\":{\"notice\":\"Executes the send() operation.\"},\"sharedDecimals()\":{\"notice\":\"Retrieves the shared decimals of the OFT.\"},\"token()\":{\"notice\":\"Retrieves the address of the token associated with the OFT.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"node_modules/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":\"IOFT\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":20000},\"remappings\":[\":@layerzerolabs/=node_modules/@layerzerolabs/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":ds-test/=node_modules/@layerzerolabs/toolbox-foundry/lib/ds-test/\",\":forge-std/=node_modules/@layerzerolabs/toolbox-foundry/lib/forge-std/\",\":solidity-bytes-utils/contracts/=node_modules/@layerzerolabs/toolbox-foundry/lib/solidity-bytes-utils/\"]},\"sources\":{\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\":{\"keccak256\":\"0xf7f941bee89ea6369950fe54e8ac476ae6478b958b20fc0e8a83e8ff1364eac3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bacc29fd3866af71e59cb0bdc1cf82c882a4a7f4e2652fd413c9f12649762083\",\"dweb:/ipfs/QmZh2toLnrQDWaNYhS5K4NoW7Vxd2GdZx9KA77vKEDLAqs\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol\":{\"keccak256\":\"0x919b37133adff4dc528e3061deb2789c3149971b530c61e556fb3d09ab315dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d8ff6a8a89297fa127f86b54e0db3eba1d6a6eeb4f6398d3c84d569665ac8f1b\",\"dweb:/ipfs/QmVSwhw6xFDrLRAX4RXaCM47yBaBtac4wf36DYEq6KCTvT\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol\":{\"keccak256\":\"0x0878f64dffebf58c4165569416372f40860fab546b88cd926eba0d5cb6d8d972\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7e1b245d58221d16d8b5e0f01ef3e289a24a7df1ace3b94239e4d5b954ad5927\",\"dweb:/ipfs/Qmappsgp7PCY9rSSNE9Cdn4BTRX591WfCSEgq2HxhA3z6S\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol\":{\"keccak256\":\"0x85bc7090134529ec474866dc4bb1c48692d518c756eb0a961c82574829c51901\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b18b23a1643fc6636c4ad9d9023e2e6ca2d3c2a4a046482d4655bff09950598d\",\"dweb:/ipfs/Qma6G5SqiovwrMPfgqTrRngK1HWW373Wkf9c6YP2NhXpPk\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol\":{\"keccak256\":\"0xff0c546c2813dae3e440882f46b377375f7461b0714efd80bd3f0c6e5cb8da4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5173fc9143bea314b159ca5a9adb5626659ef763bc598e27de5fa46efe3291a6\",\"dweb:/ipfs/QmSLFeMFPmVeGxT4sxRPW28ictjAS22M8rLeYRu9TXkA6D\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol\":{\"keccak256\":\"0x13a9c2d1d2c1f086b8624f2e84c4a4702212daae36f701d92bb915b535cbe4cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://606515dd9193551bd2c94ac8c304f3776fafcc70e544ebf441f334658b2fd5f0\",\"dweb:/ipfs/QmZ88ey7DdZqV5taAoebabvszX5kdPMSrQCAmTteVdDtcH\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol\":{\"keccak256\":\"0x518cf4adca601923ed4baa6619846a253ea32b8d8775f8bc1faa3dfac7f67c20\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d42b471418efadcc3577ef3fa9f8f504e8bed7db90c3b0c862038d8b29529eb2\",\"dweb:/ipfs/QmZETDQiJN4U92fmLKo8T9ZbdDf7BNBUUvo9H7M7GqAyFU\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol\":{\"keccak256\":\"0x40e49f2de74506e1da5dcaed53a39853f691647f4ceb0fccc8f49a68d3f47c58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4a1deb2a6a3eb1fb83936c9578469142bff470295f403d7d07d955a76be3adbd\",\"dweb:/ipfs/QmS9bjSfBaE4YhQ1PCQ1TknbEPbNfRXzBK9E7SaPGyiZEv\"]},\"node_modules/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":{\"keccak256\":\"0x278e7bdeb2e8aa3f528373d8a3b3fedfe2e1bec050bcaf95065a136645cf56bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://43d1789ca4f5cd81986bb52682a94caf188dc8910ecd84cf98bc59221847bd12\",\"dweb:/ipfs/QmSmvKyCukcqxCUvdvNQNyshp4nYt2xxiFaB7Uji4YSrBv\"]},\"node_modules/@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC1363.sol\":{\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://da62d6be1f5c6edf577f0cb45666a8aa9c2086a4bac87d95d65f02e2f4c36a4b\",\"dweb:/ipfs/QmNkpvBpoCMvX8JwAFNSc5XxJ2q5BXJpL5L1txb4QkqVFF\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11fea9f8bc98949ac6709f0c1699db7430d2948137aa94d5a9e95a91f61a710a\",\"dweb:/ipfs/QmQdfRXxQjwP6yn3DVo1GHPpriKNcFghSPi94Z1oKEFUNS\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC20.sol\":{\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a2608291cb038b388d80b79a06b6118a42f7894ff67b7da10ec0dbbf5b2973ba\",\"dweb:/ipfs/QmWohqcBLbcxmA4eGPhZDXe5RYMMEEpFq22nfkaUMvTfw1\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db\",\"dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0xca2ae13e0610f6a99238dd00b97bd786bc92732dae6d6b9d61f573ec51018310\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://75f8c71ce0c91c40dd5f249ace0b7d8270f8f1767231bcf71490f7157d6ba862\",\"dweb:/ipfs/QmYXgxeDyFHvz3JsXxLEYN6GNUR44ThHeFj5XkpkgMoG4w\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0x9d8da059267bac779a2dbbb9a26c2acf00ca83085e105d62d5d4ef96054a47f5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c78e2aa4313323cecd1ef12a8d6265b96beee1a199923abf55d9a2a9e291ad23\",\"dweb:/ipfs/QmUTs2KStXucZezzFo3EYeqYu47utu56qrF7jj1Gue65vb\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"node_modules/@openzeppelin/contracts/utils/Errors.sol\":{\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ba1d02f4847670a1b83dec9f7d37f0b0418d6043447b69f3a29a5f9efc547fcf\",\"dweb:/ipfs/QmQ7iH2keLNUKgq2xSWcRmuBE5eZ3F5whYAkAGzCNNoEWB\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f6fda447a62815e8064f47eff0dd1cf58d9207ad69b5d32280f8d7ed1d1e4621\",\"dweb:/ipfs/QmfDRc7pxfaXB2Dh9np5Uf29Na3pQ7tafRS684wd3GLjVL\"]}},\"version\":1}", + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.22+commit.4fc1097e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InvalidLocalDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"}],\"name\":\"SlippageExceeded\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"srcEid\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"name\":\"OFTReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"name\":\"OFTSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"approvalRequired\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oftVersion\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"},{\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"}],\"name\":\"quoteOFT\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxAmountLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTLimit\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"int256\",\"name\":\"feeAmountLD\",\"type\":\"int256\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"internalType\":\"struct OFTFeeDetail[]\",\"name\":\"oftFeeDetails\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTReceipt\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"_payInLzToken\",\"type\":\"bool\"}],\"name\":\"quoteSend\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"_fee\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"_refundAddress\",\"type\":\"address\"}],\"name\":\"send\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"fee\",\"type\":\"tuple\"}],\"internalType\":\"struct MessagingReceipt\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTReceipt\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sharedDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface for the OftChain (OFT) token.Does not inherit ERC20 to accommodate usage by OFTAdapter as well.This specific interface ID is '0x02e49c2c'.\",\"kind\":\"dev\",\"methods\":{\"approvalRequired()\":{\"details\":\"Allows things like wallet implementers to determine integration requirements, without understanding the underlying token implementation.\",\"returns\":{\"_0\":\"requiresApproval Needs approval of the underlying token implementation.\"}},\"oftVersion()\":{\"details\":\"interfaceId: This specific interface ID is '0x02e49c2c'.version: Indicates a cross-chain compatible msg encoding with other OFTs.If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented. ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)\",\"returns\":{\"interfaceId\":\"The interface ID.\",\"version\":\"The version.\"}},\"quoteOFT((uint32,bytes32,uint256,uint256,bytes,bytes,bytes))\":{\"params\":{\"_sendParam\":\"The parameters for the send operation.\"},\"returns\":{\"_0\":\"limit The OFT limit information.\",\"_2\":\"receipt The OFT receipt information.\",\"oftFeeDetails\":\"The details of OFT fees.\"}},\"quoteSend((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),bool)\":{\"details\":\"MessagingFee: LayerZero msg fee - nativeFee: The native fee. - lzTokenFee: The lzToken fee.\",\"params\":{\"_payInLzToken\":\"Flag indicating whether the caller is paying in the LZ token.\",\"_sendParam\":\"The parameters for the send() operation.\"},\"returns\":{\"_0\":\"fee The calculated LayerZero messaging fee from the send() operation.\"}},\"send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\":{\"details\":\"MessagingReceipt: LayerZero msg receipt - guid: The unique identifier for the sent message. - nonce: The nonce of the sent message. - fee: The LayerZero fee incurred for the message.\",\"params\":{\"_fee\":\"The fee information supplied by the caller. - nativeFee: The native fee. - lzTokenFee: The lzToken fee.\",\"_refundAddress\":\"The address to receive any excess funds from fees etc. on the src.\",\"_sendParam\":\"The parameters for the send operation.\"},\"returns\":{\"_0\":\"receipt The LayerZero messaging receipt from the send() operation.\",\"_1\":\"oftReceipt The OFT receipt information.\"}},\"sharedDecimals()\":{\"returns\":{\"_0\":\"sharedDecimals The shared decimals of the OFT.\"}},\"token()\":{\"returns\":{\"_0\":\"token The address of the ERC20 token implementation.\"}}},\"title\":\"IOFT\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"approvalRequired()\":{\"notice\":\"Indicates whether the OFT contract requires approval of the 'token()' to send.\"},\"oftVersion()\":{\"notice\":\"Retrieves interfaceID and the version of the OFT.\"},\"quoteOFT((uint32,bytes32,uint256,uint256,bytes,bytes,bytes))\":{\"notice\":\"Provides the fee breakdown and settings data for an OFT. Unused in the default implementation.\"},\"quoteSend((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),bool)\":{\"notice\":\"Provides a quote for the send() operation.\"},\"send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\":{\"notice\":\"Executes the send() operation.\"},\"sharedDecimals()\":{\"notice\":\"Retrieves the shared decimals of the OFT.\"},\"token()\":{\"notice\":\"Retrieves the address of the token associated with the OFT.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"node_modules/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":\"IOFT\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":20000},\"remappings\":[\":@layerzerolabs/=node_modules/@layerzerolabs/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":ds-test/=node_modules/@layerzerolabs/toolbox-foundry/lib/ds-test/\",\":forge-std/=node_modules/@layerzerolabs/toolbox-foundry/lib/forge-std/\",\":solidity-bytes-utils/contracts/=node_modules/@layerzerolabs/toolbox-foundry/lib/solidity-bytes-utils/\"]},\"sources\":{\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\":{\"keccak256\":\"0xf7f941bee89ea6369950fe54e8ac476ae6478b958b20fc0e8a83e8ff1364eac3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bacc29fd3866af71e59cb0bdc1cf82c882a4a7f4e2652fd413c9f12649762083\",\"dweb:/ipfs/QmZh2toLnrQDWaNYhS5K4NoW7Vxd2GdZx9KA77vKEDLAqs\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol\":{\"keccak256\":\"0x919b37133adff4dc528e3061deb2789c3149971b530c61e556fb3d09ab315dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d8ff6a8a89297fa127f86b54e0db3eba1d6a6eeb4f6398d3c84d569665ac8f1b\",\"dweb:/ipfs/QmVSwhw6xFDrLRAX4RXaCM47yBaBtac4wf36DYEq6KCTvT\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol\":{\"keccak256\":\"0x0878f64dffebf58c4165569416372f40860fab546b88cd926eba0d5cb6d8d972\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7e1b245d58221d16d8b5e0f01ef3e289a24a7df1ace3b94239e4d5b954ad5927\",\"dweb:/ipfs/Qmappsgp7PCY9rSSNE9Cdn4BTRX591WfCSEgq2HxhA3z6S\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol\":{\"keccak256\":\"0x85bc7090134529ec474866dc4bb1c48692d518c756eb0a961c82574829c51901\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b18b23a1643fc6636c4ad9d9023e2e6ca2d3c2a4a046482d4655bff09950598d\",\"dweb:/ipfs/Qma6G5SqiovwrMPfgqTrRngK1HWW373Wkf9c6YP2NhXpPk\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol\":{\"keccak256\":\"0xff0c546c2813dae3e440882f46b377375f7461b0714efd80bd3f0c6e5cb8da4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5173fc9143bea314b159ca5a9adb5626659ef763bc598e27de5fa46efe3291a6\",\"dweb:/ipfs/QmSLFeMFPmVeGxT4sxRPW28ictjAS22M8rLeYRu9TXkA6D\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol\":{\"keccak256\":\"0x13a9c2d1d2c1f086b8624f2e84c4a4702212daae36f701d92bb915b535cbe4cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://606515dd9193551bd2c94ac8c304f3776fafcc70e544ebf441f334658b2fd5f0\",\"dweb:/ipfs/QmZ88ey7DdZqV5taAoebabvszX5kdPMSrQCAmTteVdDtcH\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol\":{\"keccak256\":\"0x518cf4adca601923ed4baa6619846a253ea32b8d8775f8bc1faa3dfac7f67c20\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d42b471418efadcc3577ef3fa9f8f504e8bed7db90c3b0c862038d8b29529eb2\",\"dweb:/ipfs/QmZETDQiJN4U92fmLKo8T9ZbdDf7BNBUUvo9H7M7GqAyFU\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol\":{\"keccak256\":\"0x40e49f2de74506e1da5dcaed53a39853f691647f4ceb0fccc8f49a68d3f47c58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4a1deb2a6a3eb1fb83936c9578469142bff470295f403d7d07d955a76be3adbd\",\"dweb:/ipfs/QmS9bjSfBaE4YhQ1PCQ1TknbEPbNfRXzBK9E7SaPGyiZEv\"]},\"node_modules/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":{\"keccak256\":\"0x7ba6bb62fba7ee83451cfb0e727ddeef0e96b4388bd4e9ff0fc6ce103e1101c8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cfbd447f2e8a730bd46a14c3c3e6a0b2bf7446145579603a9793ba5ac1dd38b4\",\"dweb:/ipfs/QmZ4nx4iGrFmBHvYFgki5TXFdCHz4Co38hgdgwpRaM7NLs\"]},\"node_modules/@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC1363.sol\":{\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://da62d6be1f5c6edf577f0cb45666a8aa9c2086a4bac87d95d65f02e2f4c36a4b\",\"dweb:/ipfs/QmNkpvBpoCMvX8JwAFNSc5XxJ2q5BXJpL5L1txb4QkqVFF\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11fea9f8bc98949ac6709f0c1699db7430d2948137aa94d5a9e95a91f61a710a\",\"dweb:/ipfs/QmQdfRXxQjwP6yn3DVo1GHPpriKNcFghSPi94Z1oKEFUNS\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC20.sol\":{\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a2608291cb038b388d80b79a06b6118a42f7894ff67b7da10ec0dbbf5b2973ba\",\"dweb:/ipfs/QmWohqcBLbcxmA4eGPhZDXe5RYMMEEpFq22nfkaUMvTfw1\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db\",\"dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0xca2ae13e0610f6a99238dd00b97bd786bc92732dae6d6b9d61f573ec51018310\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://75f8c71ce0c91c40dd5f249ace0b7d8270f8f1767231bcf71490f7157d6ba862\",\"dweb:/ipfs/QmYXgxeDyFHvz3JsXxLEYN6GNUR44ThHeFj5XkpkgMoG4w\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0x9d8da059267bac779a2dbbb9a26c2acf00ca83085e105d62d5d4ef96054a47f5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c78e2aa4313323cecd1ef12a8d6265b96beee1a199923abf55d9a2a9e291ad23\",\"dweb:/ipfs/QmUTs2KStXucZezzFo3EYeqYu47utu56qrF7jj1Gue65vb\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"node_modules/@openzeppelin/contracts/utils/Errors.sol\":{\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ba1d02f4847670a1b83dec9f7d37f0b0418d6043447b69f3a29a5f9efc547fcf\",\"dweb:/ipfs/QmQ7iH2keLNUKgq2xSWcRmuBE5eZ3F5whYAkAGzCNNoEWB\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f6fda447a62815e8064f47eff0dd1cf58d9207ad69b5d32280f8d7ed1d1e4621\",\"dweb:/ipfs/QmfDRc7pxfaXB2Dh9np5Uf29Na3pQ7tafRS684wd3GLjVL\"]}},\"version\":1}", "metadata": { "compiler": { "version": "0.8.22+commit.4fc1097e" }, "language": "Solidity", @@ -826,7 +826,7 @@ "notice": "Retrieves interfaceID and the version of the OFT." }, "quoteOFT((uint32,bytes32,uint256,uint256,bytes,bytes,bytes))": { - "notice": "Provides a quote for OFT-related operations." + "notice": "Provides the fee breakdown and settings data for an OFT. Unused in the default implementation." }, "quoteSend((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),bool)": { "notice": "Provides a quote for the send() operation." @@ -926,10 +926,10 @@ "license": "MIT" }, "node_modules/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol": { - "keccak256": "0x278e7bdeb2e8aa3f528373d8a3b3fedfe2e1bec050bcaf95065a136645cf56bb", + "keccak256": "0x7ba6bb62fba7ee83451cfb0e727ddeef0e96b4388bd4e9ff0fc6ce103e1101c8", "urls": [ - "bzz-raw://43d1789ca4f5cd81986bb52682a94caf188dc8910ecd84cf98bc59221847bd12", - "dweb:/ipfs/QmSmvKyCukcqxCUvdvNQNyshp4nYt2xxiFaB7Uji4YSrBv" + "bzz-raw://cfbd447f2e8a730bd46a14c3c3e6a0b2bf7446145579603a9793ba5ac1dd38b4", + "dweb:/ipfs/QmZ4nx4iGrFmBHvYFgki5TXFdCHz4Co38hgdgwpRaM7NLs" ], "license": "MIT" }, From e95cd881a755a030974f2fcd1b964094ed82b7fa Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Wed, 11 Dec 2024 11:13:13 -0800 Subject: [PATCH 02/47] fix: remove artifact changes --- packages/oft-alt-evm/artifacts/IOFT.sol/IOFT.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/oft-alt-evm/artifacts/IOFT.sol/IOFT.json b/packages/oft-alt-evm/artifacts/IOFT.sol/IOFT.json index 0c12bdaef..9f52ba02a 100644 --- a/packages/oft-alt-evm/artifacts/IOFT.sol/IOFT.json +++ b/packages/oft-alt-evm/artifacts/IOFT.sol/IOFT.json @@ -359,7 +359,7 @@ "sharedDecimals()": "857749b0", "token()": "fc0c546a" }, - "rawMetadata": "{\"compiler\":{\"version\":\"0.8.22+commit.4fc1097e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InvalidLocalDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"}],\"name\":\"SlippageExceeded\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"srcEid\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"name\":\"OFTReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"name\":\"OFTSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"approvalRequired\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oftVersion\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"},{\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"}],\"name\":\"quoteOFT\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxAmountLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTLimit\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"int256\",\"name\":\"feeAmountLD\",\"type\":\"int256\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"internalType\":\"struct OFTFeeDetail[]\",\"name\":\"oftFeeDetails\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTReceipt\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"_payInLzToken\",\"type\":\"bool\"}],\"name\":\"quoteSend\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"_fee\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"_refundAddress\",\"type\":\"address\"}],\"name\":\"send\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"fee\",\"type\":\"tuple\"}],\"internalType\":\"struct MessagingReceipt\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTReceipt\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sharedDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface for the OftChain (OFT) token.Does not inherit ERC20 to accommodate usage by OFTAdapter as well.This specific interface ID is '0x02e49c2c'.\",\"kind\":\"dev\",\"methods\":{\"approvalRequired()\":{\"details\":\"Allows things like wallet implementers to determine integration requirements, without understanding the underlying token implementation.\",\"returns\":{\"_0\":\"requiresApproval Needs approval of the underlying token implementation.\"}},\"oftVersion()\":{\"details\":\"interfaceId: This specific interface ID is '0x02e49c2c'.version: Indicates a cross-chain compatible msg encoding with other OFTs.If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented. ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)\",\"returns\":{\"interfaceId\":\"The interface ID.\",\"version\":\"The version.\"}},\"quoteOFT((uint32,bytes32,uint256,uint256,bytes,bytes,bytes))\":{\"params\":{\"_sendParam\":\"The parameters for the send operation.\"},\"returns\":{\"_0\":\"limit The OFT limit information.\",\"_2\":\"receipt The OFT receipt information.\",\"oftFeeDetails\":\"The details of OFT fees.\"}},\"quoteSend((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),bool)\":{\"details\":\"MessagingFee: LayerZero msg fee - nativeFee: The native fee. - lzTokenFee: The lzToken fee.\",\"params\":{\"_payInLzToken\":\"Flag indicating whether the caller is paying in the LZ token.\",\"_sendParam\":\"The parameters for the send() operation.\"},\"returns\":{\"_0\":\"fee The calculated LayerZero messaging fee from the send() operation.\"}},\"send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\":{\"details\":\"MessagingReceipt: LayerZero msg receipt - guid: The unique identifier for the sent message. - nonce: The nonce of the sent message. - fee: The LayerZero fee incurred for the message.\",\"params\":{\"_fee\":\"The fee information supplied by the caller. - nativeFee: The native fee. - lzTokenFee: The lzToken fee.\",\"_refundAddress\":\"The address to receive any excess funds from fees etc. on the src.\",\"_sendParam\":\"The parameters for the send operation.\"},\"returns\":{\"_0\":\"receipt The LayerZero messaging receipt from the send() operation.\",\"_1\":\"oftReceipt The OFT receipt information.\"}},\"sharedDecimals()\":{\"returns\":{\"_0\":\"sharedDecimals The shared decimals of the OFT.\"}},\"token()\":{\"returns\":{\"_0\":\"token The address of the ERC20 token implementation.\"}}},\"title\":\"IOFT\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"approvalRequired()\":{\"notice\":\"Indicates whether the OFT contract requires approval of the 'token()' to send.\"},\"oftVersion()\":{\"notice\":\"Retrieves interfaceID and the version of the OFT.\"},\"quoteOFT((uint32,bytes32,uint256,uint256,bytes,bytes,bytes))\":{\"notice\":\"Provides the fee breakdown and settings data for an OFT. Unused in the default implementation.\"},\"quoteSend((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),bool)\":{\"notice\":\"Provides a quote for the send() operation.\"},\"send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\":{\"notice\":\"Executes the send() operation.\"},\"sharedDecimals()\":{\"notice\":\"Retrieves the shared decimals of the OFT.\"},\"token()\":{\"notice\":\"Retrieves the address of the token associated with the OFT.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"node_modules/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":\"IOFT\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":20000},\"remappings\":[\":@layerzerolabs/=node_modules/@layerzerolabs/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":ds-test/=node_modules/@layerzerolabs/toolbox-foundry/lib/ds-test/\",\":forge-std/=node_modules/@layerzerolabs/toolbox-foundry/lib/forge-std/\",\":solidity-bytes-utils/contracts/=node_modules/@layerzerolabs/toolbox-foundry/lib/solidity-bytes-utils/\"]},\"sources\":{\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\":{\"keccak256\":\"0xf7f941bee89ea6369950fe54e8ac476ae6478b958b20fc0e8a83e8ff1364eac3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bacc29fd3866af71e59cb0bdc1cf82c882a4a7f4e2652fd413c9f12649762083\",\"dweb:/ipfs/QmZh2toLnrQDWaNYhS5K4NoW7Vxd2GdZx9KA77vKEDLAqs\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol\":{\"keccak256\":\"0x919b37133adff4dc528e3061deb2789c3149971b530c61e556fb3d09ab315dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d8ff6a8a89297fa127f86b54e0db3eba1d6a6eeb4f6398d3c84d569665ac8f1b\",\"dweb:/ipfs/QmVSwhw6xFDrLRAX4RXaCM47yBaBtac4wf36DYEq6KCTvT\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol\":{\"keccak256\":\"0x0878f64dffebf58c4165569416372f40860fab546b88cd926eba0d5cb6d8d972\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7e1b245d58221d16d8b5e0f01ef3e289a24a7df1ace3b94239e4d5b954ad5927\",\"dweb:/ipfs/Qmappsgp7PCY9rSSNE9Cdn4BTRX591WfCSEgq2HxhA3z6S\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol\":{\"keccak256\":\"0x85bc7090134529ec474866dc4bb1c48692d518c756eb0a961c82574829c51901\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b18b23a1643fc6636c4ad9d9023e2e6ca2d3c2a4a046482d4655bff09950598d\",\"dweb:/ipfs/Qma6G5SqiovwrMPfgqTrRngK1HWW373Wkf9c6YP2NhXpPk\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol\":{\"keccak256\":\"0xff0c546c2813dae3e440882f46b377375f7461b0714efd80bd3f0c6e5cb8da4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5173fc9143bea314b159ca5a9adb5626659ef763bc598e27de5fa46efe3291a6\",\"dweb:/ipfs/QmSLFeMFPmVeGxT4sxRPW28ictjAS22M8rLeYRu9TXkA6D\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol\":{\"keccak256\":\"0x13a9c2d1d2c1f086b8624f2e84c4a4702212daae36f701d92bb915b535cbe4cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://606515dd9193551bd2c94ac8c304f3776fafcc70e544ebf441f334658b2fd5f0\",\"dweb:/ipfs/QmZ88ey7DdZqV5taAoebabvszX5kdPMSrQCAmTteVdDtcH\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol\":{\"keccak256\":\"0x518cf4adca601923ed4baa6619846a253ea32b8d8775f8bc1faa3dfac7f67c20\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d42b471418efadcc3577ef3fa9f8f504e8bed7db90c3b0c862038d8b29529eb2\",\"dweb:/ipfs/QmZETDQiJN4U92fmLKo8T9ZbdDf7BNBUUvo9H7M7GqAyFU\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol\":{\"keccak256\":\"0x40e49f2de74506e1da5dcaed53a39853f691647f4ceb0fccc8f49a68d3f47c58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4a1deb2a6a3eb1fb83936c9578469142bff470295f403d7d07d955a76be3adbd\",\"dweb:/ipfs/QmS9bjSfBaE4YhQ1PCQ1TknbEPbNfRXzBK9E7SaPGyiZEv\"]},\"node_modules/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":{\"keccak256\":\"0x7ba6bb62fba7ee83451cfb0e727ddeef0e96b4388bd4e9ff0fc6ce103e1101c8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cfbd447f2e8a730bd46a14c3c3e6a0b2bf7446145579603a9793ba5ac1dd38b4\",\"dweb:/ipfs/QmZ4nx4iGrFmBHvYFgki5TXFdCHz4Co38hgdgwpRaM7NLs\"]},\"node_modules/@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC1363.sol\":{\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://da62d6be1f5c6edf577f0cb45666a8aa9c2086a4bac87d95d65f02e2f4c36a4b\",\"dweb:/ipfs/QmNkpvBpoCMvX8JwAFNSc5XxJ2q5BXJpL5L1txb4QkqVFF\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11fea9f8bc98949ac6709f0c1699db7430d2948137aa94d5a9e95a91f61a710a\",\"dweb:/ipfs/QmQdfRXxQjwP6yn3DVo1GHPpriKNcFghSPi94Z1oKEFUNS\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC20.sol\":{\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a2608291cb038b388d80b79a06b6118a42f7894ff67b7da10ec0dbbf5b2973ba\",\"dweb:/ipfs/QmWohqcBLbcxmA4eGPhZDXe5RYMMEEpFq22nfkaUMvTfw1\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db\",\"dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0xca2ae13e0610f6a99238dd00b97bd786bc92732dae6d6b9d61f573ec51018310\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://75f8c71ce0c91c40dd5f249ace0b7d8270f8f1767231bcf71490f7157d6ba862\",\"dweb:/ipfs/QmYXgxeDyFHvz3JsXxLEYN6GNUR44ThHeFj5XkpkgMoG4w\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0x9d8da059267bac779a2dbbb9a26c2acf00ca83085e105d62d5d4ef96054a47f5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c78e2aa4313323cecd1ef12a8d6265b96beee1a199923abf55d9a2a9e291ad23\",\"dweb:/ipfs/QmUTs2KStXucZezzFo3EYeqYu47utu56qrF7jj1Gue65vb\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"node_modules/@openzeppelin/contracts/utils/Errors.sol\":{\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ba1d02f4847670a1b83dec9f7d37f0b0418d6043447b69f3a29a5f9efc547fcf\",\"dweb:/ipfs/QmQ7iH2keLNUKgq2xSWcRmuBE5eZ3F5whYAkAGzCNNoEWB\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f6fda447a62815e8064f47eff0dd1cf58d9207ad69b5d32280f8d7ed1d1e4621\",\"dweb:/ipfs/QmfDRc7pxfaXB2Dh9np5Uf29Na3pQ7tafRS684wd3GLjVL\"]}},\"version\":1}", + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.22+commit.4fc1097e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InvalidLocalDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"}],\"name\":\"SlippageExceeded\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"srcEid\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"name\":\"OFTReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"name\":\"OFTSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"approvalRequired\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oftVersion\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"},{\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"}],\"name\":\"quoteOFT\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxAmountLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTLimit\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"int256\",\"name\":\"feeAmountLD\",\"type\":\"int256\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"internalType\":\"struct OFTFeeDetail[]\",\"name\":\"oftFeeDetails\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTReceipt\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"_payInLzToken\",\"type\":\"bool\"}],\"name\":\"quoteSend\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct SendParam\",\"name\":\"_sendParam\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"_fee\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"_refundAddress\",\"type\":\"address\"}],\"name\":\"send\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"guid\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct MessagingFee\",\"name\":\"fee\",\"type\":\"tuple\"}],\"internalType\":\"struct MessagingReceipt\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountSentLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountReceivedLD\",\"type\":\"uint256\"}],\"internalType\":\"struct OFTReceipt\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sharedDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Interface for the OftChain (OFT) token.Does not inherit ERC20 to accommodate usage by OFTAdapter as well.This specific interface ID is '0x02e49c2c'.\",\"kind\":\"dev\",\"methods\":{\"approvalRequired()\":{\"details\":\"Allows things like wallet implementers to determine integration requirements, without understanding the underlying token implementation.\",\"returns\":{\"_0\":\"requiresApproval Needs approval of the underlying token implementation.\"}},\"oftVersion()\":{\"details\":\"interfaceId: This specific interface ID is '0x02e49c2c'.version: Indicates a cross-chain compatible msg encoding with other OFTs.If a new feature is added to the OFT cross-chain msg encoding, the version will be incremented. ie. localOFT version(x,1) CAN send messages to remoteOFT version(x,1)\",\"returns\":{\"interfaceId\":\"The interface ID.\",\"version\":\"The version.\"}},\"quoteOFT((uint32,bytes32,uint256,uint256,bytes,bytes,bytes))\":{\"params\":{\"_sendParam\":\"The parameters for the send operation.\"},\"returns\":{\"_0\":\"limit The OFT limit information.\",\"_2\":\"receipt The OFT receipt information.\",\"oftFeeDetails\":\"The details of OFT fees.\"}},\"quoteSend((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),bool)\":{\"details\":\"MessagingFee: LayerZero msg fee - nativeFee: The native fee. - lzTokenFee: The lzToken fee.\",\"params\":{\"_payInLzToken\":\"Flag indicating whether the caller is paying in the LZ token.\",\"_sendParam\":\"The parameters for the send() operation.\"},\"returns\":{\"_0\":\"fee The calculated LayerZero messaging fee from the send() operation.\"}},\"send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\":{\"details\":\"MessagingReceipt: LayerZero msg receipt - guid: The unique identifier for the sent message. - nonce: The nonce of the sent message. - fee: The LayerZero fee incurred for the message.\",\"params\":{\"_fee\":\"The fee information supplied by the caller. - nativeFee: The native fee. - lzTokenFee: The lzToken fee.\",\"_refundAddress\":\"The address to receive any excess funds from fees etc. on the src.\",\"_sendParam\":\"The parameters for the send operation.\"},\"returns\":{\"_0\":\"receipt The LayerZero messaging receipt from the send() operation.\",\"_1\":\"oftReceipt The OFT receipt information.\"}},\"sharedDecimals()\":{\"returns\":{\"_0\":\"sharedDecimals The shared decimals of the OFT.\"}},\"token()\":{\"returns\":{\"_0\":\"token The address of the ERC20 token implementation.\"}}},\"title\":\"IOFT\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"approvalRequired()\":{\"notice\":\"Indicates whether the OFT contract requires approval of the 'token()' to send.\"},\"oftVersion()\":{\"notice\":\"Retrieves interfaceID and the version of the OFT.\"},\"quoteOFT((uint32,bytes32,uint256,uint256,bytes,bytes,bytes))\":{\"notice\":\"Provides a quote for OFT-related operations.\"},\"quoteSend((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),bool)\":{\"notice\":\"Provides a quote for the send() operation.\"},\"send((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),(uint256,uint256),address)\":{\"notice\":\"Executes the send() operation.\"},\"sharedDecimals()\":{\"notice\":\"Retrieves the shared decimals of the OFT.\"},\"token()\":{\"notice\":\"Retrieves the address of the token associated with the OFT.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"node_modules/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":\"IOFT\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":20000},\"remappings\":[\":@layerzerolabs/=node_modules/@layerzerolabs/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":ds-test/=node_modules/@layerzerolabs/toolbox-foundry/lib/ds-test/\",\":forge-std/=node_modules/@layerzerolabs/toolbox-foundry/lib/forge-std/\",\":solidity-bytes-utils/contracts/=node_modules/@layerzerolabs/toolbox-foundry/lib/solidity-bytes-utils/\"]},\"sources\":{\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol\":{\"keccak256\":\"0xf7f941bee89ea6369950fe54e8ac476ae6478b958b20fc0e8a83e8ff1364eac3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bacc29fd3866af71e59cb0bdc1cf82c882a4a7f4e2652fd413c9f12649762083\",\"dweb:/ipfs/QmZh2toLnrQDWaNYhS5K4NoW7Vxd2GdZx9KA77vKEDLAqs\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol\":{\"keccak256\":\"0x919b37133adff4dc528e3061deb2789c3149971b530c61e556fb3d09ab315dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d8ff6a8a89297fa127f86b54e0db3eba1d6a6eeb4f6398d3c84d569665ac8f1b\",\"dweb:/ipfs/QmVSwhw6xFDrLRAX4RXaCM47yBaBtac4wf36DYEq6KCTvT\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingChannel.sol\":{\"keccak256\":\"0x0878f64dffebf58c4165569416372f40860fab546b88cd926eba0d5cb6d8d972\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7e1b245d58221d16d8b5e0f01ef3e289a24a7df1ace3b94239e4d5b954ad5927\",\"dweb:/ipfs/Qmappsgp7PCY9rSSNE9Cdn4BTRX591WfCSEgq2HxhA3z6S\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingComposer.sol\":{\"keccak256\":\"0x85bc7090134529ec474866dc4bb1c48692d518c756eb0a961c82574829c51901\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b18b23a1643fc6636c4ad9d9023e2e6ca2d3c2a4a046482d4655bff09950598d\",\"dweb:/ipfs/Qma6G5SqiovwrMPfgqTrRngK1HWW373Wkf9c6YP2NhXpPk\"]},\"node_modules/@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessagingContext.sol\":{\"keccak256\":\"0xff0c546c2813dae3e440882f46b377375f7461b0714efd80bd3f0c6e5cb8da4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5173fc9143bea314b159ca5a9adb5626659ef763bc598e27de5fa46efe3291a6\",\"dweb:/ipfs/QmSLFeMFPmVeGxT4sxRPW28ictjAS22M8rLeYRu9TXkA6D\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppCore.sol\":{\"keccak256\":\"0x13a9c2d1d2c1f086b8624f2e84c4a4702212daae36f701d92bb915b535cbe4cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://606515dd9193551bd2c94ac8c304f3776fafcc70e544ebf441f334658b2fd5f0\",\"dweb:/ipfs/QmZ88ey7DdZqV5taAoebabvszX5kdPMSrQCAmTteVdDtcH\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/OAppSender.sol\":{\"keccak256\":\"0x518cf4adca601923ed4baa6619846a253ea32b8d8775f8bc1faa3dfac7f67c20\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d42b471418efadcc3577ef3fa9f8f504e8bed7db90c3b0c862038d8b29529eb2\",\"dweb:/ipfs/QmZETDQiJN4U92fmLKo8T9ZbdDf7BNBUUvo9H7M7GqAyFU\"]},\"node_modules/@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol\":{\"keccak256\":\"0x40e49f2de74506e1da5dcaed53a39853f691647f4ceb0fccc8f49a68d3f47c58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4a1deb2a6a3eb1fb83936c9578469142bff470295f403d7d07d955a76be3adbd\",\"dweb:/ipfs/QmS9bjSfBaE4YhQ1PCQ1TknbEPbNfRXzBK9E7SaPGyiZEv\"]},\"node_modules/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol\":{\"keccak256\":\"0x278e7bdeb2e8aa3f528373d8a3b3fedfe2e1bec050bcaf95065a136645cf56bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://43d1789ca4f5cd81986bb52682a94caf188dc8910ecd84cf98bc59221847bd12\",\"dweb:/ipfs/QmSmvKyCukcqxCUvdvNQNyshp4nYt2xxiFaB7Uji4YSrBv\"]},\"node_modules/@openzeppelin/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC1363.sol\":{\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://da62d6be1f5c6edf577f0cb45666a8aa9c2086a4bac87d95d65f02e2f4c36a4b\",\"dweb:/ipfs/QmNkpvBpoCMvX8JwAFNSc5XxJ2q5BXJpL5L1txb4QkqVFF\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11fea9f8bc98949ac6709f0c1699db7430d2948137aa94d5a9e95a91f61a710a\",\"dweb:/ipfs/QmQdfRXxQjwP6yn3DVo1GHPpriKNcFghSPi94Z1oKEFUNS\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC20.sol\":{\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a2608291cb038b388d80b79a06b6118a42f7894ff67b7da10ec0dbbf5b2973ba\",\"dweb:/ipfs/QmWohqcBLbcxmA4eGPhZDXe5RYMMEEpFq22nfkaUMvTfw1\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db\",\"dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9\"]},\"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0xca2ae13e0610f6a99238dd00b97bd786bc92732dae6d6b9d61f573ec51018310\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://75f8c71ce0c91c40dd5f249ace0b7d8270f8f1767231bcf71490f7157d6ba862\",\"dweb:/ipfs/QmYXgxeDyFHvz3JsXxLEYN6GNUR44ThHeFj5XkpkgMoG4w\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0x9d8da059267bac779a2dbbb9a26c2acf00ca83085e105d62d5d4ef96054a47f5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c78e2aa4313323cecd1ef12a8d6265b96beee1a199923abf55d9a2a9e291ad23\",\"dweb:/ipfs/QmUTs2KStXucZezzFo3EYeqYu47utu56qrF7jj1Gue65vb\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"node_modules/@openzeppelin/contracts/utils/Errors.sol\":{\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ba1d02f4847670a1b83dec9f7d37f0b0418d6043447b69f3a29a5f9efc547fcf\",\"dweb:/ipfs/QmQ7iH2keLNUKgq2xSWcRmuBE5eZ3F5whYAkAGzCNNoEWB\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f6fda447a62815e8064f47eff0dd1cf58d9207ad69b5d32280f8d7ed1d1e4621\",\"dweb:/ipfs/QmfDRc7pxfaXB2Dh9np5Uf29Na3pQ7tafRS684wd3GLjVL\"]}},\"version\":1}", "metadata": { "compiler": { "version": "0.8.22+commit.4fc1097e" }, "language": "Solidity", @@ -826,7 +826,7 @@ "notice": "Retrieves interfaceID and the version of the OFT." }, "quoteOFT((uint32,bytes32,uint256,uint256,bytes,bytes,bytes))": { - "notice": "Provides the fee breakdown and settings data for an OFT. Unused in the default implementation." + "notice": "Provides a quote for OFT-related operations." }, "quoteSend((uint32,bytes32,uint256,uint256,bytes,bytes,bytes),bool)": { "notice": "Provides a quote for the send() operation." @@ -926,10 +926,10 @@ "license": "MIT" }, "node_modules/@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol": { - "keccak256": "0x7ba6bb62fba7ee83451cfb0e727ddeef0e96b4388bd4e9ff0fc6ce103e1101c8", + "keccak256": "0x278e7bdeb2e8aa3f528373d8a3b3fedfe2e1bec050bcaf95065a136645cf56bb", "urls": [ - "bzz-raw://cfbd447f2e8a730bd46a14c3c3e6a0b2bf7446145579603a9793ba5ac1dd38b4", - "dweb:/ipfs/QmZ4nx4iGrFmBHvYFgki5TXFdCHz4Co38hgdgwpRaM7NLs" + "bzz-raw://43d1789ca4f5cd81986bb52682a94caf188dc8910ecd84cf98bc59221847bd12", + "dweb:/ipfs/QmSmvKyCukcqxCUvdvNQNyshp4nYt2xxiFaB7Uji4YSrBv" ], "license": "MIT" }, From 3f93284cbcd1c79f59191a894ec21afc2f34482e Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Wed, 11 Dec 2024 11:30:01 -0800 Subject: [PATCH 03/47] fix: run linter on composer lib --- .../contracts/UniswapV3Composer.sol | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/examples/oft-composer-library/contracts/UniswapV3Composer.sol b/examples/oft-composer-library/contracts/UniswapV3Composer.sol index 54d6eb5d1..45c502b69 100644 --- a/examples/oft-composer-library/contracts/UniswapV3Composer.sol +++ b/examples/oft-composer-library/contracts/UniswapV3Composer.sol @@ -13,7 +13,7 @@ import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTCom /** * @title UniswapV3Composer - * @author + * @author * @notice Handles cross-chain OFT token swaps using Uniswap V3 upon receiving tokens via LayerZero. * @dev This contract inherits from IOAppComposer and interacts with Uniswap V3's SwapRouter to execute token swaps. */ @@ -35,13 +35,7 @@ contract UniswapV3Composer is IOAppComposer { /// @param tokenOut The address of the ERC20 token being swapped to. /// @param amountIn The amount of `tokenIn` being swapped. /// @param amountOut The amount of `tokenOut` received from the swap. - event SwapExecuted( - address indexed user, - address tokenIn, - address tokenOut, - uint256 amountIn, - uint256 amountOut - ); + event SwapExecuted(address indexed user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut); /** * @notice Initializes the UniswapV3Composer contract with necessary parameters. @@ -55,11 +49,7 @@ contract UniswapV3Composer is IOAppComposer { * - `_endpoint` cannot be the zero address. * - `_oft` cannot be the zero address. */ - constructor( - address _swapRouter, - address _endpoint, - address _oft - ) { + constructor(address _swapRouter, address _endpoint, address _oft) { require(_swapRouter != address(0), "Invalid SwapRouter address"); require(_endpoint != address(0), "Invalid Endpoint address"); require(_oft != address(0), "Invalid OFT address"); @@ -101,15 +91,10 @@ contract UniswapV3Composer is IOAppComposer { require(msg.sender == endpoint, "Unauthorized Endpoint"); // Decode the composed message using OFTComposeMsgCodec - ( - address user, - address tokenOut, - uint24 fee, - address recipient - ) = abi.decode( - OFTComposeMsgCodec.composeMsg(_message), - (address, address, uint24, address) - ); + (address user, address tokenOut, uint24 fee, address recipient) = abi.decode( + OFTComposeMsgCodec.composeMsg(_message), + (address, address, uint24, address) + ); // Decode the amountIn from the message amount received uint256 amountIn = OFTComposeMsgCodec.amountLD(_message); From 4a32f138996ece3a032aae4bbe249cac46e28e18 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Wed, 11 Dec 2024 13:18:19 -0800 Subject: [PATCH 04/47] chore: add UniswapV3Composer unit tests --- .../contracts/UniswapV3Composer.sol | 3 +- .../test/foundry/UniswapV3Composer.t.sol | 249 ++++++++++++++++++ .../test/mocks/SwapRouterMock.sol | 123 +++++++++ 3 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol create mode 100644 examples/oft-composer-library/test/mocks/SwapRouterMock.sol diff --git a/examples/oft-composer-library/contracts/UniswapV3Composer.sol b/examples/oft-composer-library/contracts/UniswapV3Composer.sol index 45c502b69..6451de220 100644 --- a/examples/oft-composer-library/contracts/UniswapV3Composer.sol +++ b/examples/oft-composer-library/contracts/UniswapV3Composer.sol @@ -13,8 +13,9 @@ import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTCom /** * @title UniswapV3Composer - * @author + * * @notice Handles cross-chain OFT token swaps using Uniswap V3 upon receiving tokens via LayerZero. + * * @dev This contract inherits from IOAppComposer and interacts with Uniswap V3's SwapRouter to execute token swaps. */ contract UniswapV3Composer is IOAppComposer { diff --git a/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol b/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol new file mode 100644 index 000000000..4c0c69431 --- /dev/null +++ b/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +// Import necessary testing libraries and contracts +import "forge-std/Test.sol"; +import { UniswapV3Composer } from "../../contracts/UniswapV3Composer.sol"; +import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; + +// Mock imports +import { OFTMock } from "../mocks/OFTMock.sol"; +import { ERC20Mock } from "../mocks/ERC20Mock.sol"; +import { SwapRouterMock } from "../mocks/SwapRouterMock.sol"; + +// OApp imports +import { IOAppOptionsType3, EnforcedOptionParam } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol"; +import { OptionsBuilder } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol"; + +// OFT imports +import { IOFT, SendParam, OFTReceipt } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; +import { MessagingFee, MessagingReceipt } from "@layerzerolabs/oft-evm/contracts/OFTCore.sol"; +import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol"; +import { OFTMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTMsgCodec.sol"; + +// OpenZeppelin imports +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +// Forge imports +import "forge-std/console.sol"; + +// DevTools imports +import { TestHelperOz5 } from "@layerzerolabs/test-devtools-evm-foundry/contracts/TestHelperOz5.sol"; + +/** + * @title UniswapV3ComposerTest + * @notice Unit tests for the UniswapV3Composer contract. + * @dev Utilizes Forge's testing framework to simulate interactions and verify contract behavior. + */ +contract UniswapV3ComposerTest is TestHelperOz5 { + using OptionsBuilder for bytes; + + // ---------------------------- + // ============ Setup =========== + // ---------------------------- + + // Endpoint Identifiers + uint32 private constant aEid = 1; + uint32 private constant bEid = 2; + + // Mock Contracts + OFTMock private aOFT; + OFTMock private bOFT; + UniswapV3Composer private bComposer; + SwapRouterMock private bSwapRouter; + + // ERC20 Tokens + address bTokenIn; + ERC20Mock private bTokenOut; + + // User Addresses + address private userA = makeAddr("userA"); + address private userB = makeAddr("userB"); + address private otherOFTB = makeAddr("otherOFTB"); + address private receiver = makeAddr("receiver"); + + // Initial Balances and Swap Amounts + uint256 private constant initialBalance = 100 ether; + uint256 private constant swapAmountIn = 1 ether; + uint256 private constant swapAmountOut = 1 ether; // Predefined output for SwapRouterMock + + // Events + event SwapExecuted(address indexed user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut); + + /** + * @notice Sets up the testing environment before each test. + * + * @dev Deploys mock contracts, initializes token balances, and configures the UniswapV3Composer. + */ + function setUp() public virtual override { + // Allocate Ether to users + vm.deal(userA, 1000 ether); + vm.deal(userB, 1000 ether); + + // Initialize endpoints + super.setUp(); + setUpEndpoints(2, LibraryType.UltraLightNode); + + // Deploy mock ERC20 TokenOut and TokenIn + bTokenOut = new ERC20Mock("TokenOut", "OUT"); + + // Deploy mock OFTs with corresponding endpoints + aOFT = OFTMock( + _deployOApp(type(OFTMock).creationCode, abi.encode("aOFT", "aOFT", address(endpoints[aEid]), address(this))) + ); + + bOFT = OFTMock( + _deployOApp(type(OFTMock).creationCode, abi.encode("bOFT", "bOFT", address(endpoints[bEid]), address(this))) + ); + + // Every OFT variant has token() to distinguish between OFT Adapter and OFT + bTokenIn = address(bOFT.token()); + + // Deploy mock SwapRouter with correct tokenIn and tokenOut addresses + bSwapRouter = new SwapRouterMock(address(bTokenIn), address(bTokenOut), swapAmountOut); + + // Deploy the UniswapV3Composer contract with initialized SwapRouter and OFT + bComposer = new UniswapV3Composer(address(bSwapRouter), address(endpoints[bEid]), address(bOFT)); + + // Configure and link the deployed OFTs + address[] memory ofts = new address[](2); + ofts[0] = address(aOFT); + ofts[1] = address(bOFT); + this.wireOApps(ofts); + + // Mint initial tokens to users and contracts + aOFT.mint(userA, initialBalance); + bOFT.mint(userB, initialBalance); + bOFT.mint(address(bComposer), initialBalance); + // Note: SwapRouterMock handles minting TokenOut during swap execution + } + + // ---------------------------- + // ========= Constructor ======= + // ---------------------------- + + /** + * @notice Tests the constructor of UniswapV3Composer for correct initialization. + * @dev Verifies that SwapRouter, endpoint, and OFT addresses are set as expected. + */ + function test_constructor() public { + // Assert that the SwapRouter address is correctly set in UniswapV3Composer + assertEq(address(bComposer.swapRouter()), address(bSwapRouter), "SwapRouter address mismatch"); + + // Assert that the endpoint address is correctly set in UniswapV3Composer + assertEq(bComposer.endpoint(), address(endpoints[bEid]), "Endpoint address mismatch"); + + // Assert that the OFT address is correctly set in UniswapV3Composer + assertEq(bComposer.oft(), address(bOFT), "OFT address mismatch"); + } + + // ---------------------------- + // ========= Test Cases ======= + // ---------------------------- + + /** + * @notice Tests the `lzCompose` function to ensure it correctly handles incoming messages and executes swaps. + * @dev Simulates sending a compose message via LayerZero and verifies SwapRouterMock interactions and token balances. + */ + function test_lzCompose() public { + // ------------------------------ + // 1. Prepare the Compose Message + // ------------------------------ + uint24 fee = 3000; // Example fee tier + + // Encode the compose message with (userA, bTokenOut, fee, receiver) + bytes memory composeMsg = abi.encode(userA, address(bTokenOut), fee, receiver); + + // Encode the full message using OFTComposeMsgCodec + // Parameters: + // _nonce: 1 (unique identifier) + // _srcEid: aEid (source endpoint ID) + // _amountLD: swapAmountIn (amount to be swapped) + // _composeMsg: composeMsg (encoded compose message) + bytes memory fullMessage = OFTComposeMsgCodec.encode( + 1, + aEid, + swapAmountIn, + abi.encodePacked(addressToBytes32(userA), composeMsg) + ); + + // ------------------------------ + // 2. Simulate Sending the Message + // ------------------------------ + // Prank as the authorized endpoint to call lzCompose + vm.prank(address(endpoints[bEid])); + + // Execute lzCompose with the encoded full message + bComposer.lzCompose( + address(bOFT), + bytes32(0), // guid (unused in this test) + fullMessage, + address(this), // executor + bytes("") // extraData (unused in this test) + ); + + // ------------------------------ + // 3. Verify SwapRouterMock Interactions + // ------------------------------ + assertEq(bSwapRouter.lastSender(), address(bComposer), "SwapRouter sender mismatch"); + assertEq(bSwapRouter.lastTokenIn(), address(bTokenIn), "TokenIn address mismatch"); + assertEq(bSwapRouter.lastTokenOut(), address(bTokenOut), "TokenOut address mismatch"); + assertEq(bSwapRouter.lastFee(), fee, "Fee tier mismatch"); + assertEq(bSwapRouter.lastRecipient(), receiver, "Recipient address mismatch"); + assertEq(bSwapRouter.lastAmountIn(), swapAmountIn, "AmountIn mismatch"); + assertEq(bSwapRouter.lastAmountOut(), swapAmountOut, "AmountOut mismatch"); + + // ------------------------------ + // 4. Verify Token Balances After Swap + // ------------------------------ + // Verify that bComposer's tokenIn balance decreased by swapAmountIn + assertEq( + IERC20(bOFT.token()).balanceOf(address(bComposer)), + initialBalance - swapAmountIn, + "bComposer TokenIn balance incorrect" + ); + + // Verify that the receiver's tokenOut balance increased by swapAmountOut + assertEq(bTokenOut.balanceOf(receiver), swapAmountOut, "Receiver TokenOut balance incorrect"); + } + + /** + * @notice Tests that `lzCompose` reverts when called with an unauthorized OFT. + * @dev Attempts to invoke `lzCompose` with a different OFT address and expects a revert. + */ + function test_lzCompose_UnauthorizedOFT() public { + // ------------------------------ + // 1. Prepare the Unauthorized Compose Message + // ------------------------------ + uint24 fee = 3000; // Example fee tier + + // Encode the compose message with (userA, bTokenOut, fee, receiver) + bytes memory composeMsg = abi.encode(userA, address(bTokenOut), fee, receiver); + + // Encode the full message using OFTComposeMsgCodec + bytes memory fullMessage = OFTComposeMsgCodec.encode( + 1, // _nonce + aEid, // _srcEid + swapAmountIn, // _amountLD + composeMsg // _composeMsg + ); + + // ------------------------------ + // 2. Attempt Unauthorized lzCompose + // ------------------------------ + // Prank as the authorized endpoint to call lzCompose + vm.prank(address(endpoints[bEid])); + + // Expect the transaction to revert with "Unauthorized OFT" + vm.expectRevert("Unauthorized OFT"); + + // Attempt to execute lzCompose with an unauthorized OFT address + bComposer.lzCompose( + address(otherOFTB), + bytes32(0), // guid (unused in this test) + fullMessage, + address(0), // executor + bytes("") // extraData (unused in this test) + ); + } +} diff --git a/examples/oft-composer-library/test/mocks/SwapRouterMock.sol b/examples/oft-composer-library/test/mocks/SwapRouterMock.sol new file mode 100644 index 000000000..064623a93 --- /dev/null +++ b/examples/oft-composer-library/test/mocks/SwapRouterMock.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +// Import the ISwapRouter interface from Uniswap V3 Periphery +import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; + +// Import the ERC20Mock to simulate token behavior +import { ERC20Mock } from "../mocks/ERC20Mock.sol"; +import { OFTMock } from "../mocks/OFTMock.sol"; + +/** + * @title SwapRouterMock + * @notice A mock implementation of Uniswap V3's ISwapRouter for testing purposes. + * @dev This contract records the parameters of the last swap and returns a predefined amountOut. + */ +contract SwapRouterMock is ISwapRouter { + // State variables to record the parameters of the last swap + address public lastSender; + address public lastTokenIn; + address public lastTokenOut; + uint24 public lastFee; + address public lastRecipient; + uint256 public lastAmountIn; + uint256 public lastAmountOut; + + // ERC20 tokens used for swapping + OFTMock public tokenIn; + ERC20Mock public tokenOut; + + // Predefined amountOut to return on swaps + uint256 private predefinedAmountOut; + + /** + * @notice Initializes the SwapRouterMock with predefined tokens and amountOut. + * @param _tokenIn The ERC20 token address being swapped from. + * @param _tokenOut The ERC20 token address being swapped to. + * @param _predefinedAmountOut The amount of tokenOut to return on swaps. + */ + constructor(address _tokenIn, address _tokenOut, uint256 _predefinedAmountOut) { + tokenIn = OFTMock(_tokenIn); + tokenOut = ERC20Mock(_tokenOut); + predefinedAmountOut = _predefinedAmountOut; + } + + /** + * @notice Allows setting a new predefined amountOut for subsequent swaps. + * @param _newAmountOut The new amountOut to return. + */ + function setPredefinedAmountOut(uint256 _newAmountOut) external { + predefinedAmountOut = _newAmountOut; + } + + /** + * @notice Mocks the exactInputSingle function of Uniswap V3's ISwapRouter. + * @param params The parameters for the swap, as defined in ISwapRouter.ExactInputSingleParams. + * @return amountOut The amount of tokenOut received from the swap. + * + * @dev This function records the swap parameters and returns a predefined amountOut. + * It also simulates the token transfer by minting tokenOut to the recipient. + */ + function exactInputSingle( + ExactInputSingleParams calldata params + ) external payable override returns (uint256 amountOut) { + // Validate amountIn + require(params.amountIn > 0, "SwapRouterMock: amountIn must be greater than zero"); + + // Record the parameters of the swap + lastSender = msg.sender; + lastTokenIn = params.tokenIn; + lastTokenOut = params.tokenOut; + lastFee = params.fee; + lastRecipient = params.recipient; + lastAmountIn = params.amountIn; + lastAmountOut = predefinedAmountOut; + + // Simulate the transfer of tokenIn from the sender to the SwapRouterMock + tokenIn.transferFrom(msg.sender, address(this), params.amountIn); + + // Simulate minting tokenOut to the recipient + tokenOut.mint(params.recipient, predefinedAmountOut); + + // Return the predefined amountOut + return predefinedAmountOut; + } + + /** + * @notice Mocks other functions from the ISwapRouter interface. + * @dev These functions are left unimplemented and will revert if called, indicating they are not supported in the mock. + */ + + // Swaps with exact input along a specified path + function exactInput( + ISwapRouter.ExactInputParams calldata /*params*/ + ) external payable override returns (uint256 /*amountOut*/) { + revert("SwapRouterMock: exactInput not implemented"); + } + + // Swaps to receive an exact amount of output tokens with single-hop + function exactOutputSingle( + ISwapRouter.ExactOutputSingleParams calldata /*params*/ + ) external payable override returns (uint256 /*amountIn*/) { + revert("SwapRouterMock: exactOutputSingle not implemented"); + } + + // Swaps to receive an exact amount of output tokens along a specified path + function exactOutput( + ISwapRouter.ExactOutputParams calldata /*params*/ + ) external payable override returns (uint256 /*amountIn*/) { + revert("SwapRouterMock: exactOutput not implemented"); + } + + /** + * @notice Mocks the uniswapV3SwapCallback function from IUniswapV3SwapCallback. + * @dev This mock does not handle actual swap callbacks and will revert if called. + */ + function uniswapV3SwapCallback( + int256 /*amount0Delta*/, + int256 /*amount1Delta*/, + bytes calldata /*data*/ + ) external pure override { + revert("SwapRouterMock: uniswapV3SwapCallback not implemented"); + } +} From b9cb9664123c63b3d3d8a32a39783b61b67593e6 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Wed, 11 Dec 2024 13:52:25 -0800 Subject: [PATCH 05/47] fix: lint --- .../contracts/UniswapV3Composer.sol | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/examples/oft-composer-library/contracts/UniswapV3Composer.sol b/examples/oft-composer-library/contracts/UniswapV3Composer.sol index 6451de220..b5c35e500 100644 --- a/examples/oft-composer-library/contracts/UniswapV3Composer.sol +++ b/examples/oft-composer-library/contracts/UniswapV3Composer.sol @@ -30,16 +30,20 @@ contract UniswapV3Composer is IOAppComposer { /// @notice The address of the OFT on the receiving chain. address public immutable oft; - /// @notice Emitted when a token swap is successfully executed. - /// @param user The address of the user initiating the swap. - /// @param tokenIn The address of the ERC20 token being swapped from (OFT). - /// @param tokenOut The address of the ERC20 token being swapped to. - /// @param amountIn The amount of `tokenIn` being swapped. - /// @param amountOut The amount of `tokenOut` received from the swap. + /** + * @notice Emitted when a token swap is successfully executed. + * + * @param user The address of the user initiating the swap. + * @param tokenIn The address of the ERC20 token being swapped from (OFT). + * @param tokenOut The address of the ERC20 token being swapped to. + * @param amountIn The amount of `tokenIn` being swapped. + * @param amountOut The amount of `tokenOut` received from the swap. + */ event SwapExecuted(address indexed user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut); /** * @notice Initializes the UniswapV3Composer contract with necessary parameters. + * * @param _swapRouter The address of the Uniswap V3 SwapRouter. * @param _endpoint The LayerZero Endpoint address for cross-chain communication. * @param _oft The address of the originating OFT that sends composed messages. @@ -65,6 +69,7 @@ contract UniswapV3Composer is IOAppComposer { * * @param _oft The address of the originating OFT. * @param _message The encoded message content in the format of OFTComposeMsgCodec. + * * @dev _executor The address of the executor (unused in this context). * @dev _guid The globally unique identifier of the message (unused in this context). * @dev _executorData Additional data for the executor (unused in this context). From d3ab75aee0034c823b35e78079d9a650ff2984fe Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Wed, 11 Dec 2024 13:58:31 -0800 Subject: [PATCH 06/47] chore: remove tasks --- .../oft-composer-library/hardhat.config.ts | 1 - .../tasks/createUniswapPool.ts | 135 ------------------ examples/oft-composer-library/tasks/send.ts | 112 --------------- 3 files changed, 248 deletions(-) delete mode 100644 examples/oft-composer-library/tasks/createUniswapPool.ts delete mode 100644 examples/oft-composer-library/tasks/send.ts diff --git a/examples/oft-composer-library/hardhat.config.ts b/examples/oft-composer-library/hardhat.config.ts index 85c1ae8ff..53c186deb 100644 --- a/examples/oft-composer-library/hardhat.config.ts +++ b/examples/oft-composer-library/hardhat.config.ts @@ -12,7 +12,6 @@ import '@layerzerolabs/toolbox-hardhat' import { HardhatUserConfig, HttpNetworkAccountsUserConfig } from 'hardhat/types' import { EndpointId } from '@layerzerolabs/lz-definitions' -import './tasks/send.ts' // Set your preferred authentication method // diff --git a/examples/oft-composer-library/tasks/createUniswapPool.ts b/examples/oft-composer-library/tasks/createUniswapPool.ts deleted file mode 100644 index b678492b4..000000000 --- a/examples/oft-composer-library/tasks/createUniswapPool.ts +++ /dev/null @@ -1,135 +0,0 @@ -// tasks/createUniswapV3Pool.ts - -import IUniswapV3FactoryABI from '@uniswap/v3-core/artifacts/contracts/interfaces/IUniswapV3Factory.sol/IUniswapV3Factory.json' -import INonfungiblePositionManagerABI from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json' -import { Contract } from 'ethers' -import { task } from 'hardhat/config' -import { HardhatRuntimeEnvironment } from 'hardhat/types' - -// Import ABIs for Uniswap V3 Factory and Position Manager - -// Define the Hardhat task -task('create-uniswapv3-pool', 'Creates a Uniswap V3 pool for your OFT token and USDC on Arbitrum Sepolia').setAction( - async (taskArgs: any, hre: HardhatRuntimeEnvironment) => { - // Destructure necessary objects from Hardhat Runtime Environment - const { ethers, deployments } = hre - - // ====== Configuration ====== - - // Replace these addresses with actual deployed contract addresses on Arbitrum Sepolia - const UNISWAP_V3_FACTORY_ADDRESS = '0xYourUniswapV3FactoryAddress' // e.g., '0x1F98431c8aD98523631AE4a59f267346ea31F984' - const NONFUNGIBLE_POSITION_MANAGER_ADDRESS = '0xYourPositionManagerAddress' // e.g., '0xC36442b4a4522E871399CD717aBDD847Ab11FE88' - const YOUR_OFT_ADDRESS = '0xYourOFTTokenAddress' // Replace with your OFT token address - const USDC_ADDRESS = '0xYourUSDCAddress' // Replace with USDC token address on Arbitrum Sepolia - - // Define the fee tier for the pool (e.g., 3000 = 0.3%) - const FEE_TIER = 3000 - - // Define the amount of OFT and USDC to add as initial liquidity - const AMOUNT_OFT_DESIRED = ethers.utils.parseUnits('1000', 18) // Adjust decimals if your OFT has different decimals - const AMOUNT_USDC_DESIRED = ethers.utils.parseUnits('1000', 6) // USDC typically has 6 decimals - - // Define slippage parameters (set min amounts equal to desired amounts for zero slippage) - const AMOUNT_OFT_MIN = AMOUNT_OFT_DESIRED - const AMOUNT_USDC_MIN = AMOUNT_USDC_DESIRED - - // Define the recipient and deadline for the liquidity provision - const signer = (await ethers.getSigners())[0] - const recipient = signer.address - const deadline = Math.floor(Date.now() / 1000) + 60 * 20 // 20 minutes from now - - // ====== Instantiate Contracts ====== - - // Instantiate Uniswap V3 Factory - const factory = new Contract(UNISWAP_V3_FACTORY_ADDRESS, IUniswapV3FactoryABI.abi, signer) - - // Instantiate Nonfungible Position Manager - const positionManager = new Contract( - NONFUNGIBLE_POSITION_MANAGER_ADDRESS, - INonfungiblePositionManagerABI.abi, - signer - ) - - // Instantiate your OFT token contract - const oftContract = new Contract( - YOUR_OFT_ADDRESS, - [ - 'function approve(address spender, uint256 amount) external returns (bool)', - 'function decimals() view returns (uint8)', - ], - signer - ) - - // Instantiate USDC token contract - const usdcContract = new Contract( - USDC_ADDRESS, - [ - 'function approve(address spender, uint256 amount) external returns (bool)', - 'function decimals() view returns (uint8)', - ], - signer - ) - - // ====== Approve Position Manager to Spend Tokens ====== - - console.log('Approving Position Manager to spend OFT tokens...') - const approveOftTx = await oftContract.approve(NONFUNGIBLE_POSITION_MANAGER_ADDRESS, AMOUNT_OFT_DESIRED) - await approveOftTx.wait() - console.log('OFT token approval completed.') - - console.log('Approving Position Manager to spend USDC tokens...') - const approveUsdcTx = await usdcContract.approve(NONFUNGIBLE_POSITION_MANAGER_ADDRESS, AMOUNT_USDC_DESIRED) - await approveUsdcTx.wait() - console.log('USDC token approval completed.') - - // ====== Check if Pool Exists ====== - - console.log('Checking if the pool already exists...') - const poolAddress = await factory.getPool(YOUR_OFT_ADDRESS, USDC_ADDRESS, FEE_TIER) - if (poolAddress !== ethers.constants.AddressZero) { - console.log(`Pool already exists at address: ${poolAddress}`) - return - } - console.log('Pool does not exist. It will be created upon adding liquidity.') - - // ====== Define Tick Ranges ====== - - // For demonstration purposes, use wide tick ranges to cover all possible prices - const tickSpacing = await factory.tickSpacing(FEE_TIER) // Get tick spacing for the fee tier - const tickLower = -887220 // Minimum tick - const tickUpper = 887220 // Maximum tick - - // ====== Add Liquidity (Create Pool) ====== - - console.log('Adding liquidity to create the pool...') - const mintTx = await positionManager.mint({ - token0: YOUR_OFT_ADDRESS, - token1: USDC_ADDRESS, - fee: FEE_TIER, - tickLower: tickLower, - tickUpper: tickUpper, - amount0Desired: AMOUNT_OFT_DESIRED, - amount1Desired: AMOUNT_USDC_DESIRED, - amount0Min: AMOUNT_OFT_MIN, - amount1Min: AMOUNT_USDC_MIN, - recipient: recipient, - deadline: deadline, - }) - - const receipt = await mintTx.wait() - console.log(`Liquidity added successfully. Transaction hash: ${receipt.transactionHash}`) - - // ====== Retrieve Pool Address ====== - - const newPoolAddress = await factory.getPool(YOUR_OFT_ADDRESS, USDC_ADDRESS, FEE_TIER) - console.log(`New Pool Address: ${newPoolAddress}`) - - // ====== Confirm Pool Creation ====== - - if (newPoolAddress !== ethers.constants.AddressZero) { - console.log('Pool created successfully!') - } else { - console.error('Failed to create the pool.') - } - } -) diff --git a/examples/oft-composer-library/tasks/send.ts b/examples/oft-composer-library/tasks/send.ts deleted file mode 100644 index aeabedfe5..000000000 --- a/examples/oft-composer-library/tasks/send.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { BigNumberish, BytesLike } from 'ethers' -import { task } from 'hardhat/config' - -import { getNetworkNameForEid, types } from '@layerzerolabs/devtools-evm-hardhat' -import { EndpointId } from '@layerzerolabs/lz-definitions' -import { Options, addressToBytes32 } from '@layerzerolabs/lz-v2-utilities' - -// Define the interface for task arguments -interface Args { - amount: string - to: string - toEid: EndpointId - tokenOut: string - fee: number -} - -// Define the interface for SendParam as per your requirements -interface SendParam { - dstEid: EndpointId // Destination endpoint ID, represented as a number. - to: BytesLike // Recipient address, represented as bytes. - amountLD: BigNumberish // Amount to send in local decimals. - minAmountLD: BigNumberish // Minimum amount to send in local decimals. - extraOptions: BytesLike // Additional options supplied by the caller to be used in the LayerZero message. - composeMsg: BytesLike // The composed message for the send() operation. - oftCmd: BytesLike // The OFT command to be executed, unused in default OFT implementations. -} - -// Define the Hardhat task -task('lz:oft:send-and-swap', 'Sends tokens via OFT and performs a swap with UniswapV3Composer on the destination chain') - .addParam('to', 'Contract address on the destination network', undefined, types.string) - .addParam('toEid', 'Destination endpoint ID', undefined, types.eid) - .addParam('amount', 'Amount to transfer in token decimals', undefined, types.string) - .addParam('tokenOut', 'Address of the token to swap to on the destination chain', undefined, types.string) - .addParam('fee', 'Uniswap V3 pool fee (e.g., 3000 for 0.3%)', undefined, types.int) - .setAction(async (taskArgs: Args, { ethers, deployments }) => { - // Extract task arguments - const toAddress = taskArgs.to - const eidB = taskArgs.toEid - const tokenOut = taskArgs.tokenOut - const fee = taskArgs.fee - - // Define gas limit and msg.value for the swap on the destination chain - // These values should be estimated based on the swap complexity and network specifics - const swapGasLimit = 300000 // Example gas limit; adjust as needed - const swapMsgValue = ethers.utils.parseEther('0.01') // Example ETH value for gas; adjust as needed - - // Retrieve the OFT deployment information - const oftDeployment = await deployments.get('MyOFT') - - // Get the signer (deployer) account - const [signer] = await ethers.getSigners() - - // Instantiate the OFT contract - const oftContract = new ethers.Contract(oftDeployment.address, oftDeployment.abi, signer) - - // Retrieve the token decimals from the OFT contract - const decimals = await oftContract.decimals() - - // Parse the amount to transfer into the correct units - const amount = ethers.utils.parseUnits(taskArgs.amount, decimals) - - // Initialize the options with existing executor options (e.g., LzReceive) - // and add the new executor option for LzCompose with the gas limit and msg.value - const options = Options.newOptions() - .addExecutorComposeOption(0, swapGasLimit, swapMsgValue.toBigInt()) // New LzCompose option - .toBytes() - - // Define the user initiating the swap as the signer - const user = await signer.getAddress() - - // Define the recipient of the swap on the destination chain - const recipient = toAddress - - // Encode the swap parameters into the composeMsg bytes using abi.encode - const composeMsg = ethers.utils.defaultAbiCoder.encode( - ['address', 'address', 'uint24', 'address'], - [user, tokenOut, fee, recipient] - ) - - // Construct the SendParam object with all required parameters - const sendParam: SendParam = { - dstEid: eidB, - to: addressToBytes32(toAddress), - amountLD: amount, - minAmountLD: amount, // Adjust minAmountLD based on slippage tolerance - extraOptions: options, - composeMsg: composeMsg, // Encoded swap parameters - oftCmd: ethers.utils.arrayify('0x'), // Assuming no OFT command is needed; adjust if necessary - } - - // Obtain the fee quote for the send operation - const feeQuote = await oftContract.quoteSend(sendParam, false) - const nativeFee = feeQuote.nativeFee - - console.log( - `Sending ${taskArgs.amount} token(s) to network ${getNetworkNameForEid(eidB)} (Endpoint ID: ${eidB})` - ) - - // Optionally, approve the amount to be spent by the OFT contract - // This step may be unnecessary if the OFT contract already has the required allowance - /* - const erc20 = IERC20(await oftContract.token()); - await erc20.approve(oftDeployment.address, amount); - */ - - // Execute the send operation with the composed parameters and required fees - const tx = await oftContract.send(sendParam, { nativeFee: nativeFee, lzTokenFee: 0 }, recipient, { - value: nativeFee, // Include the native fee; adjust if lzTokenFee is used - }) - - console.log(`Send transaction initiated. View on LayerZero Scan: https://layerzeroscan.com/tx/${tx.hash}`) - }) From 9761620e2a6a942bb36e82667c81f622e5a1ba85 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Wed, 11 Dec 2024 14:03:02 -0800 Subject: [PATCH 07/47] chore: update SwapRouterMock --- .../oft-composer-library/test/mocks/SwapRouterMock.sol | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/oft-composer-library/test/mocks/SwapRouterMock.sol b/examples/oft-composer-library/test/mocks/SwapRouterMock.sol index 064623a93..11eb0a0ea 100644 --- a/examples/oft-composer-library/test/mocks/SwapRouterMock.sol +++ b/examples/oft-composer-library/test/mocks/SwapRouterMock.sol @@ -4,9 +4,12 @@ pragma solidity ^0.8.20; // Import the ISwapRouter interface from Uniswap V3 Periphery import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; +import { IOFT } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + // Import the ERC20Mock to simulate token behavior import { ERC20Mock } from "../mocks/ERC20Mock.sol"; -import { OFTMock } from "../mocks/OFTMock.sol"; /** * @title SwapRouterMock @@ -24,7 +27,7 @@ contract SwapRouterMock is ISwapRouter { uint256 public lastAmountOut; // ERC20 tokens used for swapping - OFTMock public tokenIn; + IERC20 public tokenIn; ERC20Mock public tokenOut; // Predefined amountOut to return on swaps @@ -37,7 +40,7 @@ contract SwapRouterMock is ISwapRouter { * @param _predefinedAmountOut The amount of tokenOut to return on swaps. */ constructor(address _tokenIn, address _tokenOut, uint256 _predefinedAmountOut) { - tokenIn = OFTMock(_tokenIn); + tokenIn = IERC20(IOFT(_tokenIn).token()); tokenOut = ERC20Mock(_tokenOut); predefinedAmountOut = _predefinedAmountOut; } From 119b75d43171c7f38db46a0a563bd2f3193a3308 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Wed, 11 Dec 2024 14:09:27 -0800 Subject: [PATCH 08/47] chore: remove unused safeERC20 --- examples/oft-composer-library/contracts/UniswapV3Composer.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/oft-composer-library/contracts/UniswapV3Composer.sol b/examples/oft-composer-library/contracts/UniswapV3Composer.sol index b5c35e500..bcfc7c6a2 100644 --- a/examples/oft-composer-library/contracts/UniswapV3Composer.sol +++ b/examples/oft-composer-library/contracts/UniswapV3Composer.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.0; // Import necessary interfaces and libraries import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; @@ -19,8 +18,6 @@ import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTCom * @dev This contract inherits from IOAppComposer and interacts with Uniswap V3's SwapRouter to execute token swaps. */ contract UniswapV3Composer is IOAppComposer { - using SafeERC20 for IERC20; - /// @notice The Uniswap V3 SwapRouter used to perform token swaps. ISwapRouter public immutable swapRouter; From 8b193864d17c301d465c0de8651854a5a3c734d4 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Fri, 13 Dec 2024 12:42:58 -0800 Subject: [PATCH 09/47] chore: update mock to use IOFT instead of IERC20 --- examples/oft-composer-library/test/mocks/SwapRouterMock.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/oft-composer-library/test/mocks/SwapRouterMock.sol b/examples/oft-composer-library/test/mocks/SwapRouterMock.sol index 11eb0a0ea..1910aa61c 100644 --- a/examples/oft-composer-library/test/mocks/SwapRouterMock.sol +++ b/examples/oft-composer-library/test/mocks/SwapRouterMock.sol @@ -35,12 +35,12 @@ contract SwapRouterMock is ISwapRouter { /** * @notice Initializes the SwapRouterMock with predefined tokens and amountOut. - * @param _tokenIn The ERC20 token address being swapped from. + * @param _oftIn The OFT address being swapped from. * @param _tokenOut The ERC20 token address being swapped to. * @param _predefinedAmountOut The amount of tokenOut to return on swaps. */ - constructor(address _tokenIn, address _tokenOut, uint256 _predefinedAmountOut) { - tokenIn = IERC20(IOFT(_tokenIn).token()); + constructor(address _oftIn, address _tokenOut, uint256 _predefinedAmountOut) { + tokenIn = IERC20(IOFT(_oftIn).token()); tokenOut = ERC20Mock(_tokenOut); predefinedAmountOut = _predefinedAmountOut; } From a2009faa08c6b82675bd914c5c0844ded54b476b Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Fri, 13 Dec 2024 12:45:47 -0800 Subject: [PATCH 10/47] fix: update lockfile --- pnpm-lock.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 62f4c4180..1e25a585a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14125,7 +14125,7 @@ packages: peerDependencies: eslint: ^8.56.0 dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) '@types/json-schema': 7.0.15 '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 7.7.1 From 2016957b76fcfeb49c93c3ee5c077c6bd430f8ba Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Mon, 17 Feb 2025 12:12:00 -0800 Subject: [PATCH 11/47] chore: address audit feedback --- .../contracts/UniswapV3Composer.sol | 65 +++++++++++-------- .../test/foundry/UniswapV3Composer.t.sol | 48 ++++++++------ 2 files changed, 64 insertions(+), 49 deletions(-) diff --git a/examples/oft-composer-library/contracts/UniswapV3Composer.sol b/examples/oft-composer-library/contracts/UniswapV3Composer.sol index bcfc7c6a2..9d4d4e3aa 100644 --- a/examples/oft-composer-library/contracts/UniswapV3Composer.sol +++ b/examples/oft-composer-library/contracts/UniswapV3Composer.sol @@ -3,9 +3,7 @@ pragma solidity ^0.8.0; // Import necessary interfaces and libraries import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; - import { IOAppComposer } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppComposer.sol"; import { IOFT } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol"; @@ -27,16 +25,29 @@ contract UniswapV3Composer is IOAppComposer { /// @notice The address of the OFT on the receiving chain. address public immutable oft; + /// @notice Custom errors for more gas-efficient reverts. + error InvalidSwapRouter(); + error InvalidEndpoint(); + error InvalidOFT(); + error UnauthorizedOFT(); + error UnauthorizedEndpoint(); + /** * @notice Emitted when a token swap is successfully executed. * - * @param user The address of the user initiating the swap. + * @param srcSender The bytes32 address of the user initiating the swap on the source chain. * @param tokenIn The address of the ERC20 token being swapped from (OFT). * @param tokenOut The address of the ERC20 token being swapped to. * @param amountIn The amount of `tokenIn` being swapped. * @param amountOut The amount of `tokenOut` received from the swap. */ - event SwapExecuted(address indexed user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut); + event SwapExecuted( + bytes32 indexed srcSender, + address tokenIn, + address tokenOut, + uint256 amountIn, + uint256 amountOut + ); /** * @notice Initializes the UniswapV3Composer contract with necessary parameters. @@ -52,9 +63,9 @@ contract UniswapV3Composer is IOAppComposer { * - `_oft` cannot be the zero address. */ constructor(address _swapRouter, address _endpoint, address _oft) { - require(_swapRouter != address(0), "Invalid SwapRouter address"); - require(_endpoint != address(0), "Invalid Endpoint address"); - require(_oft != address(0), "Invalid OFT address"); + if (_swapRouter == address(0)) revert InvalidSwapRouter(); + if (_endpoint == address(0)) revert InvalidEndpoint(); + if (_oft == address(0)) revert InvalidOFT(); swapRouter = ISwapRouter(_swapRouter); endpoint = _endpoint; @@ -70,9 +81,9 @@ contract UniswapV3Composer is IOAppComposer { * @dev _executor The address of the executor (unused in this context). * @dev _guid The globally unique identifier of the message (unused in this context). * @dev _executorData Additional data for the executor (unused in this context). - * @dev - * This function decodes the incoming message to extract swap parameters and executes the token swap using Uniswap V3. - * It ensures that only the authorized OFT and the LayerZero Endpoint can invoke this function. + * + * This function decodes the incoming message to extract swap parameters and executes the token swap + * using Uniswap V3. It ensures that only the authorized OFT and the LayerZero Endpoint can invoke this function. * * Emits a {SwapExecuted} event upon successful execution of the swap. * @@ -90,40 +101,38 @@ contract UniswapV3Composer is IOAppComposer { address /*_executor*/, bytes calldata /*_extraData*/ ) external payable override { - require(_oft == address(oft), "Unauthorized OFT"); - require(msg.sender == endpoint, "Unauthorized Endpoint"); + if (_oft != oft) revert UnauthorizedOFT(); + if (msg.sender != endpoint) revert UnauthorizedEndpoint(); - // Decode the composed message using OFTComposeMsgCodec - (address user, address tokenOut, uint24 fee, address recipient) = abi.decode( - OFTComposeMsgCodec.composeMsg(_message), - (address, address, uint24, address) - ); + (address tokenOut, uint24 fee, address recipient, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96) = abi + .decode(OFTComposeMsgCodec.composeMsg(_message), (address, uint24, address, uint256, uint160)); - // Decode the amountIn from the message amount received + // Extract the original msg.sender of OFT.send() on the source chain. + bytes32 srcSender = OFTComposeMsgCodec.composeFrom(_message); + // Decode the amountIn from the message amount received. uint256 amountIn = OFTComposeMsgCodec.amountLD(_message); - - // Reference to the ERC20 token used by the OFT + // Reference to the ERC20 token used by the OFT. address tokenIn = IOFT(oft).token(); - // Approve the SwapRouter to spend tokenIn + // Approve the SwapRouter to spend tokenIn. IERC20(tokenIn).approve(address(swapRouter), amountIn); - // Set up Uniswap V3 swap parameters + // Set up Uniswap V3 swap parameters. ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ tokenIn: tokenIn, tokenOut: tokenOut, fee: fee, recipient: recipient, - deadline: block.timestamp + 300, // 5 minutes deadline + deadline: block.timestamp + 300, // 5 minutes deadline. amountIn: amountIn, - amountOutMinimum: 0, // Consider setting a minimum amount out to protect against slippage - sqrtPriceLimitX96: 0 // No price limit + amountOutMinimum: amountOutMinimum, + sqrtPriceLimitX96: sqrtPriceLimitX96 }); - // Execute the swap on Uniswap V3 + // Execute the swap on Uniswap V3. uint256 amountOut = swapRouter.exactInputSingle(params); - // Emit an event to log the swap details - emit SwapExecuted(user, tokenIn, tokenOut, amountIn, amountOut); + // Emit an event to log the swap details. + emit SwapExecuted(srcSender, tokenIn, tokenOut, amountIn, amountOut); } } diff --git a/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol b/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol index 4c0c69431..cb61f8ed3 100644 --- a/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol +++ b/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol @@ -67,9 +67,6 @@ contract UniswapV3ComposerTest is TestHelperOz5 { uint256 private constant swapAmountIn = 1 ether; uint256 private constant swapAmountOut = 1 ether; // Predefined output for SwapRouterMock - // Events - event SwapExecuted(address indexed user, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut); - /** * @notice Sets up the testing environment before each test. * @@ -151,40 +148,49 @@ contract UniswapV3ComposerTest is TestHelperOz5 { // ------------------------------ uint24 fee = 3000; // Example fee tier - // Encode the compose message with (userA, bTokenOut, fee, receiver) - bytes memory composeMsg = abi.encode(userA, address(bTokenOut), fee, receiver); + // New slippage parameters. + uint256 swapAmountOutMinimum = 100; // Example minimum amount out + uint160 swapSqrtPriceLimitX96 = 0; // Example: no price limit (0) + + // Compose message now encodes: + // (tokenOut, fee, recipient, amountOutMinimum, sqrtPriceLimitX96) + bytes memory composeMsg = abi.encode( + address(bTokenOut), + fee, + receiver, + swapAmountOutMinimum, + swapSqrtPriceLimitX96 + ); - // Encode the full message using OFTComposeMsgCodec - // Parameters: - // _nonce: 1 (unique identifier) - // _srcEid: aEid (source endpoint ID) - // _amountLD: swapAmountIn (amount to be swapped) - // _composeMsg: composeMsg (encoded compose message) + // The full message now prepends the source sender (userA) to the composed payload. + // Here, addressToBytes32(userA) converts the source sender's address to a bytes32 representation. bytes memory fullMessage = OFTComposeMsgCodec.encode( - 1, - aEid, - swapAmountIn, + 1, // _nonce: unique identifier + aEid, // _srcEid: source endpoint ID + swapAmountIn, // _amountLD: amount to be swapped abi.encodePacked(addressToBytes32(userA), composeMsg) ); // ------------------------------ // 2. Simulate Sending the Message // ------------------------------ - // Prank as the authorized endpoint to call lzCompose + // Prank as the authorized endpoint to call lzCompose. vm.prank(address(endpoints[bEid])); - // Execute lzCompose with the encoded full message + // Execute lzCompose with the encoded full message. bComposer.lzCompose( - address(bOFT), + address(bOFT), // The originating OFT address. bytes32(0), // guid (unused in this test) fullMessage, - address(this), // executor + address(this), // executor (unused in this test) bytes("") // extraData (unused in this test) ); // ------------------------------ // 3. Verify SwapRouterMock Interactions // ------------------------------ + // Verify that the SwapRouter was called with the correct parameters. + // Note: The mock should record the following parameters for inspection. assertEq(bSwapRouter.lastSender(), address(bComposer), "SwapRouter sender mismatch"); assertEq(bSwapRouter.lastTokenIn(), address(bTokenIn), "TokenIn address mismatch"); assertEq(bSwapRouter.lastTokenOut(), address(bTokenOut), "TokenOut address mismatch"); @@ -196,14 +202,14 @@ contract UniswapV3ComposerTest is TestHelperOz5 { // ------------------------------ // 4. Verify Token Balances After Swap // ------------------------------ - // Verify that bComposer's tokenIn balance decreased by swapAmountIn + // Verify that bComposer's tokenIn balance decreased by swapAmountIn. assertEq( IERC20(bOFT.token()).balanceOf(address(bComposer)), initialBalance - swapAmountIn, "bComposer TokenIn balance incorrect" ); - // Verify that the receiver's tokenOut balance increased by swapAmountOut + // Verify that the receiver's tokenOut balance increased by swapAmountOut. assertEq(bTokenOut.balanceOf(receiver), swapAmountOut, "Receiver TokenOut balance incorrect"); } @@ -235,7 +241,7 @@ contract UniswapV3ComposerTest is TestHelperOz5 { vm.prank(address(endpoints[bEid])); // Expect the transaction to revert with "Unauthorized OFT" - vm.expectRevert("Unauthorized OFT"); + vm.expectRevert(UniswapV3Composer.UnauthorizedOFT.selector); // Attempt to execute lzCompose with an unauthorized OFT address bComposer.lzCompose( From 010c95ac04d11da1464635403f18082254acf4aa Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Mon, 17 Feb 2025 12:23:00 -0800 Subject: [PATCH 12/47] chore: update lockfile --- pnpm-lock.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1e25a585a..62f4c4180 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14125,7 +14125,7 @@ packages: peerDependencies: eslint: ^8.56.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) '@types/json-schema': 7.0.15 '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 7.7.1 From 50898b87072470ac7557ecf7751c58bd13a99300 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Wed, 5 Mar 2025 17:00:14 -0800 Subject: [PATCH 13/47] chore: add fallback for swap failure --- .../contracts/UniswapV3Composer.sol | 30 +++++-- .../test/foundry/UniswapV3Composer.t.sol | 78 +++++++++++++++++++ .../test/mocks/SwapRouterMock.sol | 45 ++++++----- 3 files changed, 127 insertions(+), 26 deletions(-) diff --git a/examples/oft-composer-library/contracts/UniswapV3Composer.sol b/examples/oft-composer-library/contracts/UniswapV3Composer.sol index 9d4d4e3aa..3d02036a9 100644 --- a/examples/oft-composer-library/contracts/UniswapV3Composer.sol +++ b/examples/oft-composer-library/contracts/UniswapV3Composer.sol @@ -3,7 +3,10 @@ pragma solidity ^0.8.0; // Import necessary interfaces and libraries import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; + import { IOAppComposer } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppComposer.sol"; import { IOFT } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol"; @@ -16,6 +19,7 @@ import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTCom * @dev This contract inherits from IOAppComposer and interacts with Uniswap V3's SwapRouter to execute token swaps. */ contract UniswapV3Composer is IOAppComposer { + using SafeERC20 for IERC20; /// @notice The Uniswap V3 SwapRouter used to perform token swaps. ISwapRouter public immutable swapRouter; @@ -43,12 +47,23 @@ contract UniswapV3Composer is IOAppComposer { */ event SwapExecuted( bytes32 indexed srcSender, + address recipient, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut ); + /** + * @notice Emitted when a token swap fails and the OFT tokens are refunded to the recipient. + * + * @param srcSender The bytes32 address of the user initiating the swap on the source chain. + * @param recipient The address of the recipient of the OFT tokens. + * @param tokenIn The address of the ERC20 token being swapped from (OFT). + * @param amountIn The amount of `tokenIn` being refunded. + */ + event SwapFailedAndRefunded(bytes32 indexed srcSender, address tokenIn, address recipient, uint256 amountIn); + /** * @notice Initializes the UniswapV3Composer contract with necessary parameters. * @@ -87,6 +102,8 @@ contract UniswapV3Composer is IOAppComposer { * * Emits a {SwapExecuted} event upon successful execution of the swap. * + * Transfers the OFT tokens directly to the recipient if the swap fails. + * * Requirements: * * - `_oft` must match the authorized OFT address. @@ -129,10 +146,13 @@ contract UniswapV3Composer is IOAppComposer { sqrtPriceLimitX96: sqrtPriceLimitX96 }); - // Execute the swap on Uniswap V3. - uint256 amountOut = swapRouter.exactInputSingle(params); - - // Emit an event to log the swap details. - emit SwapExecuted(srcSender, tokenIn, tokenOut, amountIn, amountOut); + // Attempt to execute the swap on Uniswap V3. + try swapRouter.exactInputSingle(params) returns (uint256 amountOut) { + emit SwapExecuted(srcSender, recipient, tokenIn, tokenOut, amountIn, amountOut); + } catch { + // Refund the OFT tokens to the recipient if the swap fails. + IERC20(tokenIn).safeTransfer(recipient, amountIn); + emit SwapFailedAndRefunded(srcSender, tokenIn, recipient, amountIn); + } } } diff --git a/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol b/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol index cb61f8ed3..1bf711ac1 100644 --- a/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol +++ b/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol @@ -213,6 +213,84 @@ contract UniswapV3ComposerTest is TestHelperOz5 { assertEq(bTokenOut.balanceOf(receiver), swapAmountOut, "Receiver TokenOut balance incorrect"); } + /** + * @notice Tests the fallback logic in `lzCompose` when the swap fails. + * + * This test simulates a swap failure by setting the SwapRouterMock to revert. + * In that case, the fallback logic in the catch block should transfer the full token amount + * from the composer to the specified recipient. + */ + function test_lzCompose_Fallback() public { + // ------------------------------ + // 1. Prepare the Compose Message + // ------------------------------ + uint24 fee = 3000; // Example fee tier + uint256 swapAmountOutMinimum = 100; // Example minimum amount out + uint160 swapSqrtPriceLimitX96 = 0; // Example: no price limit + + // Compose message now encodes: + // (tokenOut, fee, recipient, amountOutMinimum, sqrtPriceLimitX96) + bytes memory composeMsg = abi.encode( + address(bTokenOut), + fee, + receiver, + swapAmountOutMinimum, + swapSqrtPriceLimitX96 + ); + + // The full message now prepends the source sender (userA) to the composed payload. + // addressToBytes32(userA) converts the source sender's address to a bytes32 representation. + bytes memory fullMessage = OFTComposeMsgCodec.encode( + 1, // _nonce: unique identifier + aEid, // _srcEid: source endpoint ID + swapAmountIn, // _amountLD: amount to be swapped + abi.encodePacked(addressToBytes32(userA), composeMsg) + ); + + // ------------------------------ + // 2. Configure the SwapRouterMock to Revert + // ------------------------------ + // Instruct the mock to revert when swapRouter.exactInputSingle() is called. + // This simulates a condition where the swap fails (e.g., slippage exceeded). + bSwapRouter.setShouldRevert(true); + + // Capture initial tokenIn balances for later verification. + uint256 initialComposerBalance = IERC20(bOFT.token()).balanceOf(address(bComposer)); + uint256 initialReceiverBalance = IERC20(bOFT.token()).balanceOf(receiver); + + // ------------------------------ + // 3. Simulate Sending the Message + // ------------------------------ + // Prank as the authorized endpoint to call lzCompose. + vm.prank(address(endpoints[bEid])); + + // Execute lzCompose with the encoded full message. + bComposer.lzCompose( + address(bOFT), // The originating OFT address. + bytes32(0), // guid (unused in this test) + fullMessage, + address(this), // executor (unused in this test) + bytes("") // extraData (unused in this test) + ); + + // ------------------------------ + // 4. Verify Fallback Logic Execution + // ------------------------------ + // Since the swap reverted, the catch block should have transferred swapAmountIn of tokenIn + // directly from bComposer to the receiver. + assertEq( + IERC20(bOFT.token()).balanceOf(address(bComposer)), + initialComposerBalance - swapAmountIn, + "bComposer TokenIn balance incorrect after fallback transfer" + ); + + assertEq( + IERC20(bOFT.token()).balanceOf(receiver), + initialReceiverBalance + swapAmountIn, + "Receiver TokenIn balance incorrect after fallback transfer" + ); + } + /** * @notice Tests that `lzCompose` reverts when called with an unauthorized OFT. * @dev Attempts to invoke `lzCompose` with a different OFT address and expects a revert. diff --git a/examples/oft-composer-library/test/mocks/SwapRouterMock.sol b/examples/oft-composer-library/test/mocks/SwapRouterMock.sol index 1910aa61c..25c201a2c 100644 --- a/examples/oft-composer-library/test/mocks/SwapRouterMock.sol +++ b/examples/oft-composer-library/test/mocks/SwapRouterMock.sol @@ -3,12 +3,8 @@ pragma solidity ^0.8.20; // Import the ISwapRouter interface from Uniswap V3 Periphery import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; - import { IOFT } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; - import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -// Import the ERC20Mock to simulate token behavior import { ERC20Mock } from "../mocks/ERC20Mock.sol"; /** @@ -33,6 +29,9 @@ contract SwapRouterMock is ISwapRouter { // Predefined amountOut to return on swaps uint256 private predefinedAmountOut; + // Flag to simulate revert behavior + bool public shouldRevert; + /** * @notice Initializes the SwapRouterMock with predefined tokens and amountOut. * @param _oftIn The OFT address being swapped from. @@ -53,21 +52,35 @@ contract SwapRouterMock is ISwapRouter { predefinedAmountOut = _newAmountOut; } + /** + * @notice Sets whether the swap should revert to simulate failure conditions. + * @param _shouldRevert If true, the swap will revert. + */ + function setShouldRevert(bool _shouldRevert) external { + shouldRevert = _shouldRevert; + } + /** * @notice Mocks the exactInputSingle function of Uniswap V3's ISwapRouter. * @param params The parameters for the swap, as defined in ISwapRouter.ExactInputSingleParams. * @return amountOut The amount of tokenOut received from the swap. * * @dev This function records the swap parameters and returns a predefined amountOut. - * It also simulates the token transfer by minting tokenOut to the recipient. + * It simulates the token transfer by minting tokenOut to the recipient. + * If shouldRevert is true, it reverts to simulate a swap failure. */ function exactInputSingle( ExactInputSingleParams calldata params ) external payable override returns (uint256 amountOut) { - // Validate amountIn + // Simulate a swap failure if requested. + if (shouldRevert) { + revert("SwapRouterMock: swap reverted as requested"); + } + + // Validate amountIn. require(params.amountIn > 0, "SwapRouterMock: amountIn must be greater than zero"); - // Record the parameters of the swap + // Record the parameters of the swap. lastSender = msg.sender; lastTokenIn = params.tokenIn; lastTokenOut = params.tokenOut; @@ -76,46 +89,36 @@ contract SwapRouterMock is ISwapRouter { lastAmountIn = params.amountIn; lastAmountOut = predefinedAmountOut; - // Simulate the transfer of tokenIn from the sender to the SwapRouterMock + // Simulate the transfer of tokenIn from the sender to the SwapRouterMock. tokenIn.transferFrom(msg.sender, address(this), params.amountIn); - // Simulate minting tokenOut to the recipient + // Simulate minting tokenOut to the recipient. tokenOut.mint(params.recipient, predefinedAmountOut); - // Return the predefined amountOut + // Return the predefined amountOut. return predefinedAmountOut; } - /** - * @notice Mocks other functions from the ISwapRouter interface. - * @dev These functions are left unimplemented and will revert if called, indicating they are not supported in the mock. - */ + // The following functions are not implemented in this mock and will revert if called. - // Swaps with exact input along a specified path function exactInput( ISwapRouter.ExactInputParams calldata /*params*/ ) external payable override returns (uint256 /*amountOut*/) { revert("SwapRouterMock: exactInput not implemented"); } - // Swaps to receive an exact amount of output tokens with single-hop function exactOutputSingle( ISwapRouter.ExactOutputSingleParams calldata /*params*/ ) external payable override returns (uint256 /*amountIn*/) { revert("SwapRouterMock: exactOutputSingle not implemented"); } - // Swaps to receive an exact amount of output tokens along a specified path function exactOutput( ISwapRouter.ExactOutputParams calldata /*params*/ ) external payable override returns (uint256 /*amountIn*/) { revert("SwapRouterMock: exactOutput not implemented"); } - /** - * @notice Mocks the uniswapV3SwapCallback function from IUniswapV3SwapCallback. - * @dev This mock does not handle actual swap callbacks and will revert if called. - */ function uniswapV3SwapCallback( int256 /*amount0Delta*/, int256 /*amount1Delta*/, From 54230f8c9958ab4f4d55461350e9fa1b04245f3f Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Wed, 5 Mar 2025 17:36:05 -0800 Subject: [PATCH 14/47] chore: add optimizer to toml --- examples/oft-composer-library/foundry.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/oft-composer-library/foundry.toml b/examples/oft-composer-library/foundry.toml index 7af2bea24..3595660e3 100644 --- a/examples/oft-composer-library/foundry.toml +++ b/examples/oft-composer-library/foundry.toml @@ -5,6 +5,8 @@ out = 'out' test = 'test/foundry' cache_path = 'cache/foundry' verbosity = 3 +optimizer = true +optimizer_runs = 20_000 libs = [ # We provide a set of useful contract utilities # in the lib directory of @layerzerolabs/toolbox-foundry: From 5ef855704bbcab061a0afa7bf99bca227c0c2d95 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Thu, 27 Mar 2025 13:03:05 -0700 Subject: [PATCH 15/47] chore: update README --- examples/oft-composer-library/README.md | 526 +++--------------- examples/oft-composer-library/package.json | 6 +- .../test/hardhat/MyOFT.test.ts | 101 ---- 3 files changed, 83 insertions(+), 550 deletions(-) delete mode 100644 examples/oft-composer-library/test/hardhat/MyOFT.test.ts diff --git a/examples/oft-composer-library/README.md b/examples/oft-composer-library/README.md index 6edc40dc3..1e57bf6bd 100644 --- a/examples/oft-composer-library/README.md +++ b/examples/oft-composer-library/README.md @@ -8,521 +8,157 @@ Homepage | Docs | Developers

-

Omnichain Fungible Token (OFT) Example

+

LayerZero OFT Composer Library

- Quickstart | Configuration | Message Execution Options | Endpoint, MessageLib, & Executor Addresses | DVN Addresses + Quickstart | Configuration | Message Execution Options | Composer Overview

-

Template project for getting started with LayerZero's OFT contract standard.

- -

+ A Composer library to integrate LayerZero composer contracts with the Omnichain Fungible Token (OFT) standard.

-## So what is an Omnichain Fungible Token? - -The Omnichain Fungible Token (OFT) Standard is an ERC20 token that can be transferred across multiple blockchains without asset wrapping or middlechains. - -LayerZero - -This standard works by combining the LayerZero OApp Contract Standard with the ERC20 [`_burn`](https://github.com/LayerZero-Labs/LayerZero-v2/blob/main/packages/layerzero-v2/evm/oapp/contracts/oft/OFT.sol#L80) method, to initiate omnichain send transfers on the source chain, sending a message via the LayerZero protocol, and delivering a function call to the destination contract to [`_mint`](https://github.com/LayerZero-Labs/LayerZero-v2/blob/main/packages/layerzero-v2/evm/oapp/contracts/oft/OFT.sol#L96) the same number of tokens burned, creating a unified supply across all networks connected. - -Read more about what you can do with OFTs by reading the [OFT Quickstart](https://docs.layerzero.network/v2/developers/evm/oft/quickstart) in the LayerZero Documentation. - -## LayerZero Hardhat Helper Tasks - -LayerZero Devtools provides several helper hardhat tasks to easily deploy, verify, configure, connect, and send OFTs cross-chain. - -
- npx hardhat lz:deploy - -
- -Deploys your contract to any of the available networks in your [`hardhat.config.ts`](./hardhat.config.ts) when given a deploy tag (by default contract name) and returns a list of available networks to select for the deployment. For specifics around all deployment options, please refer to the [Deploying Contracts](https://docs.layerzero.network/v2/developers/evm/create-lz-oapp/deploying) section of the documentation. LayerZero's `lz:deploy` utilizes `hardhat-deploy`. - -```yml -'arbitrum-sepolia': { - eid: EndpointId.ARBSEP_V2_TESTNET, - url: process.env.RPC_URL_ARBSEP_TESTNET, - accounts, -}, -'base-sepolia': { - eid: EndpointId.BASESEP_V2_TESTNET, - url: process.env.RPC_URL_BASE_TESTNET, - accounts, -}, -``` - -
- -
- npx hardhat lz:oapp:config:init --oapp-config YOUR_OAPP_CONFIG --contract-name CONTRACT_NAME - -
- -Initializes a `layerzero.config.ts` file for all available pathways between your hardhat networks with the current LayerZero default placeholder settings. This task can be incredibly useful for correctly formatting your config file. - -You can run this task by providing the `contract-name` you want to set for the config and `file-name` you want to generate: - -```bash -npx hardhat lz:oapp:config:init --contract-name CONTRACT_NAME --oapp-config FILE_NAME -``` - -This will create a `layerzero.config.ts` in your working directory populated with your contract name and connections for every pathway possible between your hardhat networks: - -```yml -import { EndpointId } from '@layerzerolabs/lz-definitions' - -const arbsepContract = { - eid: EndpointId.ARBSEP_V2_TESTNET, - contractName: 'MyOFT', -} -const sepoliaContract = { - eid: EndpointId.SEPOLIA_V2_TESTNET, - contractName: 'MyOFT', -} - -export default { - contracts: [{ contract: arbsepContract }, { contract: sepoliaContract }], - connections: [ - { - from: arbsepContract, - to: sepoliaContract, - config: { - sendLibrary: '0x4f7cd4DA19ABB31b0eC98b9066B9e857B1bf9C0E', - receiveLibraryConfig: { receiveLibrary: '0x75Db67CDab2824970131D5aa9CECfC9F69c69636', gracePeriod: 0 }, - sendConfig: { - executorConfig: { maxMessageSize: 10000, executor: '0x5Df3a1cEbBD9c8BA7F8dF51Fd632A9aef8308897' }, - ulnConfig: { - confirmations: 1, - requiredDVNs: ['0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8'], - optionalDVNs: [], - optionalDVNThreshold: 0, - }, - }, - // receiveConfig: { - // ulnConfig: { - // confirmations: 2, - // requiredDVNs: ['0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8'], - // optionalDVNs: [], - // optionalDVNThreshold: 0, - // }, - // }, - }, - }, - { - from: sepoliaContract, - to: arbsepContract, - config: { - sendLibrary: '0xcc1ae8Cf5D3904Cef3360A9532B477529b177cCE', - receiveLibraryConfig: { receiveLibrary: '0xdAf00F5eE2158dD58E0d3857851c432E34A3A851', gracePeriod: 0 }, - // sendConfig: { - // executorConfig: { maxMessageSize: 10000, executor: '0x718B92b5CB0a5552039B593faF724D182A881eDA' }, - // ulnConfig: { - // confirmations: 2, - // requiredDVNs: ['0x8eebf8b423B73bFCa51a1Db4B7354AA0bFCA9193'], - // optionalDVNs: [], - // optionalDVNThreshold: 0, - // }, - // }, - receiveConfig: { - ulnConfig: { - confirmations: 1, - requiredDVNs: ['0x8eebf8b423B73bFCa51a1Db4B7354AA0bFCA9193'], - optionalDVNs: [], - optionalDVNThreshold: 0, - }, - }, - }, - }, - ], -} -``` - -
- -
- npx hardhat lz:oapp:config:wire --oapp-config YOUR_OAPP_CONFIG - -
- -Calls the configuration functions between your deployed OApp contracts on every chain based on the provided `layerzero.config.ts`. - -Running `lz:oapp:wire` will make the following function calls per pathway connection for a fully defined config file using your specified settings and your environment variables (Private Keys and RPCs): - -- function setPeer(uint32 \_eid, bytes32 \_peer) public virtual onlyOwner {} +

+- [What is an Omnichain Fungible Token?](#what-is-an-omnichain-fungible-token) +- [Using Composer with OFTs](#using-composer-with-ofts) +- [LayerZero Hardhat Helper Tasks](#layerzero-hardhat-helper-tasks) +- [Developing & Deploying Contracts](#developing-contracts) +- [Connecting Contracts](#connecting-contracts) +

-- function setConfig(address \_oapp, address \_lib, SetConfigParam[] calldata \_params) external onlyRegistered(\_lib) {} +## What is an Omnichain Fungible Token? -- function setEnforcedOptions(EnforcedOptionParam[] calldata \_enforcedOptions) public virtual onlyOwner {} +The Omnichain Fungible Token (OFT) standard extends the ERC20 interface to enable seamless cross-chain token transfers without the need for asset wrapping or intermediary chains. By combining LayerZero’s OApp Contract Standard with ERC20’s `_burn` and `_mint` methods, OFTs maintain a unified token supply across multiple blockchains. -- function setSendLibrary(address \_oapp, uint32 \_eid, address \_newLib) external onlyRegisteredOrDefault(\_newLib) isSendLib(\_newLib) onlySupportedEid(\_newLib, \_eid) {} +LayerZero -- function setReceiveLibrary(address \_oapp, uint32 \_eid, address \_newLib, uint256 \_gracePeriod) external onlyRegisteredOrDefault(\_newLib) isReceiveLib(\_newLib) onlySupportedEid(\_newLib, \_eid) {} +Learn more about OFTs in the [OFT Quickstart](https://docs.layerzero.network/v2/developers/evm/oft/quickstart). -To use this task, run: +## Using Composer with OFTs -```bash -npx hardhat lz:oapp:wire --oapp-config YOUR_LAYERZERO_CONFIG_FILE -``` +This repository is not only a template for OFTs, it’s a fully featured **composer library** that empowers you to build composable, cross-chain applications using LayerZero’s composer contracts in combination with the OFT standard. -Whenever you make changes to the configuration, run `lz:oapp:wire` again. The task will check your current configuration, and only apply NEW changes. +For example, our repository includes an example contract (see [UniswapV3Composer.sol](./path/to/UniswapV3Composer.sol)) that demonstrates how to: -To use a Gnosis Safe multisig as the signer for these transactions, add the following to each network in your `hardhat.config.ts` and add the `--safe` flag to `lz:oapp:wire --safe`: +- Receive cross-chain messages via LayerZero. +- Decode composable messages (using `OFTComposeMsgCodec`) to extract parameters. +- Execute token swaps on Uniswap V3 after an OFT transfer. +- Gracefully handle failures by refunding tokens. -```yml -// hardhat.config.ts +This composability approach lets you extend basic omnichain token transfers with additional logic—such as token swaps, lending, or other decentralized finance features. For more information on composability, visit the [What is Composability?](https://docs.layerzero.network/v2/concepts/applications/composer-standard) documentation and the [EVM Composer Overview](https://docs.layerzero.network/v2/developers/evm/composer/overview). -networks: { - // Include configurations for other networks as needed - fuji: { - /* ... */ - // Network-specific settings - safeConfig: { - safeUrl: 'http://something', // URL of the Safe API, not the Safe itself - safeAddress: 'address' - } - } -} -``` - -
-
- npx hardhat lz:oapp:config:get --oapp-config YOUR_OAPP_CONFIG +## LayerZero Hardhat Helper Tasks -
+LayerZero Devtools offers several helper tasks to deploy, configure, connect, and wire your OFT and composer contracts across multiple chains. These tasks streamline operations like: -Returns your current OApp's configuration for each chain and pathway in 3 columns: +- **Deploying Contracts:** -- **Custom Configuration**: the changes that your `layerzero.config.ts` currently has set + ```bash + npx hardhat lz:deploy + ``` -- **Default Configuration**: the default placeholder configuration that LayerZero provides + Deploy your contracts to networks specified in your `hardhat.config.ts`. -- **Active Configuration**: the active configuration that applies to the message pathway (Defaults + Custom Values) +- **Initializing Configuration:** -If you do NOT explicitly set each configuration parameter, your OApp will fallback to the placeholder parameters in the default config. + ```bash + npx hardhat lz:oapp:config:init --contract-name YOUR_CONTRACT_NAME --oapp-config FILE_NAME + ``` -```bash -┌────────────────────┬───────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┐ -│ │ Custom OApp Config │ Default OApp Config │ Active OApp Config │ -├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ -│ localNetworkName │ arbsep │ arbsep │ arbsep │ -├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ -│ remoteNetworkName │ sepolia │ sepolia │ sepolia │ -├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ -│ sendLibrary │ 0x4f7cd4DA19ABB31b0eC98b9066B9e857B1bf9C0E │ 0x4f7cd4DA19ABB31b0eC98b9066B9e857B1bf9C0E │ 0x4f7cd4DA19ABB31b0eC98b9066B9e857B1bf9C0E │ -├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ -│ receiveLibrary │ 0x75Db67CDab2824970131D5aa9CECfC9F69c69636 │ 0x75Db67CDab2824970131D5aa9CECfC9F69c69636 │ 0x75Db67CDab2824970131D5aa9CECfC9F69c69636 │ -├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ -│ sendUlnConfig │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ -│ │ │ confirmations │ 1 │ │ │ confirmations │ 1 │ │ │ confirmations │ 1 │ │ -│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ -│ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ -│ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ -│ │ │ │ └───┴────────────────────────────────────────────┘ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │ -│ │ │ │ │ │ │ │ │ │ │ │ │ │ -│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ -│ │ │ optionalDVNs │ │ │ │ optionalDVNs │ │ │ │ optionalDVNs │ │ │ -│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ -│ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNThreshold │ 0 │ │ -│ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ -│ │ │ │ │ -├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ -│ sendExecutorConfig │ ┌────────────────┬────────────────────────────────────────────┐ │ ┌────────────────┬────────────────────────────────────────────┐ │ ┌────────────────┬────────────────────────────────────────────┐ │ -│ │ │ executor │ 0x5Df3a1cEbBD9c8BA7F8dF51Fd632A9aef8308897 │ │ │ executor │ 0x5Df3a1cEbBD9c8BA7F8dF51Fd632A9aef8308897 │ │ │ executor │ 0x5Df3a1cEbBD9c8BA7F8dF51Fd632A9aef8308897 │ │ -│ │ ├────────────────┼────────────────────────────────────────────┤ │ ├────────────────┼────────────────────────────────────────────┤ │ ├────────────────┼────────────────────────────────────────────┤ │ -│ │ │ maxMessageSize │ 10000 │ │ │ maxMessageSize │ 10000 │ │ │ maxMessageSize │ 10000 │ │ -│ │ └────────────────┴────────────────────────────────────────────┘ │ └────────────────┴────────────────────────────────────────────┘ │ └────────────────┴────────────────────────────────────────────┘ │ -│ │ │ │ │ -├────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤ -│ receiveUlnConfig │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ ┌──────────────────────┬────────────────────────────────────────────────────┐ │ -│ │ │ confirmations │ 2 │ │ │ confirmations │ 2 │ │ │ confirmations │ 2 │ │ -│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ -│ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ │ requiredDVNs │ ┌───┬────────────────────────────────────────────┐ │ │ -│ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ │ │ │ 0 │ 0x53f488E93b4f1b60E8E83aa374dBe1780A1EE8a8 │ │ │ -│ │ │ │ └───┴────────────────────────────────────────────┘ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │ │ │ └───┴────────────────────────────────────────────┘ │ │ -│ │ │ │ │ │ │ │ │ │ │ │ │ │ -│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ -│ │ │ optionalDVNs │ │ │ │ optionalDVNs │ │ │ │ optionalDVNs │ │ │ -│ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ ├──────────────────────┼────────────────────────────────────────────────────┤ │ -│ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNThreshold │ 0 │ │ │ optionalDVNThreshold │ 0 │ │ -│ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ └──────────────────────┴────────────────────────────────────────────────────┘ │ -│ │ │ │ │ -└────────────────────┴───────────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┘ -``` + Generate a default `layerzero.config.ts` file for setting up cross-chain pathways. -
-
- npx hardhat lz:oapp:config:get:executor --oapp-config YOUR_OAPP_CONFIG +- **Wiring Contracts:** -
+ ```bash + npx hardhat lz:oapp:wire --oapp-config YOUR_LAYERZERO_CONFIG_FILE + ``` -Returns the LayerZero Executor config for each network in your `hardhat.config.ts`. You can use this method to see the max destination gas in wei (`nativeCap`) you can request in your [`execution options`](https://docs.layerzero.network/v2/developers/evm/gas-settings/options). + Connect your deployed contracts by executing the necessary configuration functions. -```bash -┌───────────────────┬────────────────────────────────────────────┐ -│ localNetworkName │ mantle │ -├───────────────────┼────────────────────────────────────────────┤ -│ remoteNetworkName │ polygon │ -├───────────────────┼────────────────────────────────────────────┤ -│ executorDstConfig │ ┌────────────────┬───────────────────────┐ │ -│ │ │ baseGas │ 85000 │ │ -│ │ ├────────────────┼───────────────────────┤ │ -│ │ │ multiplierBps │ 12000 │ │ -│ │ ├────────────────┼───────────────────────┤ │ -│ │ │ floorMarginUSD │ 5000000000000000000 │ │ -│ │ ├────────────────┼───────────────────────┤ │ -│ │ │ nativeCap │ 681000000000000000000 │ │ -│ │ └────────────────┴───────────────────────┘ │ -│ │ │ -└───────────────────┴────────────────────────────────────────────┘ -``` +- **Viewing Current Configurations:** + ```bash + npx hardhat lz:oapp:config:get --oapp-config YOUR_OAPP_CONFIG + ``` + Review the active, custom, and default configurations for each pathway. -
+For more details, refer to the [LayerZero Hardhat Helper Tasks Documentation](https://docs.layerzero.network/v2/developers/evm/create-lz-oapp/deploying). ## Developing Contracts -#### Installing dependencies +### Installing dependencies -We recommend using `pnpm` as a package manager (but you can of course use a package manager of your choice): +We recommend using `pnpm` (or your preferred package manager): ```bash pnpm install ``` -#### Compiling your contracts +### Compiling your contracts -This project supports both `hardhat` and `forge` compilation. By default, the `compile` command will execute both: +This project supports both Hardhat and Forge compilations: ```bash pnpm compile ``` -If you prefer one over the other, you can use the tooling-specific commands: +To compile with a specific tool: ```bash -pnpm compile:forge pnpm compile:hardhat +pnpm compile:forge ``` -Or adjust the `package.json` to for example remove `forge` build: - -```diff -- "compile": "$npm_execpath run compile:forge && $npm_execpath run compile:hardhat", -- "compile:forge": "forge build", -- "compile:hardhat": "hardhat compile", -+ "compile": "hardhat compile" -``` - -#### Running tests +### Running tests -Similarly to the contract compilation, we support both `hardhat` and `forge` tests. By default, the `test` command will execute both: +Both Hardhat and Forge tests are supported: ```bash pnpm test ``` -If you prefer one over the other, you can use the tooling-specific commands: +Or run specific tests: ```bash -pnpm test:forge pnpm test:hardhat -``` - -Or adjust the `package.json` to for example remove `hardhat` tests: - -```diff -- "test": "$npm_execpath test:forge && $npm_execpath test:hardhat", -- "test:forge": "forge test", -- "test:hardhat": "$npm_execpath hardhat test" -+ "test": "forge test" +pnpm test:forge ``` ## Deploying Contracts -Set up deployer wallet/account: - -- Rename `.env.example` -> `.env` -- Choose your preferred means of setting up your deployer wallet/account: - -``` -MNEMONIC="test test test test test test test test test test test junk" -or... -PRIVATE_KEY="0xabc...def" -``` - -- Fund this address with the corresponding chain's native tokens you want to deploy to. +1. **Set Up Deployer Wallet:** -To deploy your contracts to your desired blockchains, run the following command in your project's folder: + - Rename `.env.example` to `.env`. + - Configure your mnemonic or private key. -```bash -npx hardhat lz:deploy -``` +2. **Fund Your Account:** + Ensure your deployer wallet is funded with the appropriate native tokens. -More information about available CLI arguments can be found using the `--help` flag: - -```bash -npx hardhat lz:deploy --help -``` - -By following these steps, you can focus more on creating innovative omnichain solutions and less on the complexities of cross-chain communication. - -

+3. **Deploy Contracts:** + ```bash + npx hardhat lz:deploy + ``` + Use the `--help` flag for additional CLI options. ## Connecting Contracts -### Ethereum Configurations +1. **Configure Connections:** + Generate and customize your `layerzero.config.ts` file: -Fill out your `layerzero.config.ts` with the contracts you want to connect. You can generate the default config file for your declared hardhat networks by running: + ```bash + npx hardhat lz:oapp:config:init --contract-name [YOUR_CONTRACT_NAME] --oapp-config [CONFIG_NAME] + ``` -```bash -npx hardhat lz:oapp:config:init --contract-name [YOUR_CONTRACT_NAME] --oapp-config [CONFIG_NAME] -``` +2. **Define Network Pathways:** + Specify contracts and their interconnections (e.g., Ethereum <--> Arbitrum) in your configuration file. -> [!NOTE] -> You may need to change the contract name if you're deploying multiple OApp contracts on different chains (e.g., OFT and OFT Adapter). +3. **Apply Configuration:** + Connect your deployed contracts by running: + ```bash + npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts + ``` -
+Join our community on [Discord](https://discord-layerzero.netlify.app/discord) or follow us on [Twitter](https://twitter.com/LayerZero_Labs) for updates. -```typescript -const ethereumContract: OmniPointHardhat = { - eid: EndpointId.ETHEREUM_V2_MAINNET, - contractName: "MyOFTAdapter", -}; +--- -const arbitrumContract: OmniPointHardhat = { - eid: EndpointId.ARBITRUM_V2_MAINNET, - contractName: "MyOFT", -}; -``` - -Then define the pathway you want to create from and to each contract: - -```typescript -connections: [ - // ETH <--> ARB PATHWAY: START - { - from: ethereumContract, - to: arbitrumContract, - }, - { - from: arbitrumContract, - to: ethereumContract, - }, - // ETH <--> ARB PATHWAY: END -]; -``` - -Finally, define the config settings for each direction of the pathway: - -```typescript -connections: [ - // ETH <--> ARB PATHWAY: START - { - from: ethereumContract, - to: arbitrumContract, - config: { - sendLibrary: contractsConfig.ethereum.sendLib302, - receiveLibraryConfig: { - receiveLibrary: contractsConfig.ethereum.receiveLib302, - gracePeriod: BigInt(0), - }, - // Optional Receive Library Timeout for when the Old Receive Library Address will no longer be valid - receiveLibraryTimeoutConfig: { - lib: "0x0000000000000000000000000000000000000000", - expiry: BigInt(0), - }, - // Optional Send Configuration - // @dev Controls how the `from` chain sends messages to the `to` chain. - sendConfig: { - executorConfig: { - maxMessageSize: 10000, - // The configured Executor address - executor: contractsConfig.ethereum.executor, - }, - ulnConfig: { - // The number of block confirmations to wait on BSC before emitting the message from the source chain. - confirmations: BigInt(15), - // The address of the DVNs you will pay to verify a sent message on the source chain ). - // The destination tx will wait until ALL `requiredDVNs` verify the message. - requiredDVNs: [ - contractsConfig.ethereum.horizenDVN, // Horizen - contractsConfig.ethereum.polyhedraDVN, // Polyhedra - contractsConfig.ethereum.animocaBlockdaemonDVN, // Animoca-Blockdaemon (only available on ETH <-> Arbitrum One) - contractsConfig.ethereum.lzDVN, // LayerZero Labs - ], - // The address of the DVNs you will pay to verify a sent message on the source chain ). - // The destination tx will wait until the configured threshold of `optionalDVNs` verify a message. - optionalDVNs: [], - // The number of `optionalDVNs` that need to successfully verify the message for it to be considered Verified. - optionalDVNThreshold: 0, - }, - }, - // Optional Receive Configuration - // @dev Controls how the `from` chain receives messages from the `to` chain. - receiveConfig: { - ulnConfig: { - // The number of block confirmations to expect from the `to` chain. - confirmations: BigInt(20), - // The address of the DVNs your `receiveConfig` expects to receive verifications from on the `from` chain ). - // The `from` chain's OApp will wait until the configured threshold of `requiredDVNs` verify the message. - requiredDVNs: [ - contractsConfig.ethereum.lzDVN, // LayerZero Labs DVN - contractsConfig.ethereum.animocaBlockdaemonDVN, // Blockdaemon-Animoca - contractsConfig.ethereum.horizenDVN, // Horizen Labs - contractsConfig.ethereum.polyhedraDVN, // Polyhedra - ], - // The address of the `optionalDVNs` you expect to receive verifications from on the `from` chain ). - // The destination tx will wait until the configured threshold of `optionalDVNs` verify the message. - optionalDVNs: [], - // The number of `optionalDVNs` that need to successfully verify the message for it to be considered Verified. - optionalDVNThreshold: 0, - }, - }, - // Optional Enforced Options Configuration - // @dev Controls how much gas to use on the `to` chain, which the user pays for on the source `from` chain. - enforcedOptions: [ - { - msgType: 1, - optionType: ExecutorOptionType.LZ_RECEIVE, - gas: 65000, - value: 0, - }, - { - msgType: 2, - optionType: ExecutorOptionType.LZ_RECEIVE, - gas: 65000, - value: 0, - }, - { - msgType: 2, - optionType: ExecutorOptionType.COMPOSE, - index: 0, - gas: 50000, - value: 0, - }, - ], - }, - }, - { - from: arbitrumContract, - to: ethereumContract, - }, - // ETH <--> ARB PATHWAY: END -]; -``` - -To set these config settings, run: - -```bash -npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts -``` - -

- Join our community on Discord | Follow us on Twitter -

+By following these steps, you leverage LayerZero’s composer library to build and deploy innovative, composable cross-chain applications powered by the OFT standard. diff --git a/examples/oft-composer-library/package.json b/examples/oft-composer-library/package.json index 0041b015f..6f221f73a 100644 --- a/examples/oft-composer-library/package.json +++ b/examples/oft-composer-library/package.json @@ -1,6 +1,6 @@ { "name": "@layerzerolabs/oft-composer-library-example", - "version": "0.5.1", + "version": "0.0.1", "private": true, "license": "MIT", "scripts": { @@ -20,9 +20,6 @@ "ethers": "^5.7.2", "hardhat-deploy": "^0.12.1" }, - "dependencies": { - "@uniswap/v3-core": "^1.0.1" - }, "devDependencies": { "@babel/core": "^7.23.9", "@layerzerolabs/devtools-evm-hardhat": "^2.0.1", @@ -47,6 +44,7 @@ "@types/chai": "^4.3.11", "@types/mocha": "^10.0.6", "@types/node": "~18.18.14", + "@uniswap/v3-core": "^1.0.1", "@uniswap/v3-periphery": "^1.4.4", "chai": "^4.4.1", "concurrently": "~9.1.0", diff --git a/examples/oft-composer-library/test/hardhat/MyOFT.test.ts b/examples/oft-composer-library/test/hardhat/MyOFT.test.ts deleted file mode 100644 index 257bc5218..000000000 --- a/examples/oft-composer-library/test/hardhat/MyOFT.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { expect } from 'chai' -import { Contract, ContractFactory } from 'ethers' -import { deployments, ethers } from 'hardhat' - -import { Options } from '@layerzerolabs/lz-v2-utilities' - -describe('MyOFT Test', function () { - // Constant representing a mock Endpoint ID for testing purposes - const eidA = 1 - const eidB = 2 - // Declaration of variables to be used in the test suite - let MyOFT: ContractFactory - let EndpointV2Mock: ContractFactory - let ownerA: SignerWithAddress - let ownerB: SignerWithAddress - let endpointOwner: SignerWithAddress - let myOFTA: Contract - let myOFTB: Contract - let mockEndpointV2A: Contract - let mockEndpointV2B: Contract - - // Before hook for setup that runs once before all tests in the block - before(async function () { - // Contract factory for our tested contract - // - // We are using a derived contract that exposes a mint() function for testing purposes - MyOFT = await ethers.getContractFactory('MyOFTMock') - - // Fetching the first three signers (accounts) from Hardhat's local Ethereum network - const signers = await ethers.getSigners() - - ;[ownerA, ownerB, endpointOwner] = signers - - // The EndpointV2Mock contract comes from @layerzerolabs/test-devtools-evm-hardhat package - // and its artifacts are connected as external artifacts to this project - // - // Unfortunately, hardhat itself does not yet provide a way of connecting external artifacts, - // so we rely on hardhat-deploy to create a ContractFactory for EndpointV2Mock - // - // See https://github.com/NomicFoundation/hardhat/issues/1040 - const EndpointV2MockArtifact = await deployments.getArtifact('EndpointV2Mock') - EndpointV2Mock = new ContractFactory(EndpointV2MockArtifact.abi, EndpointV2MockArtifact.bytecode, endpointOwner) - }) - - // beforeEach hook for setup that runs before each test in the block - beforeEach(async function () { - // Deploying a mock LZEndpoint with the given Endpoint ID - mockEndpointV2A = await EndpointV2Mock.deploy(eidA) - mockEndpointV2B = await EndpointV2Mock.deploy(eidB) - - // Deploying two instances of MyOFT contract with different identifiers and linking them to the mock LZEndpoint - myOFTA = await MyOFT.deploy('aOFT', 'aOFT', mockEndpointV2A.address, ownerA.address) - myOFTB = await MyOFT.deploy('bOFT', 'bOFT', mockEndpointV2B.address, ownerB.address) - - // Setting destination endpoints in the LZEndpoint mock for each MyOFT instance - await mockEndpointV2A.setDestLzEndpoint(myOFTB.address, mockEndpointV2B.address) - await mockEndpointV2B.setDestLzEndpoint(myOFTA.address, mockEndpointV2A.address) - - // Setting each MyOFT instance as a peer of the other in the mock LZEndpoint - await myOFTA.connect(ownerA).setPeer(eidB, ethers.utils.zeroPad(myOFTB.address, 32)) - await myOFTB.connect(ownerB).setPeer(eidA, ethers.utils.zeroPad(myOFTA.address, 32)) - }) - - // A test case to verify token transfer functionality - it('should send a token from A address to B address via each OFT', async function () { - // Minting an initial amount of tokens to ownerA's address in the myOFTA contract - const initialAmount = ethers.utils.parseEther('100') - await myOFTA.mint(ownerA.address, initialAmount) - - // Defining the amount of tokens to send and constructing the parameters for the send operation - const tokensToSend = ethers.utils.parseEther('1') - - // Defining extra message execution options for the send operation - const options = Options.newOptions().addExecutorLzReceiveOption(200000, 0).toHex().toString() - - const sendParam = [ - eidB, - ethers.utils.zeroPad(ownerB.address, 32), - tokensToSend, - tokensToSend, - options, - '0x', - '0x', - ] - - // Fetching the native fee for the token send operation - const [nativeFee] = await myOFTA.quoteSend(sendParam, false) - - // Executing the send operation from myOFTA contract - await myOFTA.send(sendParam, [nativeFee, 0], ownerA.address, { value: nativeFee }) - - // Fetching the final token balances of ownerA and ownerB - const finalBalanceA = await myOFTA.balanceOf(ownerA.address) - const finalBalanceB = await myOFTB.balanceOf(ownerB.address) - - // Asserting that the final balances are as expected after the send operation - expect(finalBalanceA).eql(initialAmount.sub(tokensToSend)) - expect(finalBalanceB).eql(tokensToSend) - }) -}) From 818b2f10a4815fd6427601708ea60b87e76b3872 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Thu, 27 Mar 2025 16:53:06 -0700 Subject: [PATCH 16/47] chore: add readme updates --- examples/oft-composer-library/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/oft-composer-library/README.md b/examples/oft-composer-library/README.md index 1e57bf6bd..49b86615b 100644 --- a/examples/oft-composer-library/README.md +++ b/examples/oft-composer-library/README.md @@ -18,13 +18,12 @@ A Composer library to integrate LayerZero composer contracts with the Omnichain Fungible Token (OFT) standard.

-

+ - [What is an Omnichain Fungible Token?](#what-is-an-omnichain-fungible-token) - [Using Composer with OFTs](#using-composer-with-ofts) - [LayerZero Hardhat Helper Tasks](#layerzero-hardhat-helper-tasks) - [Developing & Deploying Contracts](#developing-contracts) - [Connecting Contracts](#connecting-contracts) -

## What is an Omnichain Fungible Token? @@ -38,7 +37,7 @@ Learn more about OFTs in the [OFT Quickstart](https://docs.layerzero.network/v2/ This repository is not only a template for OFTs, it’s a fully featured **composer library** that empowers you to build composable, cross-chain applications using LayerZero’s composer contracts in combination with the OFT standard. -For example, our repository includes an example contract (see [UniswapV3Composer.sol](./path/to/UniswapV3Composer.sol)) that demonstrates how to: +For example, our repository includes an example contract (see [UniswapV3Composer.sol](./contracts/UniswapV3Composer.sol)) that demonstrates how to: - Receive cross-chain messages via LayerZero. - Decode composable messages (using `OFTComposeMsgCodec`) to extract parameters. From e84ea8457f0785f61af07c37ed450e331bd714f0 Mon Sep 17 00:00:00 2001 From: Matthew Krak Date: Thu, 27 Mar 2025 17:03:39 -0700 Subject: [PATCH 17/47] chore: run linter --- examples/oft-composer-library/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/oft-composer-library/README.md b/examples/oft-composer-library/README.md index 49b86615b..4cf7de2c7 100644 --- a/examples/oft-composer-library/README.md +++ b/examples/oft-composer-library/README.md @@ -18,7 +18,6 @@ A Composer library to integrate LayerZero composer contracts with the Omnichain Fungible Token (OFT) standard.

- - [What is an Omnichain Fungible Token?](#what-is-an-omnichain-fungible-token) - [Using Composer with OFTs](#using-composer-with-ofts) - [LayerZero Hardhat Helper Tasks](#layerzero-hardhat-helper-tasks) From 6c6fb792590806c168597310f43e550e62f4c61b Mon Sep 17 00:00:00 2001 From: Krak Date: Wed, 11 Jun 2025 14:49:53 -0700 Subject: [PATCH 18/47] fix: remove changlog --- examples/oft-composer-library/CHANGELOG.md | 270 --------------------- 1 file changed, 270 deletions(-) delete mode 100644 examples/oft-composer-library/CHANGELOG.md diff --git a/examples/oft-composer-library/CHANGELOG.md b/examples/oft-composer-library/CHANGELOG.md deleted file mode 100644 index 4d5e63961..000000000 --- a/examples/oft-composer-library/CHANGELOG.md +++ /dev/null @@ -1,270 +0,0 @@ -# @layerzerolabs/oft-example - -## 0.5.1 - -### Patch Changes - -- 447af65: Use concurrently for parallel compilation task - -## 0.5.0 - -### Minor Changes - -- e2395b5: Add OApp Read Example - -## 0.4.0 - -### Minor Changes - -- aa37daf: Update layerzerolabs packages to 3.0.12 - -## 0.3.1 - -### Patch Changes - -- 9ab480a: foundry.toml QOL improvements - -## 0.3.0 - -### Minor Changes - -- b4a12d3: Update hardhat runtime environment factory to match the new environment constuctor - -## 0.2.15 - -### Patch Changes - -- 893ad66: Update @LayerZero-Labs dependencies to 2.3.39 - -## 0.2.14 - -### Patch Changes - -- d126c52: Update monorepo dependencies and typescript version - -## 0.2.13 - -### Patch Changes - -- 40aebd3: Fix avalanche-testnet url - -## 0.2.12 - -### Patch Changes - -- 218ab72: OpenZeppelin Contracts/Contracts-Upgradeable Upgraded to 5.0.2 - -## 0.2.11 - -### Patch Changes - -- 658ba47: Update to use @layerzerolabs/oapp-evm - -## 0.2.10 - -### Patch Changes - -- 7c4b031: Fix network name suffix in examples - -## 0.2.9 - -### Patch Changes - -- d2ff651: Use @layerzerolabs/oft-evm OFT version - -## 0.2.8 - -### Patch Changes - -- 141d067: Update cache paths - -## 0.2.7 - -### Patch Changes - -- 3ec2912: Fixing changeset race condition in the PR's updating them all -- 58cbd3e: Update to latest lz dependencies - -## 0.2.6 - -### Patch Changes - -- 938ac3d: Improve error reporting on UIntBigIntSchema - -## 0.2.5 - -### Patch Changes - -- f865318: Update @LayerZero-Labs dependencies to 2.3.3 - -## 0.2.4 - -### Patch Changes - -- 835cdbe: Replace Mumbai with Amoy - -## 0.2.3 - -### Patch Changes - -- e16c864: Update @LayerZero-Labs dependencies to 2.1.27 -- e16c864: Update executor config schema & types after update to 2.1.27 - -## 0.2.2 - -### Patch Changes - -- c09680a: Update @LayerZero-Labs dependencies to 2.1.25 -- c09680a: Add eslint-plugin-jest-extended to examples - -## 0.2.1 - -### Patch Changes - -- a6f2fef: Re-export useful types from toolbox-hardhat - -## 0.2.0 - -### Minor Changes - -- a4093ab: Adapt LayerZero package updates, including OApp version 2 - -## 0.1.10 - -### Patch Changes - -- ff6427c: Update @LayerZero-Labs dependencies to 2.1.18 - -## 0.1.9 - -### Patch Changes - -- a5c185f: Take RPC URLs from the environment in the examples - -## 0.1.8 - -### Patch Changes - -- 54cf16e: Silence bigint-buffer warning - -## 0.1.7 - -### Patch Changes - -- e7ef1aa: Update @layerzero-labs dependencies to 2.1.15 - -## 0.1.6 - -### Patch Changes - -- b93a018: Update @layerzero-labs dependencies to 2.1.13 - -## 0.1.5 - -### Patch Changes - -- 855fa36: Update to latest layerzerolabsmonorepo dependencies - -## 0.1.4 - -### Patch Changes - -- c6e3b45: Lock versions of ethers & @openzeppelin/contracts in packages; Put pnpm first in create-lz-oapp - -## 0.1.3 - -### Patch Changes - -- 491b5a5: Upgrade contract Dependencies to 2.1.7 - -## 0.1.2 - -### Patch Changes - -- c8f1739: Fix OFT example tests - -## 0.1.1 - -### Patch Changes - -- 71e355c: Update "@layerzerolabs/\*" dependencies - -## 0.1.0 - -### Minor Changes - -- 6e464f2: Specify EndpointV2 with the "V2" suffix wherever appropriate - -## 0.0.12 - -### Patch Changes - -- 8227742: Update @layerzero-labs dependencies to 2.1.4 -- 9996f00: Updated Readmes and the example rpcs used in createLZOApp - -## 0.0.11 - -### Patch Changes - -- 2007d55: Update example configs; Use dotenv in examples; Use layerzero.config without an extension as a default value for --oapp-config - -## 0.0.10 - -### Patch Changes - -- 151a92e: Improve error handling and introduce node engine specifiers - -## 0.0.9 - -### Patch Changes - -- 5c58d69: Update @layerzerolabs dependencies to 2.1.3 - -## 0.0.8 - -### Patch Changes - -- f0036c5: Use monorepo 2.1.2 released dependencies - -## 0.0.7 - -### Patch Changes - -- 7aaf750: Fix compile & tests scripts for npm - -## 0.0.6 - -### Patch Changes - -- 0877186: Update @layerzerolabs dependencies to 2.0.25 and 2.0.26-rc1 - -## 0.0.5 - -### Patch Changes - -- 1e375c9: Adding EVM testing abilities for hardhat and foundry - -## 0.0.4 - -### Patch Changes - -- af8cc25: Update dependencies - -## 0.0.3 - -### Patch Changes - -- 73b37d0: Include solidity-bytes-utils in toolbox-foundry - -## 0.0.2 - -### Patch Changes - -- 6483544: Update dependency versions -- 70646b4: Add missing dependencies - -## 0.0.1 - -### Patch Changes - -- b74afbe: Initial 0.0.1 version From 589ba1973bdb5177adc8cff26e53312df42c5c2c Mon Sep 17 00:00:00 2001 From: Krak Date: Wed, 11 Jun 2025 15:14:04 -0700 Subject: [PATCH 19/47] chore: add create-lz-oapp example --- .changeset/brown-donkeys-trade.md | 5 +++++ packages/create-lz-oapp/src/config.ts | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 .changeset/brown-donkeys-trade.md diff --git a/.changeset/brown-donkeys-trade.md b/.changeset/brown-donkeys-trade.md new file mode 100644 index 000000000..efa01983f --- /dev/null +++ b/.changeset/brown-donkeys-trade.md @@ -0,0 +1,5 @@ +--- +"create-lz-oapp": patch +--- + +Adds OFT composer library diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index 009f551b5..d97d7e0c7 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -214,6 +214,17 @@ export const getExamples = (): Example[] => { }, ] : []), + ...(process.env.LZ_ENABLE_COMPOSER_EXAMPLE + ? [ + { + id: 'oft-composer-library', + label: 'OFT Composer Library', + repository, + directory: 'examples/oft-composer-library', + ref, + }, + ] + : []), ...(process.env.LZ_ENABLE_EXPERIMENTAL_OMNI_CALL_EXAMPLE ? [ { From 86b1820a1e6293bbf4b36bd96f7a27b0ce7a1740 Mon Sep 17 00:00:00 2001 From: Krak Date: Tue, 24 Jun 2025 10:15:39 -0700 Subject: [PATCH 20/47] chore: respond to feedback --- .../contracts/IUniswapV3Composer.sol | 48 ++++++++++ .../contracts/UniswapV3Composer.sol | 90 +++++++------------ .../test/foundry/UniswapV3Composer.t.sol | 16 ++-- 3 files changed, 89 insertions(+), 65 deletions(-) create mode 100644 examples/oft-composer-library/contracts/IUniswapV3Composer.sol diff --git a/examples/oft-composer-library/contracts/IUniswapV3Composer.sol b/examples/oft-composer-library/contracts/IUniswapV3Composer.sol new file mode 100644 index 000000000..4997ffc25 --- /dev/null +++ b/examples/oft-composer-library/contracts/IUniswapV3Composer.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @title IUniswapV3Composer + * + * @notice Interface defining events and errors for the UniswapV3Composer contract. + * + * @dev This interface helps with code organization, testing, and reusability by separating + * contract definitions from implementation logic. + */ +interface IUniswapV3Composer { + /// @notice Custom errors for more gas-efficient reverts. + error InvalidSwapRouter(); + error InvalidEndpoint(); + error InvalidOFT(); + error UnauthorizedOFT(); + error UnauthorizedEndpoint(); + + /** + * @notice Emitted when a token swap is successfully executed. + * + * @param srcSender The bytes32 address of the user initiating the swap on the source chain. + * @param recipient The address of the recipient of the swapped tokens. + * @param tokenIn The address of the ERC20 token being swapped from (OFT). + * @param tokenOut The address of the ERC20 token being swapped to. + * @param amountIn The amount of `tokenIn` being swapped. + * @param amountOut The amount of `tokenOut` received from the swap. + */ + event SwapExecuted( + bytes32 indexed srcSender, + address recipient, + address tokenIn, + address tokenOut, + uint256 amountIn, + uint256 amountOut + ); + + /** + * @notice Emitted when a token swap fails and the OFT tokens are refunded to the recipient. + * + * @param srcSender The bytes32 address of the user initiating the swap on the source chain. + * @param tokenIn The address of the ERC20 token being swapped from (OFT). + * @param recipient The address of the recipient of the OFT tokens. + * @param amountIn The amount of `tokenIn` being refunded. + */ + event SwapFailedAndRefunded(bytes32 indexed srcSender, address tokenIn, address recipient, uint256 amountIn); +} \ No newline at end of file diff --git a/examples/oft-composer-library/contracts/UniswapV3Composer.sol b/examples/oft-composer-library/contracts/UniswapV3Composer.sol index 3d02036a9..3f105141f 100644 --- a/examples/oft-composer-library/contracts/UniswapV3Composer.sol +++ b/examples/oft-composer-library/contracts/UniswapV3Composer.sol @@ -10,6 +10,9 @@ import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRou import { IOAppComposer } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppComposer.sol"; import { IOFT } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol"; +import { IOAppCore } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol"; + +import { IUniswapV3Composer } from "./IUniswapV3Composer.sol"; /** * @title UniswapV3Composer @@ -18,73 +21,47 @@ import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTCom * * @dev This contract inherits from IOAppComposer and interacts with Uniswap V3's SwapRouter to execute token swaps. */ -contract UniswapV3Composer is IOAppComposer { +contract UniswapV3Composer is IOAppComposer, IUniswapV3Composer { using SafeERC20 for IERC20; /// @notice The Uniswap V3 SwapRouter used to perform token swaps. - ISwapRouter public immutable swapRouter; - - /// @notice The LayerZero Endpoint address for cross-chain communication. - address public immutable endpoint; + ISwapRouter public immutable SWAP_ROUTER; /// @notice The address of the OFT on the receiving chain. - address public immutable oft; - - /// @notice Custom errors for more gas-efficient reverts. - error InvalidSwapRouter(); - error InvalidEndpoint(); - error InvalidOFT(); - error UnauthorizedOFT(); - error UnauthorizedEndpoint(); + address public immutable OFT; - /** - * @notice Emitted when a token swap is successfully executed. - * - * @param srcSender The bytes32 address of the user initiating the swap on the source chain. - * @param tokenIn The address of the ERC20 token being swapped from (OFT). - * @param tokenOut The address of the ERC20 token being swapped to. - * @param amountIn The amount of `tokenIn` being swapped. - * @param amountOut The amount of `tokenOut` received from the swap. - */ - event SwapExecuted( - bytes32 indexed srcSender, - address recipient, - address tokenIn, - address tokenOut, - uint256 amountIn, - uint256 amountOut - ); + /// @notice The LayerZero Endpoint address for cross-chain communication. + address public immutable ENDPOINT; - /** - * @notice Emitted when a token swap fails and the OFT tokens are refunded to the recipient. - * - * @param srcSender The bytes32 address of the user initiating the swap on the source chain. - * @param recipient The address of the recipient of the OFT tokens. - * @param tokenIn The address of the ERC20 token being swapped from (OFT). - * @param amountIn The amount of `tokenIn` being refunded. - */ - event SwapFailedAndRefunded(bytes32 indexed srcSender, address tokenIn, address recipient, uint256 amountIn); + /// @notice The address of the token being swapped from (OFT). + address public immutable TOKEN_IN; /** * @notice Initializes the UniswapV3Composer contract with necessary parameters. * * @param _swapRouter The address of the Uniswap V3 SwapRouter. - * @param _endpoint The LayerZero Endpoint address for cross-chain communication. * @param _oft The address of the originating OFT that sends composed messages. * * Requirements: * * - `_swapRouter` cannot be the zero address. - * - `_endpoint` cannot be the zero address. * - `_oft` cannot be the zero address. */ - constructor(address _swapRouter, address _endpoint, address _oft) { + constructor(address _swapRouter, address _oft) { if (_swapRouter == address(0)) revert InvalidSwapRouter(); - if (_endpoint == address(0)) revert InvalidEndpoint(); if (_oft == address(0)) revert InvalidOFT(); - swapRouter = ISwapRouter(_swapRouter); - endpoint = _endpoint; - oft = _oft; + // Get the LayerZero Endpoint address from the OFT. + ENDPOINT = address(IOAppCore(_oft).endpoint()); + + // Initialize the swap router and OFT addresses. + SWAP_ROUTER = ISwapRouter(_swapRouter); + OFT = _oft; + TOKEN_IN = IOFT(OFT).token(); + + // Max approve the SwapRouter to spend TOKEN_IN to save gas on every compose transaction. + // This is safe since tokens can only enter this contract from the trusted LayerZero Endpoint + // via the trusted OFT, and the SwapRouter can only spend tokens the contract actually holds. + IERC20(TOKEN_IN).approve(address(SWAP_ROUTER), type(uint256).max); } /** @@ -118,8 +95,8 @@ contract UniswapV3Composer is IOAppComposer { address /*_executor*/, bytes calldata /*_extraData*/ ) external payable override { - if (_oft != oft) revert UnauthorizedOFT(); - if (msg.sender != endpoint) revert UnauthorizedEndpoint(); + if (_oft != OFT) revert UnauthorizedOFT(); + if (msg.sender != ENDPOINT) revert UnauthorizedEndpoint(); (address tokenOut, uint24 fee, address recipient, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96) = abi .decode(OFTComposeMsgCodec.composeMsg(_message), (address, uint24, address, uint256, uint160)); @@ -128,31 +105,26 @@ contract UniswapV3Composer is IOAppComposer { bytes32 srcSender = OFTComposeMsgCodec.composeFrom(_message); // Decode the amountIn from the message amount received. uint256 amountIn = OFTComposeMsgCodec.amountLD(_message); - // Reference to the ERC20 token used by the OFT. - address tokenIn = IOFT(oft).token(); - - // Approve the SwapRouter to spend tokenIn. - IERC20(tokenIn).approve(address(swapRouter), amountIn); // Set up Uniswap V3 swap parameters. ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ - tokenIn: tokenIn, + tokenIn: TOKEN_IN, tokenOut: tokenOut, fee: fee, recipient: recipient, - deadline: block.timestamp + 300, // 5 minutes deadline. + deadline: block.timestamp + 300, // 5 minutes deadline for example. amountIn: amountIn, amountOutMinimum: amountOutMinimum, sqrtPriceLimitX96: sqrtPriceLimitX96 }); // Attempt to execute the swap on Uniswap V3. - try swapRouter.exactInputSingle(params) returns (uint256 amountOut) { - emit SwapExecuted(srcSender, recipient, tokenIn, tokenOut, amountIn, amountOut); + try SWAP_ROUTER.exactInputSingle(params) returns (uint256 amountOut) { + emit SwapExecuted(srcSender, recipient, TOKEN_IN, tokenOut, amountIn, amountOut); } catch { // Refund the OFT tokens to the recipient if the swap fails. - IERC20(tokenIn).safeTransfer(recipient, amountIn); - emit SwapFailedAndRefunded(srcSender, tokenIn, recipient, amountIn); + IERC20(TOKEN_IN).safeTransfer(recipient, amountIn); + emit SwapFailedAndRefunded(srcSender, TOKEN_IN, recipient, amountIn); } } } diff --git a/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol b/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol index 1bf711ac1..14a622896 100644 --- a/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol +++ b/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import { UniswapV3Composer } from "../../contracts/UniswapV3Composer.sol"; import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; +import { IUniswapV3Composer } from "../../contracts/IUniswapV3Composer.sol"; // Mock imports import { OFTMock } from "../mocks/OFTMock.sol"; @@ -100,7 +101,7 @@ contract UniswapV3ComposerTest is TestHelperOz5 { bSwapRouter = new SwapRouterMock(address(bTokenIn), address(bTokenOut), swapAmountOut); // Deploy the UniswapV3Composer contract with initialized SwapRouter and OFT - bComposer = new UniswapV3Composer(address(bSwapRouter), address(endpoints[bEid]), address(bOFT)); + bComposer = new UniswapV3Composer(address(bSwapRouter), address(bOFT)); // Configure and link the deployed OFTs address[] memory ofts = new address[](2); @@ -123,15 +124,18 @@ contract UniswapV3ComposerTest is TestHelperOz5 { * @notice Tests the constructor of UniswapV3Composer for correct initialization. * @dev Verifies that SwapRouter, endpoint, and OFT addresses are set as expected. */ - function test_constructor() public { + function test_constructor() public view { // Assert that the SwapRouter address is correctly set in UniswapV3Composer - assertEq(address(bComposer.swapRouter()), address(bSwapRouter), "SwapRouter address mismatch"); + assertEq(address(bComposer.SWAP_ROUTER()), address(bSwapRouter), "SwapRouter address mismatch"); // Assert that the endpoint address is correctly set in UniswapV3Composer - assertEq(bComposer.endpoint(), address(endpoints[bEid]), "Endpoint address mismatch"); + assertEq(bComposer.ENDPOINT(), address(endpoints[bEid]), "Endpoint address mismatch"); // Assert that the OFT address is correctly set in UniswapV3Composer - assertEq(bComposer.oft(), address(bOFT), "OFT address mismatch"); + assertEq(bComposer.OFT(), address(bOFT), "OFT address mismatch"); + + // Assert that the TOKEN_IN address is correctly set in UniswapV3Composer + assertEq(bComposer.TOKEN_IN(), address(bTokenIn), "TOKEN_IN address mismatch"); } // ---------------------------- @@ -319,7 +323,7 @@ contract UniswapV3ComposerTest is TestHelperOz5 { vm.prank(address(endpoints[bEid])); // Expect the transaction to revert with "Unauthorized OFT" - vm.expectRevert(UniswapV3Composer.UnauthorizedOFT.selector); + vm.expectRevert(IUniswapV3Composer.UnauthorizedOFT.selector); // Attempt to execute lzCompose with an unauthorized OFT address bComposer.lzCompose( From 56bcad7561e0ec29a1545b0f13a30e00b8a1e8af Mon Sep 17 00:00:00 2001 From: Krak Date: Tue, 24 Jun 2025 10:43:08 -0700 Subject: [PATCH 21/47] chore: update code comments --- .../contracts/IUniswapV3Composer.sol | 2 +- .../contracts/UniswapV3Composer.sol | 124 +++++++++++++----- 2 files changed, 89 insertions(+), 37 deletions(-) diff --git a/examples/oft-composer-library/contracts/IUniswapV3Composer.sol b/examples/oft-composer-library/contracts/IUniswapV3Composer.sol index 4997ffc25..0f89c429b 100644 --- a/examples/oft-composer-library/contracts/IUniswapV3Composer.sol +++ b/examples/oft-composer-library/contracts/IUniswapV3Composer.sol @@ -45,4 +45,4 @@ interface IUniswapV3Composer { * @param amountIn The amount of `tokenIn` being refunded. */ event SwapFailedAndRefunded(bytes32 indexed srcSender, address tokenIn, address recipient, uint256 amountIn); -} \ No newline at end of file +} diff --git a/examples/oft-composer-library/contracts/UniswapV3Composer.sol b/examples/oft-composer-library/contracts/UniswapV3Composer.sol index 3f105141f..54fc5fdd9 100644 --- a/examples/oft-composer-library/contracts/UniswapV3Composer.sol +++ b/examples/oft-composer-library/contracts/UniswapV3Composer.sol @@ -17,34 +17,60 @@ import { IUniswapV3Composer } from "./IUniswapV3Composer.sol"; /** * @title UniswapV3Composer * - * @notice Handles cross-chain OFT token swaps using Uniswap V3 upon receiving tokens via LayerZero. + * @notice Handles cross-chain token swaps using Uniswap V3 upon receiving tokens via LayerZero. * * @dev This contract inherits from IOAppComposer and interacts with Uniswap V3's SwapRouter to execute token swaps. + * It is an **educational example** that accompanies the LayerZero V2 docs on Omnichain Composers. + * See: + * • https://docs.layerzero.network/v2/developers/evm/composer/overview + * • https://docs.layerzero.network/v2/developers/evm/oft/quickstart#send-tokens--call-composer + * + * The code is annotated with numbered section dividers to clearly separate: + * 0. Setup & Constructor logic + * 1. Receive business logic (`lzCompose`) + * + * Feel free to replace the Uniswap swap with your own custom business logic in Step 4. + * The overarching pattern (authenticate → decode → act → emit/cleanup) remains the same. */ contract UniswapV3Composer is IOAppComposer, IUniswapV3Composer { using SafeERC20 for IERC20; /// @notice The Uniswap V3 SwapRouter used to perform token swaps. + /// @dev Must expose the `exactInputSingle` method from the Uniswap V3 Periphery. ISwapRouter public immutable SWAP_ROUTER; - /// @notice The address of the OFT on the receiving chain. + /// @notice The trusted Omnichain Fungible Token (OFT) that can trigger `lzCompose` on this contract. address public immutable OFT; - /// @notice The LayerZero Endpoint address for cross-chain communication. + /// @notice LayerZero Endpoint V2 used by the trusted OFT on this chain. address public immutable ENDPOINT; - /// @notice The address of the token being swapped from (OFT). + /// @notice ERC20 token address that backs the trusted OFT (`tokenIn` for every swap). address public immutable TOKEN_IN; + // ────────────────────────────────────────────────────────────────────────────── + // 0. Setup & Constructor + // • Validates inputs + // • Caches Endpoint / Router / Token addresses + // • Grants a one-time max approval to the Uniswap V3 router + // + // ↳ Docs: https://docs.layerzero.network/v2/developers/evm/composer/overview + // https://docs.layerzero.network/v2/developers/evm/oft/quickstart#send-tokens--call-composer + // ────────────────────────────────────────────────────────────────────────────── + /** - * @notice Initializes the UniswapV3Composer contract with necessary parameters. + * @notice Deploys the composer and connects it to a trusted OFT and Uniswap V3 router. * - * @param _swapRouter The address of the Uniswap V3 SwapRouter. - * @param _oft The address of the originating OFT that sends composed messages. + * @dev The constructor assumes that `_oft` is already configured with the correct + * LayerZero Endpoint. It queries the endpoint from the OFT so the composer + * does not need a redundant constructor param. * - * Requirements: + * A **one-time `maxApprove`** is granted to the router because: + * 1. Funds only arrive via `lzReceive` → `lzCompose` from the trusted OFT. + * 2. The router can only transfer what the composeMsg allows. + * 3. Saves ~5k gas on every compose execution. * - * - `_swapRouter` cannot be the zero address. - * - `_oft` cannot be the zero address. + * @param _swapRouter Address of the Uniswap V3 `SwapRouter`. + * @param _oft Address of the trusted OFT that will source composed messages. */ constructor(address _swapRouter, address _oft) { if (_swapRouter == address(0)) revert InvalidSwapRouter(); @@ -58,35 +84,59 @@ contract UniswapV3Composer is IOAppComposer, IUniswapV3Composer { OFT = _oft; TOKEN_IN = IOFT(OFT).token(); - // Max approve the SwapRouter to spend TOKEN_IN to save gas on every compose transaction. - // This is safe since tokens can only enter this contract from the trusted LayerZero Endpoint - // via the trusted OFT, and the SwapRouter can only spend tokens the contract actually holds. + // ----------------------------------------------------------------------------- + // Grant an unlimited allowance ("maxApprove") to the Uniswap V3 router. + // + // Safety rationale: + // 1. `SWAP_ROUTER` can only `transferFrom` *this contract* (msg.sender). + // 2. This composer calls `exactInputSingle` **only** after a successful + // `lzCompose`, and for the _exact_ `amountIn` of tokens delivered with + // that message (decoded via `OFTComposeMsgCodec.amountLD`). + // 3. If the swap execution reverts we refund the tokens; if the entire + // transaction runs out of gas the tokens simply remain in the composer + // and are never at risk because the router was never invoked. + // + // Therefore an unlimited approval is safe and saves gas compared to + // approving per message. IERC20(TOKEN_IN).approve(address(SWAP_ROUTER), type(uint256).max); } + // ────────────────────────────────────────────────────────────────────────────── + // 1. Receive Business Logic (`lzCompose`) + // Called by the LayerZero Endpoint after a user sends OFT tokens cross-chain + // with a compose message. Decodes the message and performs a Uniswap V3 swap + // on behalf of the original sender. + // + // Steps: + // 1. Authenticity checks (trusted OFT & Endpoint) + // 2. Decode swap parameters & source sender from `_message` + // 3. Build `ExactInputSingleParams` struct + // 4. Try to execute swap → emit `SwapExecuted` + // • On failure, refund tokens → emit `SwapFailedAndRefunded` + // ────────────────────────────────────────────────────────────────────────────── + /** - * @notice Handles incoming composed messages from LayerZero to execute token swaps on Uniswap V3. - * - * @param _oft The address of the originating OFT. - * @param _message The encoded message content in the format of OFTComposeMsgCodec. - * - * @dev _executor The address of the executor (unused in this context). - * @dev _guid The globally unique identifier of the message (unused in this context). - * @dev _executorData Additional data for the executor (unused in this context). - * - * This function decodes the incoming message to extract swap parameters and executes the token swap - * using Uniswap V3. It ensures that only the authorized OFT and the LayerZero Endpoint can invoke this function. + * @notice Consumes a composed message and swaps `TOKEN_IN` → `tokenOut` on Uniswap V3. * - * Emits a {SwapExecuted} event upon successful execution of the swap. + * @dev `_message` is encoded by the OFT.send() caller on the source chain via + * `OFTComposeMsgCodec.encode()` and has the following layout: * - * Transfers the OFT tokens directly to the recipient if the swap fails. + * ``` + * | srcNonce (uint64) | srcEid (uint32) | amountLD (uint128) | + * | composeFrom (bytes32) | composeMsg (bytes) | + * ``` * - * Requirements: + * `composeMsg` (last field) is expected to be: + * `abi.encode(tokenOut, fee, recipient, amountOutMin, sqrtPriceLimitX96)`. * - * - `_oft` must match the authorized OFT address. - * - The caller must be the authorized LayerZero Endpoint. + * - Authentication: ensure caller is the **trusted Endpoint** and `_oft` matches. + * - Safety: on swap failure, funds are **refunded** (no token losses). * - * Reverts if any of the above conditions are not met. + * @param _oft The originating OFT address (must equal `OFT`). + * @dev _guid Message hash (unused, but kept for future extensibility). + * @param _message ABI-encoded compose message described above. + * @dev _executor Executor that relayed the message (unused). + * @dev _extraData Extra data from executor (unused). */ function lzCompose( address _oft, @@ -95,34 +145,36 @@ contract UniswapV3Composer is IOAppComposer, IUniswapV3Composer { address /*_executor*/, bytes calldata /*_extraData*/ ) external payable override { + // Step 1️: Authenticate call logic source. if (_oft != OFT) revert UnauthorizedOFT(); if (msg.sender != ENDPOINT) revert UnauthorizedEndpoint(); + // Step 2️: Decode the swap parameters & sender from the compose message included in the OFT.send() call. (address tokenOut, uint24 fee, address recipient, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96) = abi .decode(OFTComposeMsgCodec.composeMsg(_message), (address, uint24, address, uint256, uint160)); - // Extract the original msg.sender of OFT.send() on the source chain. + // • Extract the original msg.sender of `OFT.send()` on the source chain. bytes32 srcSender = OFTComposeMsgCodec.composeFrom(_message); - // Decode the amountIn from the message amount received. + // • Decode the amount (local decimals) sent with the compose message. uint256 amountIn = OFTComposeMsgCodec.amountLD(_message); - // Set up Uniswap V3 swap parameters. + // Step 3️: Build Uniswap V3 swap parameters. ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ tokenIn: TOKEN_IN, tokenOut: tokenOut, fee: fee, recipient: recipient, - deadline: block.timestamp + 300, // 5 minutes deadline for example. + deadline: block.timestamp + 300, // 5-minute deadline for example purposes. amountIn: amountIn, amountOutMinimum: amountOutMinimum, sqrtPriceLimitX96: sqrtPriceLimitX96 }); - // Attempt to execute the swap on Uniswap V3. + // Step 4️: Execute the swap or refund to target recipient. try SWAP_ROUTER.exactInputSingle(params) returns (uint256 amountOut) { emit SwapExecuted(srcSender, recipient, TOKEN_IN, tokenOut, amountIn, amountOut); } catch { - // Refund the OFT tokens to the recipient if the swap fails. + // If the swap fails, refund the exact amount to the recipient so that funds are not stuck in the composer. IERC20(TOKEN_IN).safeTransfer(recipient, amountIn); emit SwapFailedAndRefunded(srcSender, TOKEN_IN, recipient, amountIn); } From 4c1137065bd646d7c1588f3d08ac0041256b2d5d Mon Sep 17 00:00:00 2001 From: Krak Date: Tue, 24 Jun 2025 10:47:31 -0700 Subject: [PATCH 22/47] chore: update lockfile --- .changeset/chilled-fireants-try.md | 5 + pnpm-lock.yaml | 150 ++++++++++++++++++++++++++++- 2 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 .changeset/chilled-fireants-try.md diff --git a/.changeset/chilled-fireants-try.md b/.changeset/chilled-fireants-try.md new file mode 100644 index 000000000..f0440af36 --- /dev/null +++ b/.changeset/chilled-fireants-try.md @@ -0,0 +1,5 @@ +--- +"create-lz-oapp": patch +--- + +Adds lzCompose example diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 62f4c4180..13bbdbc8c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1966,6 +1966,129 @@ importers: specifier: ^2.6.1 version: 2.7.0 + examples/oft-composer-library: + devDependencies: + '@babel/core': + specifier: ^7.23.9 + version: 7.23.9 + '@layerzerolabs/devtools-evm-hardhat': + specifier: ^2.0.1 + version: 2.0.9(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@1.0.6)(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12) + '@layerzerolabs/eslint-config-next': + specifier: ~2.3.39 + version: 2.3.44(typescript@5.5.3) + '@layerzerolabs/lz-definitions': + specifier: ^3.0.12 + version: 3.0.86 + '@layerzerolabs/lz-evm-messagelib-v2': + specifier: ^3.0.12 + version: 3.0.86(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': + specifier: ^3.0.12 + version: 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': + specifier: ^3.0.12 + version: 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) + '@layerzerolabs/lz-v2-utilities': + specifier: ^3.0.12 + version: 3.0.86 + '@layerzerolabs/oapp-evm': + specifier: ^0.3.0 + version: link:../../packages/oapp-evm + '@layerzerolabs/oft-evm': + specifier: ^3.0.0 + version: link:../../packages/oft-evm + '@layerzerolabs/prettier-config-next': + specifier: ^2.3.39 + version: 2.3.44 + '@layerzerolabs/solhint-config': + specifier: ^3.0.12 + version: 3.0.12(typescript@5.5.3) + '@layerzerolabs/test-devtools-evm-foundry': + specifier: ~5.1.0 + version: 5.1.0(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@packages+oapp-evm)(@layerzerolabs/oft-evm@packages+oft-evm)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) + '@layerzerolabs/toolbox-foundry': + specifier: ~0.1.9 + version: link:../../packages/toolbox-foundry + '@layerzerolabs/toolbox-hardhat': + specifier: ~0.6.0 + version: link:../../packages/toolbox-hardhat + '@nomicfoundation/hardhat-ethers': + specifier: ^3.0.5 + version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) + '@nomiclabs/hardhat-ethers': + specifier: ^2.2.3 + version: 2.2.3(ethers@5.7.2)(hardhat@2.22.12) + '@openzeppelin/contracts': + specifier: ^5.0.2 + version: 5.1.0 + '@openzeppelin/contracts-upgradeable': + specifier: ^5.0.2 + version: 5.1.0(@openzeppelin/contracts@5.1.0) + '@rushstack/eslint-patch': + specifier: ^1.7.0 + version: 1.7.0 + '@types/chai': + specifier: ^4.3.11 + version: 4.3.20 + '@types/mocha': + specifier: ^10.0.6 + version: 10.0.6 + '@types/node': + specifier: ~18.18.14 + version: 18.18.14 + '@uniswap/v3-core': + specifier: ^1.0.1 + version: 1.0.1 + '@uniswap/v3-periphery': + specifier: ^1.4.4 + version: 1.4.4 + chai: + specifier: ^4.4.1 + version: 4.5.0 + concurrently: + specifier: ~9.1.0 + version: 9.1.0 + dotenv: + specifier: ^16.4.1 + version: 16.4.7 + eslint: + specifier: ^8.55.0 + version: 8.57.1 + eslint-plugin-jest-extended: + specifier: ~2.0.0 + version: 2.0.0(eslint@8.57.1)(typescript@5.5.3) + ethers: + specifier: ^5.7.2 + version: 5.7.2 + hardhat: + specifier: ^2.22.10 + version: 2.22.12(ts-node@10.9.2)(typescript@5.5.3) + hardhat-contract-sizer: + specifier: ^2.10.0 + version: 2.10.0(hardhat@2.22.12) + hardhat-deploy: + specifier: ^0.12.1 + version: 0.12.4 + mocha: + specifier: ^10.2.0 + version: 10.2.0 + prettier: + specifier: ^3.2.5 + version: 3.5.3 + solhint: + specifier: ^4.1.1 + version: 4.1.1(typescript@5.5.3) + solidity-bytes-utils: + specifier: ^0.8.2 + version: 0.8.2 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + typescript: + specifier: ^5.4.4 + version: 5.5.3 + examples/oft-hyperliquid: devDependencies: '@babel/core': @@ -10942,6 +11065,26 @@ packages: - utf-8-validate dev: false + /@layerzerolabs/test-devtools-evm-foundry@5.1.0(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@packages+oapp-evm)(@layerzerolabs/oft-evm@packages+oft-evm)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0): + resolution: {integrity: sha512-LDfBMeb5VQRMRXadpNgUe5Knib5FdCQ24S2o+kWMS/qPS6ZbPGe7fnhFPhcifautuhMS8i9Rk7cMjoAxRGFdfQ==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.12 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.12 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.12 + '@layerzerolabs/oapp-evm': ^0.3.0 + '@layerzerolabs/oft-evm': ^3.0.0 + '@openzeppelin/contracts': ^4.9.5 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.9.5 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.86(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) + '@layerzerolabs/oapp-evm': link:packages/oapp-evm + '@layerzerolabs/oft-evm': link:packages/oft-evm + '@openzeppelin/contracts': 5.1.0 + '@openzeppelin/contracts-upgradeable': 5.1.0(@openzeppelin/contracts@5.1.0) + dev: true + /@layerzerolabs/ton@15.2.0-rc.3(@jest/globals@29.7.0)(@layerzerolabs/ton@15.2.0-rc.3)(@ton/core@0.59.0)(@ton/crypto@3.3.0)(@types/node@18.18.14)(chai@4.5.0)(typescript@5.5.3): resolution: {integrity: sha512-Aq7htcWn31DxSYs8l0sJcQ76uAJRPy50lg6M2G+qNLSXpO01sPcUSb8oK/TmCKo+S+rDIFWUNKFjT0B/rll1YQ==} peerDependencies: @@ -10953,7 +11096,7 @@ packages: '@ton/crypto': 3.3.0 '@ton/sandbox': 0.22.0(@ton/core@0.59.0)(@ton/crypto@3.3.0) '@ton/test-utils': 0.4.2(@jest/globals@29.7.0)(@ton/core@0.59.0)(chai@4.5.0) - axios: 1.7.9 + axios: 1.8.4 dataloader: 2.2.2 symbol.inspect: 1.0.1 teslabot: 1.5.0 @@ -10981,7 +11124,7 @@ packages: '@ton/crypto': 3.3.0 '@ton/sandbox': 0.22.0(@ton/core@0.59.0)(@ton/crypto@3.3.0) '@ton/test-utils': 0.4.2(@ton/core@0.59.0)(chai@4.4.1) - axios: 1.7.9 + axios: 1.8.4 dataloader: 2.2.2 symbol.inspect: 1.0.1 teslabot: 1.5.0 @@ -11038,7 +11181,7 @@ packages: '@ton/crypto': 3.3.0 '@ton/sandbox': 0.22.0(@ton/core@0.59.0)(@ton/crypto@3.3.0) '@ton/test-utils': 0.4.2(@jest/globals@29.7.0)(@ton/core@0.59.0)(chai@4.5.0) - axios: 1.7.9 + axios: 1.8.4 dataloader: 2.2.2 symbol.inspect: 1.0.1 teslabot: 1.5.0 @@ -21940,7 +22083,6 @@ packages: resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} engines: {node: '>=14'} hasBin: true - dev: false /pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} From 483be2d3f4e7301cfdd44cfa27cc605be77fe288 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Wed, 12 Nov 2025 10:10:26 -0800 Subject: [PATCH 23/47] chore: rename --- examples/{oft-composer-library => oft-composers}/.env.example | 0 examples/{oft-composer-library => oft-composers}/.eslintignore | 0 examples/{oft-composer-library => oft-composers}/.eslintrc.js | 0 examples/{oft-composer-library => oft-composers}/.gitignore | 0 examples/{oft-composer-library => oft-composers}/.nvmrc | 0 examples/{oft-composer-library => oft-composers}/.prettierignore | 0 examples/{oft-composer-library => oft-composers}/.prettierrc.js | 0 examples/{oft-composer-library => oft-composers}/README.md | 0 .../contracts/IUniswapV3Composer.sol | 0 .../{oft-composer-library => oft-composers}/contracts/MyOFT.sol | 0 .../contracts/UniswapV3Composer.sol | 0 .../contracts/mocks/MyOFTMock.sol | 0 examples/{oft-composer-library => oft-composers}/deploy/MyOFT.ts | 0 examples/{oft-composer-library => oft-composers}/foundry.toml | 0 .../{oft-composer-library => oft-composers}/hardhat.config.ts | 0 .../{oft-composer-library => oft-composers}/layerzero.config.ts | 0 examples/{oft-composer-library => oft-composers}/package.json | 0 .../{oft-composer-library => oft-composers}/solhint.config.js | 0 .../test/foundry/MyOFT.t.sol | 0 .../test/foundry/UniswapV3Composer.t.sol | 0 .../test/mocks/ERC20Mock.sol | 0 .../test/mocks/OFTComposerMock.sol | 0 .../test/mocks/OFTMock.sol | 0 .../test/mocks/SwapRouterMock.sol | 0 examples/{oft-composer-library => oft-composers}/tsconfig.json | 0 25 files changed, 0 insertions(+), 0 deletions(-) rename examples/{oft-composer-library => oft-composers}/.env.example (100%) rename examples/{oft-composer-library => oft-composers}/.eslintignore (100%) rename examples/{oft-composer-library => oft-composers}/.eslintrc.js (100%) rename examples/{oft-composer-library => oft-composers}/.gitignore (100%) rename examples/{oft-composer-library => oft-composers}/.nvmrc (100%) rename examples/{oft-composer-library => oft-composers}/.prettierignore (100%) rename examples/{oft-composer-library => oft-composers}/.prettierrc.js (100%) rename examples/{oft-composer-library => oft-composers}/README.md (100%) rename examples/{oft-composer-library => oft-composers}/contracts/IUniswapV3Composer.sol (100%) rename examples/{oft-composer-library => oft-composers}/contracts/MyOFT.sol (100%) rename examples/{oft-composer-library => oft-composers}/contracts/UniswapV3Composer.sol (100%) rename examples/{oft-composer-library => oft-composers}/contracts/mocks/MyOFTMock.sol (100%) rename examples/{oft-composer-library => oft-composers}/deploy/MyOFT.ts (100%) rename examples/{oft-composer-library => oft-composers}/foundry.toml (100%) rename examples/{oft-composer-library => oft-composers}/hardhat.config.ts (100%) rename examples/{oft-composer-library => oft-composers}/layerzero.config.ts (100%) rename examples/{oft-composer-library => oft-composers}/package.json (100%) rename examples/{oft-composer-library => oft-composers}/solhint.config.js (100%) rename examples/{oft-composer-library => oft-composers}/test/foundry/MyOFT.t.sol (100%) rename examples/{oft-composer-library => oft-composers}/test/foundry/UniswapV3Composer.t.sol (100%) rename examples/{oft-composer-library => oft-composers}/test/mocks/ERC20Mock.sol (100%) rename examples/{oft-composer-library => oft-composers}/test/mocks/OFTComposerMock.sol (100%) rename examples/{oft-composer-library => oft-composers}/test/mocks/OFTMock.sol (100%) rename examples/{oft-composer-library => oft-composers}/test/mocks/SwapRouterMock.sol (100%) rename examples/{oft-composer-library => oft-composers}/tsconfig.json (100%) diff --git a/examples/oft-composer-library/.env.example b/examples/oft-composers/.env.example similarity index 100% rename from examples/oft-composer-library/.env.example rename to examples/oft-composers/.env.example diff --git a/examples/oft-composer-library/.eslintignore b/examples/oft-composers/.eslintignore similarity index 100% rename from examples/oft-composer-library/.eslintignore rename to examples/oft-composers/.eslintignore diff --git a/examples/oft-composer-library/.eslintrc.js b/examples/oft-composers/.eslintrc.js similarity index 100% rename from examples/oft-composer-library/.eslintrc.js rename to examples/oft-composers/.eslintrc.js diff --git a/examples/oft-composer-library/.gitignore b/examples/oft-composers/.gitignore similarity index 100% rename from examples/oft-composer-library/.gitignore rename to examples/oft-composers/.gitignore diff --git a/examples/oft-composer-library/.nvmrc b/examples/oft-composers/.nvmrc similarity index 100% rename from examples/oft-composer-library/.nvmrc rename to examples/oft-composers/.nvmrc diff --git a/examples/oft-composer-library/.prettierignore b/examples/oft-composers/.prettierignore similarity index 100% rename from examples/oft-composer-library/.prettierignore rename to examples/oft-composers/.prettierignore diff --git a/examples/oft-composer-library/.prettierrc.js b/examples/oft-composers/.prettierrc.js similarity index 100% rename from examples/oft-composer-library/.prettierrc.js rename to examples/oft-composers/.prettierrc.js diff --git a/examples/oft-composer-library/README.md b/examples/oft-composers/README.md similarity index 100% rename from examples/oft-composer-library/README.md rename to examples/oft-composers/README.md diff --git a/examples/oft-composer-library/contracts/IUniswapV3Composer.sol b/examples/oft-composers/contracts/IUniswapV3Composer.sol similarity index 100% rename from examples/oft-composer-library/contracts/IUniswapV3Composer.sol rename to examples/oft-composers/contracts/IUniswapV3Composer.sol diff --git a/examples/oft-composer-library/contracts/MyOFT.sol b/examples/oft-composers/contracts/MyOFT.sol similarity index 100% rename from examples/oft-composer-library/contracts/MyOFT.sol rename to examples/oft-composers/contracts/MyOFT.sol diff --git a/examples/oft-composer-library/contracts/UniswapV3Composer.sol b/examples/oft-composers/contracts/UniswapV3Composer.sol similarity index 100% rename from examples/oft-composer-library/contracts/UniswapV3Composer.sol rename to examples/oft-composers/contracts/UniswapV3Composer.sol diff --git a/examples/oft-composer-library/contracts/mocks/MyOFTMock.sol b/examples/oft-composers/contracts/mocks/MyOFTMock.sol similarity index 100% rename from examples/oft-composer-library/contracts/mocks/MyOFTMock.sol rename to examples/oft-composers/contracts/mocks/MyOFTMock.sol diff --git a/examples/oft-composer-library/deploy/MyOFT.ts b/examples/oft-composers/deploy/MyOFT.ts similarity index 100% rename from examples/oft-composer-library/deploy/MyOFT.ts rename to examples/oft-composers/deploy/MyOFT.ts diff --git a/examples/oft-composer-library/foundry.toml b/examples/oft-composers/foundry.toml similarity index 100% rename from examples/oft-composer-library/foundry.toml rename to examples/oft-composers/foundry.toml diff --git a/examples/oft-composer-library/hardhat.config.ts b/examples/oft-composers/hardhat.config.ts similarity index 100% rename from examples/oft-composer-library/hardhat.config.ts rename to examples/oft-composers/hardhat.config.ts diff --git a/examples/oft-composer-library/layerzero.config.ts b/examples/oft-composers/layerzero.config.ts similarity index 100% rename from examples/oft-composer-library/layerzero.config.ts rename to examples/oft-composers/layerzero.config.ts diff --git a/examples/oft-composer-library/package.json b/examples/oft-composers/package.json similarity index 100% rename from examples/oft-composer-library/package.json rename to examples/oft-composers/package.json diff --git a/examples/oft-composer-library/solhint.config.js b/examples/oft-composers/solhint.config.js similarity index 100% rename from examples/oft-composer-library/solhint.config.js rename to examples/oft-composers/solhint.config.js diff --git a/examples/oft-composer-library/test/foundry/MyOFT.t.sol b/examples/oft-composers/test/foundry/MyOFT.t.sol similarity index 100% rename from examples/oft-composer-library/test/foundry/MyOFT.t.sol rename to examples/oft-composers/test/foundry/MyOFT.t.sol diff --git a/examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol b/examples/oft-composers/test/foundry/UniswapV3Composer.t.sol similarity index 100% rename from examples/oft-composer-library/test/foundry/UniswapV3Composer.t.sol rename to examples/oft-composers/test/foundry/UniswapV3Composer.t.sol diff --git a/examples/oft-composer-library/test/mocks/ERC20Mock.sol b/examples/oft-composers/test/mocks/ERC20Mock.sol similarity index 100% rename from examples/oft-composer-library/test/mocks/ERC20Mock.sol rename to examples/oft-composers/test/mocks/ERC20Mock.sol diff --git a/examples/oft-composer-library/test/mocks/OFTComposerMock.sol b/examples/oft-composers/test/mocks/OFTComposerMock.sol similarity index 100% rename from examples/oft-composer-library/test/mocks/OFTComposerMock.sol rename to examples/oft-composers/test/mocks/OFTComposerMock.sol diff --git a/examples/oft-composer-library/test/mocks/OFTMock.sol b/examples/oft-composers/test/mocks/OFTMock.sol similarity index 100% rename from examples/oft-composer-library/test/mocks/OFTMock.sol rename to examples/oft-composers/test/mocks/OFTMock.sol diff --git a/examples/oft-composer-library/test/mocks/SwapRouterMock.sol b/examples/oft-composers/test/mocks/SwapRouterMock.sol similarity index 100% rename from examples/oft-composer-library/test/mocks/SwapRouterMock.sol rename to examples/oft-composers/test/mocks/SwapRouterMock.sol diff --git a/examples/oft-composer-library/tsconfig.json b/examples/oft-composers/tsconfig.json similarity index 100% rename from examples/oft-composer-library/tsconfig.json rename to examples/oft-composers/tsconfig.json From 12cfb366dac499950e75d47ab723330b45b7c17a Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 11:36:16 -0800 Subject: [PATCH 24/47] chore: move uni example --- .../contracts/{ => UniswapV3Composer}/IUniswapV3Composer.sol | 0 .../contracts/{ => UniswapV3Composer}/UniswapV3Composer.sol | 0 examples/oft-composers/test/foundry/UniswapV3Composer.t.sol | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename examples/oft-composers/contracts/{ => UniswapV3Composer}/IUniswapV3Composer.sol (100%) rename examples/oft-composers/contracts/{ => UniswapV3Composer}/UniswapV3Composer.sol (100%) diff --git a/examples/oft-composers/contracts/IUniswapV3Composer.sol b/examples/oft-composers/contracts/UniswapV3Composer/IUniswapV3Composer.sol similarity index 100% rename from examples/oft-composers/contracts/IUniswapV3Composer.sol rename to examples/oft-composers/contracts/UniswapV3Composer/IUniswapV3Composer.sol diff --git a/examples/oft-composers/contracts/UniswapV3Composer.sol b/examples/oft-composers/contracts/UniswapV3Composer/UniswapV3Composer.sol similarity index 100% rename from examples/oft-composers/contracts/UniswapV3Composer.sol rename to examples/oft-composers/contracts/UniswapV3Composer/UniswapV3Composer.sol diff --git a/examples/oft-composers/test/foundry/UniswapV3Composer.t.sol b/examples/oft-composers/test/foundry/UniswapV3Composer.t.sol index 14a622896..cdd58f1ac 100644 --- a/examples/oft-composers/test/foundry/UniswapV3Composer.t.sol +++ b/examples/oft-composers/test/foundry/UniswapV3Composer.t.sol @@ -3,9 +3,9 @@ pragma solidity ^0.8.20; // Import necessary testing libraries and contracts import "forge-std/Test.sol"; -import { UniswapV3Composer } from "../../contracts/UniswapV3Composer.sol"; +import { UniswapV3Composer } from "../../contracts/UniswapV3Composer/UniswapV3Composer.sol"; import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; -import { IUniswapV3Composer } from "../../contracts/IUniswapV3Composer.sol"; +import { IUniswapV3Composer } from "../../contracts/UniswapV3Composer/IUniswapV3Composer.sol"; // Mock imports import { OFTMock } from "../mocks/OFTMock.sol"; From ea2d70ffece80a30fb5585d165c3f9baeaed2149 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 11:42:51 -0800 Subject: [PATCH 25/47] feat: added aave composer example --- .../AaveV3Composer/AaveV3Composer.sol | 140 ++++++++++++++++++ .../AaveV3Composer/IAaveV3Composer.sol | 37 +++++ .../contracts/AaveV3Composer/IAaveV3Pool.sol | 22 +++ 3 files changed, 199 insertions(+) create mode 100644 examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol create mode 100644 examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol create mode 100644 examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol diff --git a/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol b/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol new file mode 100644 index 000000000..aff0dc763 --- /dev/null +++ b/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; +import { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; + +import { ILayerZeroComposer } from '@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol'; +import { OFTComposeMsgCodec } from '@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol'; +import { IOAppCore } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol"; +import { IStargate } from '@stargatefinance/stg-evm-v2/src/interfaces/IStargate.sol'; + +import { IAaveV3Composer } from './IAaveV3Composer.sol'; +import { IPool } from './IAaveV3Pool.sol'; + +/** + * @title AaveV3Composer + * + * @notice Supplies the received tokens into Aave V3 liquidity pools after an lzCompose call. + * + * @dev The contract enforces strict authentication, decodes lzCompose payloads, and either supplies tokens into Aave + * or refunds the recipient if the supply reverts. + */ +contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { + using SafeERC20 for IERC20; + + /// @notice Aave V3 pool that receives supplied liquidity. + IPool public immutable AAVE; + + /// @notice LayerZero Endpoint trusted to invoke `lzCompose`. + address public immutable ENDPOINT; + + /// @notice Stargate OFT that is authorized to trigger Aave supplies on this chain. + address public immutable STARGATE; + + /// @notice Underlying ERC20 token that backs the trusted Stargate OFT. + address public immutable TOKEN_IN; + + // ────────────────────────────────────────────────────────────────────────────── + // 0. Setup & Constructor + // • Validates constructor inputs + // • Caches protocol addresses + // • Grants a one-time approval for Aave supplies + // + // ↳ Docs: https://docs.layerzero.network/v2/developers/evm/composer/overview + // https://docs.layerzero.network/v2/developers/evm/oft/quickstart#send-tokens--call-composer + // ────────────────────────────────────────────────────────────────────────────── + + /** + * @notice Deploys the composer and connects it to Stargate and Aave pools. + * + * @dev Assuming the Stargate contract is already configured with the correct LayerZero Endpoint. + * + * A **one-time `maxApprove`** is granted to the Aave Pool because: + * 1. Funds only arrive via `lzReceive` → `lzCompose` from the trusted Stargate Pool. + * 2. The pool can only transfer what the composeMsg allows. + * 3. Saves ~5k gas on every compose execution. + * + * @param _aavePool Address of the target Aave V3 pool. + * @param _stargatePool StargatePool expected to receive the supplied tokens. + */ + constructor( + address _aavePool, + address _stargatePool + ) { + if (_aavePool == address(0)) revert InvalidAavePool(); + if (_stargatePool == address(0)) revert InvalidStargatePool(); + + // Initialize the Aave pool. + AAVE = IPool(_aavePool); + + // Initialize the Stargate Pool. + STARGATE = _stargatePool; + + // Gran the endpoint from the StargatePool. + ENDPOINT = address(IOAppCore(STARGATE).endpoint()); + + // Grab the underlying token from the StargatePool. + TOKEN_IN = IStargate(_stargatePool).token(); + + // Grant a one-time unlimited allowance so Aave can pull funds during supply. + IERC20(TOKEN_IN).approve(address(AAVE), type(uint256).max); + } + + // ────────────────────────────────────────────────────────────────────────────── + // 1. Compose Logic (`lzCompose`) + // Called by the LayerZero Endpoint after a user sends tokens cross-chain + // with a compose message. Decodes the message and performs a Aave V3 supply + // on behalf of the original sender. + + // Steps: + // 1. Authenticity checks (trusted Stargate Pool & Endpoint) + // 2. Decode recipient address and amount from `_message` + // 3. Try to execute supply on behalf of the recipient → emit `SupplyExecuted` + // • On failure, refund tokens → emit `SupplyFailedAndRefunded` + // ────────────────────────────────────────────────────────────────────────────── + + /** + * @notice Consumes composed messages and supplies the received tokens into the Aave V3 pool. + * @dev `_message` is encoded by the OFT.send() caller on the source chain via + * `OFTComposeMsgCodec.encode()` and has the following layout: + * + * ``` + * | srcNonce (uint64) | srcEid (uint32) | amountLD (uint128) | + * | composeFrom (bytes32) | composeMsg (bytes) | + * ``` + * + * `composeMsg` (last field) is expected to be: + * `abi.encode(address onBehalfOf)`. + * + * + * @param _oft Address of the originating OFT; must equal the trusted `stargate`. + * @dev _guid Message hash (unused, but kept for future extensibility). + * @param _message ABI-encoded compose payload containing recipient address. + * @dev _executor Executor that relayed the message (unused). + * @dev _extraData Extra data from executor (unused). + */ + function lzCompose( + address _oft, + bytes32 /* _guid */, + bytes calldata _message, + address /* _executor */, + bytes calldata /* _extraData */ + ) external payable { + // Step 1️: Authenticate call logic source. + if (_oft != STARGATE) revert UnauthorizedStargatePool(); + if (msg.sender != ENDPOINT) revert UnauthorizedEndpoint(); + + // Step 2️: Decode the recipient address and amount from the message. + (address _to) = abi.decode(OFTComposeMsgCodec.composeMsg(_message), (address)); + uint256 amountLD = OFTComposeMsgCodec.amountLD(_message); + + // Step 3: Execute the supply or refund to target recipient. + try AAVE.supply(TOKEN_IN, amountLD, _to, 0) { // 0 is the referral code + emit SupplyExecuted(_to, amountLD); + } catch { + IERC20(TOKEN_IN).safeTransfer(_to, amountLD); + emit SupplyFailedAndRefunded(_to, amountLD); + } + } +} diff --git a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol b/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol new file mode 100644 index 000000000..fda2fe558 --- /dev/null +++ b/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @title IAaveV3Composer + * + * @notice Interface defining events and errors for the AaveV3Composer contract. + * + * @dev This interface helps with code organization, testing, and reusability by separating + * contract definitions from implementation logic. + */ +interface IAaveV3Composer { + /// @notice Custom errors for more gas-efficient reverts. + error InvalidAavePool(); + error InvalidStargatePool(); + error UnauthorizedStargatePool(); + error UnauthorizedEndpoint(); + + /** + * @notice Emitted when a token supply is successfully executed. + * + * @param recipient The address of the recipient of the aTokens tokens. + * @param amountLD The amount of LD tokens being supplied. + */ + event SupplyExecuted( + address indexed recipient, + uint256 amountLD + ); + + /** + * @notice Emitted when a token supply fails and the OFT tokens are refunded to the recipient. + * + * @param recipient The address of the recipient of the aTokens tokens. + * @param amountLD The amount of LD tokens being refunded. + */ + event SupplyFailedAndRefunded(address indexed recipient, uint256 amountLD); +} diff --git a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol b/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol new file mode 100644 index 000000000..79543694d --- /dev/null +++ b/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @title IPool + * @author Aave + * @notice Defines the basic interface for an Aave Pool. + */ +interface IPool { + /** + * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. + * - E.g. User supplies 100 USDC and gets in return 100 aUSDC + * @param asset The address of the underlying asset to supply + * @param amount The amount to be supplied + * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user + * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens + * is a different wallet + * @param referralCode Code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; +} \ No newline at end of file From 2137375a7c594346d9bba0104536c5d1c217f42b Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 11:52:46 -0800 Subject: [PATCH 26/47] chore: ran lint on contracts --- .../AaveV3Composer/AaveV3Composer.sol | 32 +++++++++---------- .../AaveV3Composer/IAaveV3Composer.sol | 7 ++-- .../contracts/AaveV3Composer/IAaveV3Pool.sol | 26 +++++++-------- 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol b/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol index aff0dc763..e34aac7ea 100644 --- a/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol +++ b/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; -import { SafeERC20 } from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { ILayerZeroComposer } from '@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol'; -import { OFTComposeMsgCodec } from '@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol'; +import { ILayerZeroComposer } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol"; +import { OFTComposeMsgCodec } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol"; import { IOAppCore } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol"; -import { IStargate } from '@stargatefinance/stg-evm-v2/src/interfaces/IStargate.sol'; +import { IStargate } from "@stargatefinance/stg-evm-v2/src/interfaces/IStargate.sol"; -import { IAaveV3Composer } from './IAaveV3Composer.sol'; -import { IPool } from './IAaveV3Pool.sol'; +import { IAaveV3Composer } from "./IAaveV3Composer.sol"; +import { IPool } from "./IAaveV3Pool.sol"; /** * @title AaveV3Composer @@ -47,9 +47,9 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { /** * @notice Deploys the composer and connects it to Stargate and Aave pools. - * + * * @dev Assuming the Stargate contract is already configured with the correct LayerZero Endpoint. - * + * * A **one-time `maxApprove`** is granted to the Aave Pool because: * 1. Funds only arrive via `lzReceive` → `lzCompose` from the trusted Stargate Pool. * 2. The pool can only transfer what the composeMsg allows. @@ -58,16 +58,13 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { * @param _aavePool Address of the target Aave V3 pool. * @param _stargatePool StargatePool expected to receive the supplied tokens. */ - constructor( - address _aavePool, - address _stargatePool - ) { + constructor(address _aavePool, address _stargatePool) { if (_aavePool == address(0)) revert InvalidAavePool(); if (_stargatePool == address(0)) revert InvalidStargatePool(); // Initialize the Aave pool. AAVE = IPool(_aavePool); - + // Initialize the Stargate Pool. STARGATE = _stargatePool; @@ -96,7 +93,7 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { /** * @notice Consumes composed messages and supplies the received tokens into the Aave V3 pool. - * @dev `_message` is encoded by the OFT.send() caller on the source chain via + * @dev `_message` is encoded by the OFT.send() caller on the source chain via * `OFTComposeMsgCodec.encode()` and has the following layout: * * ``` @@ -126,11 +123,12 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { if (msg.sender != ENDPOINT) revert UnauthorizedEndpoint(); // Step 2️: Decode the recipient address and amount from the message. - (address _to) = abi.decode(OFTComposeMsgCodec.composeMsg(_message), (address)); + address _to = abi.decode(OFTComposeMsgCodec.composeMsg(_message), (address)); uint256 amountLD = OFTComposeMsgCodec.amountLD(_message); // Step 3: Execute the supply or refund to target recipient. - try AAVE.supply(TOKEN_IN, amountLD, _to, 0) { // 0 is the referral code + try AAVE.supply(TOKEN_IN, amountLD, _to, 0) { + // 0 is the referral code emit SupplyExecuted(_to, amountLD); } catch { IERC20(TOKEN_IN).safeTransfer(_to, amountLD); diff --git a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol b/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol index fda2fe558..06d31bf55 100644 --- a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol +++ b/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol @@ -22,10 +22,7 @@ interface IAaveV3Composer { * @param recipient The address of the recipient of the aTokens tokens. * @param amountLD The amount of LD tokens being supplied. */ - event SupplyExecuted( - address indexed recipient, - uint256 amountLD - ); + event SupplyExecuted(address indexed recipient, uint256 amountLD); /** * @notice Emitted when a token supply fails and the OFT tokens are refunded to the recipient. @@ -34,4 +31,4 @@ interface IAaveV3Composer { * @param amountLD The amount of LD tokens being refunded. */ event SupplyFailedAndRefunded(address indexed recipient, uint256 amountLD); -} +} diff --git a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol b/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol index 79543694d..11bedfbe1 100644 --- a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol +++ b/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol @@ -7,16 +7,16 @@ pragma solidity ^0.8.0; * @notice Defines the basic interface for an Aave Pool. */ interface IPool { - /** - * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. - * - E.g. User supplies 100 USDC and gets in return 100 aUSDC - * @param asset The address of the underlying asset to supply - * @param amount The amount to be supplied - * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user - * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens - * is a different wallet - * @param referralCode Code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - */ - function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; -} \ No newline at end of file + /** + * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. + * - E.g. User supplies 100 USDC and gets in return 100 aUSDC + * @param asset The address of the underlying asset to supply + * @param amount The amount to be supplied + * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user + * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens + * is a different wallet + * @param referralCode Code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; +} From cf43a00bd76a1c51301ae8d7ae40af4c0a1b9543 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 11:53:35 -0800 Subject: [PATCH 27/47] feat: add aave composer deploy script --- .../oft-composers/deploy/AaveV3Composer.ts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 examples/oft-composers/deploy/AaveV3Composer.ts diff --git a/examples/oft-composers/deploy/AaveV3Composer.ts b/examples/oft-composers/deploy/AaveV3Composer.ts new file mode 100644 index 000000000..27d240dd4 --- /dev/null +++ b/examples/oft-composers/deploy/AaveV3Composer.ts @@ -0,0 +1,41 @@ +import assert from 'assert' + +import { type DeployFunction } from 'hardhat-deploy/types' + +const contractName = 'AaveV3Composer' + +const deploy: DeployFunction = async (hre) => { + const { deployments, getNamedAccounts, ethers, network } = hre + const { deploy } = deployments + + const { deployer } = await getNamedAccounts() + assert(deployer, 'Missing named deployer account') + + const aavePool = process.env.AAVE_V3_POOL_ADDRESS + assert(aavePool, 'Missing AAVE_V3_POOL_ADDRESS environment variable') + + const stargatePool = process.env.STARGATE_POOL_ADDRESS + assert(stargatePool, 'Missing STARGATE_POOL_ADDRESS environment variable') + + const { isAddress } = ethers.utils + assert(isAddress(aavePool), `AAVE_V3_POOL_ADDRESS (${aavePool}) is not a valid address`) + assert(isAddress(stargatePool), `STARGATE_POOL_ADDRESS (${stargatePool}) is not a valid address`) + + console.log(`Network: ${network.name}`) + console.log(`Deployer: ${deployer}`) + console.log(`Aave pool: ${aavePool}`) + console.log(`Stargate pool: ${stargatePool}`) + + const { address } = await deploy(contractName, { + from: deployer, + args: [aavePool, stargatePool], + log: true, + skipIfAlreadyDeployed: false, + }) + + console.log(`Deployed contract: ${contractName}, network: ${network.name}, address: ${address}`) +} + +deploy.tags = [contractName] + +export default deploy From d39b814f3f8c7f7085f932050485aa728c972d9f Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 11:54:14 -0800 Subject: [PATCH 28/47] feat: add supply aave hh task --- examples/oft-composers/tasks/index.ts | 1 + examples/oft-composers/tasks/supplyAave.ts | 170 +++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 examples/oft-composers/tasks/index.ts create mode 100644 examples/oft-composers/tasks/supplyAave.ts diff --git a/examples/oft-composers/tasks/index.ts b/examples/oft-composers/tasks/index.ts new file mode 100644 index 000000000..b98e822af --- /dev/null +++ b/examples/oft-composers/tasks/index.ts @@ -0,0 +1 @@ +import './supplyAave' diff --git a/examples/oft-composers/tasks/supplyAave.ts b/examples/oft-composers/tasks/supplyAave.ts new file mode 100644 index 000000000..660c177e0 --- /dev/null +++ b/examples/oft-composers/tasks/supplyAave.ts @@ -0,0 +1,170 @@ +import { BigNumber } from 'ethers' +import { task } from 'hardhat/config' + +import { createModuleLogger } from '@layerzerolabs/io-devtools' +import { Options } from '@layerzerolabs/lz-v2-utilities' + +import type { HardhatRuntimeEnvironment } from 'hardhat/types' + +const logger = createModuleLogger('stargate:supply-aave') + +type SendArgs = { + stargate: string + dstEid: string + composer: string + composeGasLimit: string + amountLd: string + tokenReceiver: string + refundAddress?: string + payInLzToken?: string + oftCmd?: string +} + +const isReceiptObject = (value: unknown): value is { amountReceivedLD?: BigNumber } => { + if (!value || typeof value !== 'object' || value === null) { + return false + } + + const candidate = value as { amountReceivedLD?: unknown } + if (!('amountReceivedLD' in candidate)) { + return false + } + + const { amountReceivedLD } = candidate + return amountReceivedLD === undefined || BigNumber.isBigNumber(amountReceivedLD) +} + +const getAmountFromArray = (values: unknown[]): BigNumber | undefined => { + const candidate = values[1] ?? values[0] + return BigNumber.isBigNumber(candidate) ? candidate : undefined +} + +async function sendSupply(hre: HardhatRuntimeEnvironment, args: SendArgs) { + const { ethers } = hre + const signer = (await ethers.getSigners())[0] + const abiCoder = ethers.utils.defaultAbiCoder + + logger.info( + `Preparing Stargate supply compose send to ${args.tokenReceiver ?? signer.address} on chain ${args.dstEid}` + ) + + // 1. Build compose message payload expected by AaveV3Composer (address) + const composeMsg = abiCoder.encode(['address'], [args.tokenReceiver ?? signer.address]) + + const composeGasLimit = ethers.BigNumber.from(args.composeGasLimit ?? '200000').toString() + + const extraOptions = Options.newOptions() + .addExecutorComposeOption( + 0, // compose index + composeGasLimit, + 0 // no native drop + ) + .toHex() + + const dstEid = Number(args.dstEid) // uint32 destination endpoint + if (!Number.isSafeInteger(dstEid)) { + throw new Error(`dstEid must be a safe integer: got ${args.dstEid}`) + } + + const amountLD = ethers.BigNumber.from(args.amountLd) + const payInLzToken = (args.payInLzToken ?? 'false').toLowerCase() === 'true' + + const refundAddress = args.refundAddress ?? signer.address + + const stargateAbi = await hre.artifacts.readArtifact('IStargate') + const pool = await ethers.getContractAt(stargateAbi.abi, args.stargate, signer) + logger.debug(`Connected to Stargate pool: ${pool.address}`) + + // 2. Assemble initial SendParam tuple (minAmountLD will be filled after quoteOFT) + const sendParamTuple = [ + dstEid, + ethers.utils.hexZeroPad(args.composer, 32), + amountLD, + ethers.constants.Zero, + extraOptions, + composeMsg, + args.oftCmd ?? '0x', + ] + + const [, , receipt] = await pool.quoteOFT(sendParamTuple) + logger.debug(`QuoteOFT receipt: ${receipt}`) + + // 3. Update minAmount + compose payload using quoted amountReceivedLD + const amountReceivedLD = (() => { + if (isReceiptObject(receipt)) { + return receipt.amountReceivedLD + } + + if (Array.isArray(receipt)) { + return getAmountFromArray(receipt) + } + + return undefined + })() + + if (!amountReceivedLD) { + logger.error(`quoteOFT returned an unexpected receipt format: ${receipt}`) + throw new Error('quoteOFT returned an unexpected receipt format') + } + + // Update minAmountLD (index 3) and the compose payload (index 5) + sendParamTuple[3] = amountReceivedLD + logger.debug('Updated send param', { sendParamTuple }) + + const quoteSendResult = await pool.quoteSend(sendParamTuple, payInLzToken) + logger.debug('QuoteSend result', { quoteSendResult }) + + const messagingFee = (() => { + if (Array.isArray(quoteSendResult)) { + return [ + quoteSendResult[0] ?? quoteSendResult[quoteSendResult.length - 2], + quoteSendResult[1] ?? quoteSendResult[quoteSendResult.length - 1], + ] + } + throw new Error('quoteSend returned an unexpected format') + })() + + const valueToSend = messagingFee[0] + + // 4. Ensure ERC20 approval if pool is token-based + const tokenAddress = await pool.token() + + if (tokenAddress !== ethers.constants.AddressZero) { + const erc20Abi = await hre.artifacts.readArtifact('IERC20') + const erc20 = await ethers.getContractAt(erc20Abi.abi, tokenAddress, signer) + + const currentAllowance = await erc20.allowance(signer.address, pool.address) + logger.info(`Checking current allowance.`) + + if (currentAllowance.lt(amountLD)) { + logger.info(`Approving pool to spend tokens.`) + const approveTx = await erc20.approve(pool.address, amountLD) + await approveTx.wait() + logger.info(`Approval confirmed: ${approveTx.hash}`) + } + } + + // 5. Execute Stargate send with computed params and fees + const tx = await pool.send(sendParamTuple, messagingFee, refundAddress, { + value: valueToSend, + }) + + logger.info(`Stargate transaction submitted: ${tx.hash}`) + await tx.wait() + logger.info(`Stargate transaction confirmed.`) +} + +task('stargate:supply-aave', 'Sends tokens through Stargate and composes into AaveV3Composer') + .addParam('stargate', 'Stargate pool address') + .addParam('dstEid', 'Destination endpoint ID') + .addParam('composer', 'Composer contract address on the destination chain') + .addParam('amountLd', 'Token amount in local decimals to bridge') + .addOptionalParam('tokenReceiver', 'Recipient address on the destination chain') + .addOptionalParam('composeGasLimit', 'Gas limit to allocate for the compose call') + .addOptionalParam('refundAddress', 'Address receiving any leftover native fee') + .addOptionalParam('payInLzToken', 'Set to true to pay LayerZero fees with the LZ token (default false)', 'false') + .setAction(async (args: SendArgs, hre) => sendSupply(hre, args)) + +/* +pnpm hardhat stargate:supply-aave --network arbitrum-mainnet --stargate 0xe8cdf27acd73a434d661c84887215f7598e7d0d3 --dst-eid 30184 --composer 0xb38c4fc4b7c7672EfdA6f8b3a386e615049eed30 --amount-ld 1000000 +*/ From a42a10ca57b997f4800374e3109d696067edeab0 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 11:54:37 -0800 Subject: [PATCH 29/47] feat: add supply aave foundry script --- .../oft-composers/scripts/supplyAave.s.sol | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 examples/oft-composers/scripts/supplyAave.s.sol diff --git a/examples/oft-composers/scripts/supplyAave.s.sol b/examples/oft-composers/scripts/supplyAave.s.sol new file mode 100644 index 000000000..0927ca662 --- /dev/null +++ b/examples/oft-composers/scripts/supplyAave.s.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import "forge-std/Script.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IStargate } from "@stargatefinance/stg-evm-v2/src/interfaces/IStargate.sol"; +import { SendParam, MessagingFee, OFTReceipt } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol"; +import { OptionsBuilder } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OptionsBuilder.sol"; + +contract SupplyAaveScript is Script { + using OptionsBuilder for bytes; + + function run() external { + uint256 pk = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(pk); + + address sender = vm.addr(pk); + + address stargate = vm.envAddress("STARGATE_POOL"); + uint32 dstEid = uint32(vm.envUint("DST_EID")); + address composer = vm.envAddress("COMPOSER"); + uint256 amountLD = vm.envUint("AMOUNT_LD"); + address recipient = sender; + if (vm.envExists("COMPOSE_RECIPIENT")) { + recipient = vm.envAddress("COMPOSE_RECIPIENT"); + } + uint128 composeGas = 200000; + if (vm.envExists("COMPOSE_GAS_LIMIT")) { + composeGas = uint128(vm.envUint("COMPOSE_GAS_LIMIT")); + } + address refund = sender; + if (vm.envExists("REFUND_ADDRESS")) { + refund = vm.envAddress("REFUND_ADDRESS"); + } + bool payInLzToken = false; + if (vm.envExists("PAY_IN_LZ_TOKEN")) { + payInLzToken = vm.envBool("PAY_IN_LZ_TOKEN"); + } + + // Step 1: compose payload + bytes memory composeMsg = abi.encode(recipient, amountLD); + + // Step 2: options (compose index 0, gas limit, no native drop) + bytes memory extraOptions = OptionsBuilder.newOptions().addExecutorLzComposeOption(0, composeGas, 0); + + // Step 3: assemble SendParam with placeholder minAmount + SendParam memory sendParam = SendParam({ + dstEid: dstEid, + to: bytes32(uint256(uint160(composer))), + amountLD: amountLD, + minAmountLD: 0, + extraOptions: extraOptions, + composeMsg: composeMsg, + oftCmd: bytes("") + }); + + // Quote OFT to learn the actual receive amount + (, , OFTReceipt memory oftReceipt) = IStargate(stargate).quoteOFT(sendParam); + sendParam.minAmountLD = oftReceipt.amountReceivedLD; + sendParam.composeMsg = abi.encode(recipient, oftReceipt.amountReceivedLD); + + // Quote LayerZero messaging fee + MessagingFee memory fee = IStargate(stargate).quoteSend(sendParam, payInLzToken); + + // ERC20 approval if required + address token = IStargate(stargate).token(); + if (token != address(0)) { + _ensureApproval(token, sender, stargate, sendParam.amountLD); + } + + // Step 4: compute value (add amount if pool uses native token) + uint256 valueToSend = fee.nativeFee; + + // Step 5: send + (, OFTReceipt memory finalReceipt) = IStargate(stargate).send{ value: valueToSend }(sendParam, fee, refund); + + console.log("message sent; amount received LD =", finalReceipt.amountReceivedLD); + vm.stopBroadcast(); + } + + function _ensureApproval(address token, address owner, address spender, uint256 amount) internal { + IERC20 erc20 = IERC20(token); + if (erc20.allowance(owner, spender) < amount) { + erc20.approve(spender, type(uint256).max); + } + } +} + +/* + forge script scripts/supplyAave.s.sol:SupplyAaveScript \ + --rpc-url https://arbitrum.gateway.tenderly.co \ + --broadcast -vv --via-ir +*/ From b91bfb62fcaa7badb9e4e10301dc093534ec47e0 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 11:55:18 -0800 Subject: [PATCH 30/47] chore: add unit aave composer unit tests --- .../test/foundry/AaveV3Composer.t.sol | 161 ++++++++++++++++++ .../test/mocks/AaveV3PoolMock.sol | 35 ++++ .../test/mocks/StargatePoolMock.sol | 22 +++ 3 files changed, 218 insertions(+) create mode 100644 examples/oft-composers/test/foundry/AaveV3Composer.t.sol create mode 100644 examples/oft-composers/test/mocks/AaveV3PoolMock.sol create mode 100644 examples/oft-composers/test/mocks/StargatePoolMock.sol diff --git a/examples/oft-composers/test/foundry/AaveV3Composer.t.sol b/examples/oft-composers/test/foundry/AaveV3Composer.t.sol new file mode 100644 index 000000000..addc64612 --- /dev/null +++ b/examples/oft-composers/test/foundry/AaveV3Composer.t.sol @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +// Testing libraries +import "forge-std/Test.sol"; +import { TestHelperOz5 } from "@layerzerolabs/test-devtools-evm-foundry/contracts/TestHelperOz5.sol"; + +// Composer contracts +import { AaveV3Composer } from "../../contracts/AaveV3Composer/AaveV3Composer.sol"; +import { IAaveV3Composer } from "../../contracts/AaveV3Composer/IAaveV3Composer.sol"; + +// LayerZero helpers +import { OFTComposeMsgCodec } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol"; + +// Mock dependencies +import { ERC20Mock } from "../mocks/ERC20Mock.sol"; +import { AaveV3PoolMock } from "../mocks/AaveV3PoolMock.sol"; +import { StargatePoolMock } from "../mocks/StargatePoolMock.sol"; + +// OpenZeppelin interfaces +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/** + * @title AaveV3ComposerTest + * @notice Unit tests for the `AaveV3Composer` contract. + */ +contract AaveV3ComposerTest is TestHelperOz5 { + // ---------------------------- + // ============ Setup =========== + // ---------------------------- + + // Endpoint identifiers + uint32 private constant aEid = 1; + uint32 private constant bEid = 2; + + // Token balances + uint256 private constant initialBalance = 100 ether; + uint256 private constant amountLD = 1 ether; + + // Mock contracts + ERC20Mock private token; + AaveV3PoolMock private aave; + StargatePoolMock private stargate; + AaveV3Composer private composer; + + // User addresses + address private userA; + address private receiver; + + /** + * @notice Sets up the testing environment before each test. + * @dev Deploys mocks, configures endpoints, and seeds initial token balances. + */ + function setUp() public override { + super.setUp(); + setUpEndpoints(2, LibraryType.UltraLightNode); + token = new ERC20Mock("TokenIn", "TIN"); + stargate = new StargatePoolMock(address(endpoints[bEid]), address(token)); + aave = new AaveV3PoolMock(address(token)); + composer = new AaveV3Composer(address(aave), address(stargate)); + token.mint(address(composer), initialBalance); + userA = makeAddr("userA"); + receiver = makeAddr("receiver"); + } + + // ---------------------------- + // ========= Constructor ======= + // ---------------------------- + + /** + * @notice Verifies the constructor initializes contract state correctly. + * @dev Asserts dependencies, endpoints, and allowances are configured as expected. + */ + function test_constructor() public view { + assertEq(address(composer.aave()), address(aave)); + assertEq(composer.endpoint(), address(endpoints[bEid])); + assertEq(composer.stargate(), address(stargate)); + assertEq(composer.tokenIn(), address(token)); + assertEq(IERC20(address(token)).allowance(address(composer), address(aave)), type(uint256).max); + } + + // ---------------------------- + // ========= Test Cases ======= + // ---------------------------- + + /** + * @notice Tests that a successful `lzCompose` call supplies tokens to Aave. + * @dev Confirms the mock pool receives the correct parameters and token balance updates. + */ + function test_lzCompose_supply() public { + bytes memory composeMsg = abi.encode(receiver); + bytes memory fullMessage = OFTComposeMsgCodec.encode( + 1, + aEid, + amountLD, + abi.encodePacked(addressToBytes32(userA), composeMsg) + ); + vm.prank(address(endpoints[bEid])); + composer.lzCompose(address(stargate), bytes32(0), fullMessage, address(0), bytes("")); + assertEq(aave.lastAsset(), address(token)); + assertEq(aave.lastAmount(), amountLD); + assertEq(aave.lastOnBehalfOf(), receiver); + assertEq(aave.tokenBalance(), amountLD); + assertEq(token.balanceOf(address(composer)), initialBalance - amountLD); + } + + /** + * @notice Tests the fallback path when the Aave pool reverts. + * @dev Ensures the composer transfers tokens directly to the receiver on failure. + */ + function test_lzCompose_fallback() public { + aave.setShouldRevert(true); + uint256 composerBalanceBefore = token.balanceOf(address(composer)); + uint256 receiverBalanceBefore = token.balanceOf(receiver); + bytes memory composeMsg = abi.encode(receiver); + bytes memory fullMessage = OFTComposeMsgCodec.encode( + 1, + aEid, + amountLD, + abi.encodePacked(addressToBytes32(userA), composeMsg) + ); + vm.prank(address(endpoints[bEid])); + composer.lzCompose(address(stargate), bytes32(0), fullMessage, address(0), bytes("")); + assertEq(token.balanceOf(address(composer)), composerBalanceBefore - amountLD); + assertEq(token.balanceOf(receiver), receiverBalanceBefore + amountLD); + assertEq(aave.tokenBalance(), 0); + } + + /** + * @notice Tests `lzCompose` reverts when called by an unauthorized Stargate pool. + * @dev Expects the `UnauthorizedStargatePool` error from `IAaveV3Composer`. + */ + function test_lzCompose_unauthorizedStargate() public { + bytes memory composeMsg = abi.encode(receiver); + bytes memory fullMessage = OFTComposeMsgCodec.encode( + 1, + aEid, + amountLD, + abi.encodePacked(addressToBytes32(userA), composeMsg) + ); + vm.prank(address(endpoints[bEid])); + vm.expectRevert(IAaveV3Composer.UnauthorizedStargatePool.selector); + composer.lzCompose(address(0x1234), bytes32(0), fullMessage, address(0), bytes("")); + } + + /** + * @notice Tests `lzCompose` reverts when invoked from an unauthorized endpoint. + * @dev Expects the `UnauthorizedEndpoint` error from `IAaveV3Composer`. + */ + function test_lzCompose_unauthorizedEndpoint() public { + bytes memory composeMsg = abi.encode(receiver); + bytes memory fullMessage = OFTComposeMsgCodec.encode( + 1, + aEid, + amountLD, + abi.encodePacked(addressToBytes32(userA), composeMsg) + ); + vm.expectRevert(IAaveV3Composer.UnauthorizedEndpoint.selector); + composer.lzCompose(address(stargate), bytes32(0), fullMessage, address(0), bytes("")); + } +} diff --git a/examples/oft-composers/test/mocks/AaveV3PoolMock.sol b/examples/oft-composers/test/mocks/AaveV3PoolMock.sol new file mode 100644 index 000000000..18a1f3192 --- /dev/null +++ b/examples/oft-composers/test/mocks/AaveV3PoolMock.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IPool } from "../../contracts/AaveV3Composer/IAaveV3Pool.sol"; + +contract AaveV3PoolMock is IPool { + address public lastAsset; + uint256 public lastAmount; + address public lastOnBehalfOf; + uint16 public lastReferralCode; + bool public shouldRevert; + IERC20 private immutable _token; + + constructor(address token_) { + _token = IERC20(token_); + } + + function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external override { + if (shouldRevert) revert(); + lastAsset = asset; + lastAmount = amount; + lastOnBehalfOf = onBehalfOf; + lastReferralCode = referralCode; + _token.transferFrom(msg.sender, address(this), amount); + } + + function setShouldRevert(bool value) external { + shouldRevert = value; + } + + function tokenBalance() external view returns (uint256) { + return _token.balanceOf(address(this)); + } +} diff --git a/examples/oft-composers/test/mocks/StargatePoolMock.sol b/examples/oft-composers/test/mocks/StargatePoolMock.sol new file mode 100644 index 000000000..fde395be8 --- /dev/null +++ b/examples/oft-composers/test/mocks/StargatePoolMock.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; + +contract StargatePoolMock { + ILayerZeroEndpointV2 private immutable _endpoint; + address private immutable _token; + + constructor(address endpoint_, address token_) { + _endpoint = ILayerZeroEndpointV2(endpoint_); + _token = token_; + } + + function endpoint() external view returns (ILayerZeroEndpointV2) { + return _endpoint; + } + + function token() external view returns (address) { + return _token; + } +} From 618decbe8127f7dc3037c6d0bb34b9fad8d95bef Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 11:55:58 -0800 Subject: [PATCH 31/47] chore: added packages --- examples/oft-composers/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/oft-composers/package.json b/examples/oft-composers/package.json index 6f221f73a..c6fc2e366 100644 --- a/examples/oft-composers/package.json +++ b/examples/oft-composers/package.json @@ -24,8 +24,10 @@ "@babel/core": "^7.23.9", "@layerzerolabs/devtools-evm-hardhat": "^2.0.1", "@layerzerolabs/eslint-config-next": "~2.3.39", + "@layerzerolabs/io-devtools": "^0.2.1", "@layerzerolabs/lz-definitions": "^3.0.12", "@layerzerolabs/lz-evm-messagelib-v2": "^3.0.12", + "@layerzerolabs/lz-evm-oapp-v2": "^3.0.145", "@layerzerolabs/lz-evm-protocol-v2": "^3.0.12", "@layerzerolabs/lz-evm-v1-0.7": "^3.0.12", "@layerzerolabs/lz-v2-utilities": "^3.0.12", @@ -41,6 +43,7 @@ "@openzeppelin/contracts": "^5.0.2", "@openzeppelin/contracts-upgradeable": "^5.0.2", "@rushstack/eslint-patch": "^1.7.0", + "@stargatefinance/stg-evm-v2": "^5.0.3", "@types/chai": "^4.3.11", "@types/mocha": "^10.0.6", "@types/node": "~18.18.14", From 34df4436c00d1d56c39c95508ca94bad1ee30639 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 11:56:20 -0800 Subject: [PATCH 32/47] chore: add tasks to config --- examples/oft-composers/hardhat.config.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/examples/oft-composers/hardhat.config.ts b/examples/oft-composers/hardhat.config.ts index 53c186deb..ce521a782 100644 --- a/examples/oft-composers/hardhat.config.ts +++ b/examples/oft-composers/hardhat.config.ts @@ -9,6 +9,9 @@ import 'hardhat-deploy' import 'hardhat-contract-sizer' import '@nomiclabs/hardhat-ethers' import '@layerzerolabs/toolbox-hardhat' + +import './tasks/index' + import { HardhatUserConfig, HttpNetworkAccountsUserConfig } from 'hardhat/types' import { EndpointId } from '@layerzerolabs/lz-definitions' @@ -52,19 +55,14 @@ const config: HardhatUserConfig = { ], }, networks: { - 'sepolia-testnet': { - eid: EndpointId.SEPOLIA_V2_TESTNET, - url: process.env.RPC_URL_SEPOLIA || 'https://rpc.sepolia.org/', - accounts, - }, - 'avalanche-testnet': { - eid: EndpointId.AVALANCHE_V2_TESTNET, - url: process.env.RPC_URL_FUJI || 'https://rpc.ankr.com/avalanche_fuji', + 'arbitrum-mainnet': { + eid: EndpointId.ARBITRUM_V2_MAINNET, + url: process.env.RPC_URL_ARBITRUM || 'https://arbitrum.gateway.tenderly.co', accounts, }, - 'amoy-testnet': { - eid: EndpointId.AMOY_V2_TESTNET, - url: process.env.RPC_URL_AMOY || 'https://polygon-amoy-bor-rpc.publicnode.com', + 'base-mainnet': { + eid: EndpointId.BASE_V2_MAINNET, + url: process.env.RPC_URL_BASE || 'https://base.gateway.tenderly.co', accounts, }, hardhat: { From ddd115584642066d507e7f8ce52b36e120d7de19 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 11:56:48 -0800 Subject: [PATCH 33/47] chore: update lock file --- pnpm-lock.yaml | 1958 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 1653 insertions(+), 305 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 13bbdbc8c..5d08ac49f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,7 +81,7 @@ importers: dependencies: '@layerzerolabs/devtools': specifier: ^1.0.0 - version: link:../../packages/devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm-hardhat': specifier: ^3.1.0 version: link:../../packages/devtools-evm-hardhat @@ -93,7 +93,7 @@ importers: version: link:../../packages/export-deployments '@layerzerolabs/io-devtools': specifier: ^0.2.0 - version: link:../../packages/io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-evm-sdk-v1': specifier: ^3.0.49 version: 3.0.59 @@ -178,7 +178,7 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -190,10 +190,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -295,10 +295,10 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -310,10 +310,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.9 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -409,10 +409,10 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -424,10 +424,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.9 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -526,7 +526,7 @@ importers: version: link:../../packages/metadata-tools '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -538,10 +538,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -628,7 +628,7 @@ importers: version: link:../../packages/devtools-extensible-cli '@layerzerolabs/devtools-move': specifier: ^1.0.9 - version: link:../../packages/devtools-move + version: 1.0.14(@babel/core@7.23.9)(@types/node@18.18.14)(esbuild@0.19.11)(ts-node@10.9.2)(typescript@5.5.3) '@layerzerolabs/eslint-config-next': specifier: ~2.3.39 version: 2.3.44(typescript@5.5.3) @@ -664,13 +664,13 @@ importers: version: 3.0.59 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-move': specifier: ^1.1.0 - version: link:../../packages/oft-move + version: 1.1.2 '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -682,10 +682,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.9 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -808,7 +808,7 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -820,10 +820,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.9 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -920,7 +920,7 @@ importers: version: 0.29.0 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../../packages/devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) '@layerzerolabs/devtools-evm-hardhat': specifier: ^3.1.0 version: link:../../packages/devtools-evm-hardhat @@ -932,7 +932,7 @@ importers: version: 2.3.44(typescript@5.5.3) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../../packages/io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.86 version: 3.0.86 @@ -956,7 +956,7 @@ importers: version: link:../../packages/metadata-tools '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -974,10 +974,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@layerzerolabs/ua-devtools': specifier: ~4.0.0 version: link:../../packages/ua-devtools @@ -1130,10 +1130,10 @@ importers: version: link:../../packages/metadata-tools '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -1145,10 +1145,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -1244,10 +1244,10 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -1259,10 +1259,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.9 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -1352,7 +1352,7 @@ importers: version: link:../../packages/devtools-extensible-cli '@layerzerolabs/devtools-move': specifier: ^1.0.9 - version: link:../../packages/devtools-move + version: 1.0.14(@babel/core@7.23.9)(@types/node@18.18.14)(esbuild@0.19.11)(ts-node@10.9.2)(typescript@5.5.3) '@layerzerolabs/eslint-config-next': specifier: ~2.3.39 version: 2.3.44(typescript@5.5.3) @@ -1388,13 +1388,13 @@ importers: version: 3.0.59 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-move': specifier: ^1.1.0 - version: link:../../packages/oft-move + version: 1.1.2 '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -1406,10 +1406,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.10 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -1523,7 +1523,7 @@ importers: version: link:../../packages/devtools-extensible-cli '@layerzerolabs/devtools-move': specifier: ^1.0.9 - version: link:../../packages/devtools-move + version: 1.0.14(@babel/core@7.23.9)(@types/node@18.18.14)(esbuild@0.19.11)(ts-node@10.9.2)(typescript@5.5.3) '@layerzerolabs/eslint-config-next': specifier: ~2.3.39 version: 2.3.44(typescript@5.5.3) @@ -1559,13 +1559,13 @@ importers: version: 3.0.59 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-move': specifier: ^1.1.0 - version: link:../../packages/oft-move + version: 1.1.2 '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -1577,10 +1577,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.10 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -1706,13 +1706,13 @@ importers: version: link:../../packages/oapp-alt-evm '@layerzerolabs/oapp-evm': specifier: ^0.3.0 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-alt-evm': specifier: ^0.0.3 version: link:../../packages/oft-alt-evm '@layerzerolabs/oft-evm': specifier: ^3.0.0 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -1724,10 +1724,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.9 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.10 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -1814,7 +1814,7 @@ importers: version: link:../../packages/devtools-extensible-cli '@layerzerolabs/devtools-move': specifier: ^1.0.9 - version: link:../../packages/devtools-move + version: 1.0.14(@babel/core@7.23.9)(@types/node@18.18.14)(esbuild@0.19.11)(ts-node@10.9.2)(typescript@5.5.3) '@layerzerolabs/eslint-config-next': specifier: ~2.3.39 version: 2.3.44(typescript@5.5.3) @@ -1850,13 +1850,13 @@ importers: version: 3.0.59 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-move': specifier: ^1.1.0 - version: link:../../packages/oft-move + version: 1.1.2 '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -1868,10 +1868,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.9 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -1966,23 +1966,29 @@ importers: specifier: ^2.6.1 version: 2.7.0 - examples/oft-composer-library: + examples/oft-composers: devDependencies: '@babel/core': specifier: ^7.23.9 version: 7.23.9 '@layerzerolabs/devtools-evm-hardhat': specifier: ^2.0.1 - version: 2.0.9(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@1.0.6)(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12) + version: 2.0.9(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@1.0.6)(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12) '@layerzerolabs/eslint-config-next': specifier: ~2.3.39 version: 2.3.44(typescript@5.5.3) + '@layerzerolabs/io-devtools': + specifier: ^0.2.1 + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.12 version: 3.0.86 '@layerzerolabs/lz-evm-messagelib-v2': specifier: ^3.0.12 version: 3.0.86(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-oapp-v2': + specifier: ^3.0.145 + version: 3.0.145(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) '@layerzerolabs/lz-evm-protocol-v2': specifier: ^3.0.12 version: 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) @@ -1994,10 +2000,10 @@ importers: version: 3.0.86 '@layerzerolabs/oapp-evm': specifier: ^0.3.0 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-evm': specifier: ^3.0.0 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -2006,13 +2012,13 @@ importers: version: 3.0.12(typescript@5.5.3) '@layerzerolabs/test-devtools-evm-foundry': specifier: ~5.1.0 - version: 5.1.0(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@packages+oapp-evm)(@layerzerolabs/oft-evm@packages+oft-evm)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) + version: 5.1.0(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@0.3.3)(@layerzerolabs/oft-evm@3.2.1)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/toolbox-foundry': specifier: ~0.1.9 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.0 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -2028,6 +2034,9 @@ importers: '@rushstack/eslint-patch': specifier: ^1.7.0 version: 1.7.0 + '@stargatefinance/stg-evm-v2': + specifier: ^5.0.3 + version: 5.0.3(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(@types/node@18.18.14)(chai@4.5.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2)(typescript@5.5.3) '@types/chai': specifier: ^4.3.11 version: 4.3.20 @@ -2123,10 +2132,10 @@ importers: version: 3.0.86 '@layerzerolabs/oapp-evm': specifier: ^0.3.1 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-evm': specifier: ^3.1.2 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -2138,10 +2147,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.10 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -2241,7 +2250,7 @@ importers: version: link:../../packages/devtools-extensible-cli '@layerzerolabs/devtools-move': specifier: ^1.0.9 - version: link:../../packages/devtools-move + version: 1.0.14(@babel/core@7.23.9)(@types/node@18.18.14)(esbuild@0.19.11)(ts-node@10.9.2)(typescript@5.5.3) '@layerzerolabs/eslint-config-next': specifier: ~2.3.39 version: 2.3.44(typescript@5.5.3) @@ -2277,13 +2286,13 @@ importers: version: 3.0.59 '@layerzerolabs/oapp-evm': specifier: ^0.3.0 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-evm': specifier: ^3.0.0 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-move': specifier: ^1.1.0 - version: link:../../packages/oft-move + version: 1.1.2 '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -2295,10 +2304,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.9 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.3 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -2403,10 +2412,10 @@ importers: version: 5.7.0 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../../packages/devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../../packages/devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/devtools-evm-hardhat': specifier: ^3.1.0 version: link:../../packages/devtools-evm-hardhat @@ -2418,7 +2427,7 @@ importers: version: 2.3.44(typescript@5.5.3) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../../packages/io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.86 version: 3.0.86 @@ -2442,10 +2451,10 @@ importers: version: link:../../packages/metadata-tools '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/oft-v2-solana-sdk': specifier: ^3.0.86 version: 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(chai@4.4.1)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) @@ -2472,10 +2481,10 @@ importers: version: link:../../packages/test-devtools-evm-hardhat '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@layerzerolabs/ua-devtools': specifier: ~4.0.0 version: link:../../packages/ua-devtools @@ -2652,16 +2661,16 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/oapp-evm-upgradeable': specifier: ^0.1.2 version: link:../../packages/oapp-evm-upgradeable '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../../packages/oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/oft-evm-upgradeable': specifier: ^3.0.2 - version: link:../../packages/oft-evm-upgradeable + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -2673,10 +2682,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.10 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomiclabs/hardhat-ethers': specifier: ^2.2.3 version: 2.2.3(ethers@5.7.2)(hardhat@2.22.12) @@ -2781,7 +2790,7 @@ importers: version: 0.0.2(@layerzerolabs/devtools-evm-hardhat@2.0.9)(@layerzerolabs/ua-devtools@3.0.6) '@layerzerolabs/oapp-evm': specifier: ^0.3.0 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -2793,10 +2802,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.9 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.3 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -2895,7 +2904,7 @@ importers: version: link:../../packages/metadata-tools '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/onft-evm': specifier: ^0.2.3 version: link:../../packages/onft-evm @@ -2910,10 +2919,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -3006,7 +3015,7 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/onft-evm': specifier: ^0.2.3 version: link:../../packages/onft-evm @@ -3021,10 +3030,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.9 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@matterlabs/hardhat-zksync-deploy': specifier: ~0.9.0 version: 0.9.0(ethers@5.7.2)(hardhat@2.22.12)(zksync-ethers@5.9.0) @@ -3129,7 +3138,7 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -3141,10 +3150,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.9 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -3243,7 +3252,7 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -3255,10 +3264,10 @@ importers: version: link:../../packages/test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.9 - version: link:../../packages/toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.9 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -3367,13 +3376,13 @@ importers: version: 5.7.0 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-v2-utilities': specifier: ^3.0.75 version: 3.0.75 @@ -3422,7 +3431,7 @@ importers: devDependencies: '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@swc/core': specifier: ^1.4.0 version: 1.4.0 @@ -3501,13 +3510,13 @@ importers: version: 5.7.0 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-v2-utilities': specifier: ^3.0.75 version: 3.0.75 @@ -3568,7 +3577,7 @@ importers: version: 5.7.0 '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -3617,10 +3626,10 @@ importers: devDependencies: '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/ua-devtools': specifier: ~4.0.0 version: link:../ua-devtools @@ -3705,10 +3714,10 @@ importers: version: 5.7.2 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -3790,13 +3799,13 @@ importers: version: 5.7.0 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -3899,7 +3908,7 @@ importers: version: link:../devtools-extensible-cli '@layerzerolabs/io-devtools': specifier: ^0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -3914,7 +3923,7 @@ importers: version: 3.0.75 '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.10 - version: link:../toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@types/argparse': specifier: ^2.0.17 version: 2.0.17 @@ -3978,10 +3987,10 @@ importers: devDependencies: '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -4060,10 +4069,10 @@ importers: devDependencies: '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -4109,7 +4118,7 @@ importers: devDependencies: '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@swc/core': specifier: ^1.4.0 version: 1.4.0 @@ -4133,7 +4142,7 @@ importers: version: 2.16.2 jest: specifier: ^29.6.2 - version: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + version: 29.7.0(@types/node@18.18.14) tsup: specifier: ~8.0.1 version: 8.0.1(@swc/core@1.4.0)(typescript@5.5.3) @@ -4158,7 +4167,7 @@ importers: devDependencies: '@layerzerolabs/io-devtools': specifier: ^0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.81 version: 3.0.86 @@ -4173,10 +4182,10 @@ importers: version: 3.0.86(@types/node@22.15.3)(typescript@5.5.3) '@layerzerolabs/oapp-evm': specifier: ^0.3.1 - version: link:../oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-evm': specifier: ^3.1.2 - version: link:../oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/prettier-config-next': specifier: ^2.3.39 version: 2.3.44 @@ -4185,10 +4194,10 @@ importers: version: 3.0.12(typescript@5.5.3) '@layerzerolabs/toolbox-foundry': specifier: ^0.1.12 - version: link:../toolbox-foundry + version: 0.1.13 '@layerzerolabs/toolbox-hardhat': specifier: ^0.6.10 - version: link:../toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@msgpack/msgpack': specifier: ^3.0.0-beta2 version: 3.1.1 @@ -4318,7 +4327,7 @@ importers: version: 29.5.12 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + version: 29.7.0(@types/node@18.18.14) tslib: specifier: ~2.6.2 version: 2.6.3 @@ -4346,13 +4355,13 @@ importers: version: 3.0.75(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/test-devtools-evm-foundry': specifier: ~6.0.3 version: link:../test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ^0.1.12 - version: link:../toolbox-foundry + version: 0.1.13 '@openzeppelin/contracts': specifier: ^5.0.2 version: 5.1.0 @@ -4380,7 +4389,7 @@ importers: version: link:../test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ^0.1.12 - version: link:../toolbox-foundry + version: 0.1.13 '@openzeppelin/contracts': specifier: ^5.0.2 version: 5.0.2 @@ -4405,13 +4414,13 @@ importers: version: 3.0.75(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4) '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/test-devtools-evm-foundry': specifier: ~6.0.3 version: link:../test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ^0.1.12 - version: link:../toolbox-foundry + version: 0.1.13 '@openzeppelin/contracts': specifier: ^5.0.2 version: 5.0.2 @@ -4435,16 +4444,16 @@ importers: version: link:../oapp-alt-evm '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@layerzerolabs/test-devtools-evm-foundry': specifier: ~6.0.3 version: link:../test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ^0.1.12 - version: link:../toolbox-foundry + version: 0.1.13 '@openzeppelin/contracts': specifier: ^5.0.2 version: 5.1.0 @@ -4465,13 +4474,13 @@ importers: version: 3.0.75(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4) '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/test-devtools-evm-foundry': specifier: ~6.0.3 version: link:../test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ^0.1.12 - version: link:../toolbox-foundry + version: 0.1.13 '@openzeppelin/contracts': specifier: ^5.0.2 version: 5.0.2 @@ -4495,19 +4504,19 @@ importers: version: 3.0.75(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4) '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/oapp-evm-upgradeable': specifier: ^0.1.2 version: link:../oapp-evm-upgradeable '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/test-devtools-evm-foundry': specifier: ~6.0.3 version: link:../test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ^0.1.12 - version: link:../toolbox-foundry + version: 0.1.13 '@openzeppelin/contracts': specifier: ^5.0.2 version: 5.0.2 @@ -4528,10 +4537,10 @@ importers: version: link:../devtools-extensible-cli '@layerzerolabs/devtools-move': specifier: ^1.0.9 - version: link:../devtools-move + version: 1.0.14(@babel/core@7.23.9)(@types/node@18.18.14)(esbuild@0.19.11)(ts-node@10.9.2)(typescript@5.5.3) '@layerzerolabs/io-devtools': specifier: ^0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -4570,7 +4579,7 @@ importers: devDependencies: '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -4613,10 +4622,10 @@ importers: devDependencies: '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -4679,13 +4688,13 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/test-devtools-evm-foundry': specifier: ~6.0.3 version: link:../test-devtools-evm-foundry '@layerzerolabs/toolbox-foundry': specifier: ~0.1.12 - version: link:../toolbox-foundry + version: 0.1.13 '@openzeppelin/contracts': specifier: ^5.0.2 version: 5.0.2 @@ -4700,10 +4709,10 @@ importers: devDependencies: '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -4767,13 +4776,13 @@ importers: version: 5.7.2 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -4834,25 +4843,25 @@ importers: devDependencies: '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-solana': specifier: ~2.1.0 version: link:../devtools-solana '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 '@layerzerolabs/lz-solana-sdk-v2': specifier: ^3.0.0 - version: 3.0.0(typescript@5.5.3) + version: 3.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/lz-v2-utilities': specifier: ^3.0.75 version: 3.0.75 '@layerzerolabs/oft-v2-solana-sdk': specifier: ^3.0.38 - version: 3.0.38(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + version: 3.0.38(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/protocol-devtools': specifier: ~2.0.0 version: link:../protocol-devtools @@ -4943,10 +4952,10 @@ importers: dependencies: '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) devDependencies: '@layerzerolabs/lz-evm-messagelib-v2': specifier: ^3.0.75 @@ -4959,7 +4968,7 @@ importers: version: 3.0.75(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4) '@layerzerolabs/toolbox-foundry': specifier: ^0.1.12 - version: link:../toolbox-foundry + version: 0.1.13 '@openzeppelin/contracts': specifier: ^5.0.2 version: 5.0.2 @@ -4992,10 +5001,10 @@ importers: version: 3.0.75(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5)(hardhat-deploy@0.12.4) '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5) '@layerzerolabs/oft-evm': specifier: ^3.1.3 - version: link:../oft-evm + version: 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5) '@openzeppelin/contracts': specifier: ^4.9.5 version: 4.9.5 @@ -5121,16 +5130,16 @@ importers: version: 5.7.0 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/devtools-evm-hardhat': specifier: ~3.1.0 version: link:../devtools-evm-hardhat '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -5221,10 +5230,10 @@ importers: devDependencies: '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -5294,13 +5303,13 @@ importers: version: 5.7.2 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -5376,16 +5385,16 @@ importers: version: 5.7.2 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/devtools-evm-hardhat': specifier: ~3.1.0 version: link:../devtools-evm-hardhat '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -5461,25 +5470,25 @@ importers: devDependencies: '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-solana': specifier: ~2.1.0 version: link:../devtools-solana '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 '@layerzerolabs/lz-solana-sdk-v2': specifier: ^3.0.59 - version: 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + version: 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/lz-v2-utilities': specifier: ^3.0.75 version: 3.0.75 '@layerzerolabs/oft-v2-solana-sdk': specifier: ^3.0.59 - version: 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + version: 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/protocol-devtools': specifier: ~2.0.0 version: link:../protocol-devtools @@ -5554,7 +5563,7 @@ importers: version: 5.7.0 '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@solidity-parser/parser': specifier: ^0.16.1 version: 0.16.2 @@ -5584,7 +5593,7 @@ importers: version: 12.6.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + version: 29.7.0(@types/node@18.18.14) tsup: specifier: ^8.0.1 version: 8.0.1(@swc/core@1.4.0)(typescript@5.5.3) @@ -5623,19 +5632,19 @@ importers: version: 5.7.0 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../../packages/devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-cli': specifier: ~0.0.6 - version: link:../../packages/devtools-cli + version: 0.0.7 '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../../packages/devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/devtools-evm-hardhat': specifier: ~3.1.0 version: link:../../packages/devtools-evm-hardhat '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../../packages/io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -5656,7 +5665,7 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/omnicounter-devtools': specifier: ~4.0.0 version: link:../../packages/omnicounter-devtools @@ -5677,7 +5686,7 @@ importers: version: link:../test-setup-devtools-evm-hardhat '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@layerzerolabs/ua-devtools': specifier: ~4.0.0 version: link:../../packages/ua-devtools @@ -5764,16 +5773,16 @@ importers: version: 5.7.0 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../../packages/devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../../packages/devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/devtools-evm-hardhat': specifier: ~3.1.0 version: link:../../packages/devtools-evm-hardhat '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../../packages/io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -5815,7 +5824,7 @@ importers: version: link:../test-setup-devtools-evm-hardhat '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -5884,10 +5893,10 @@ importers: version: 5.7.2 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../../packages/devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../../packages/devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -5938,13 +5947,13 @@ importers: version: link:../../packages/export-deployments '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../../packages/io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/test-setup-devtools-evm-hardhat': specifier: ~8.0.0 version: link:../test-setup-devtools-evm-hardhat '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.5 version: 3.0.5(ethers@5.7.2)(hardhat@2.22.12) @@ -6016,16 +6025,16 @@ importers: version: 5.7.2 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../../packages/devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../../packages/devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/devtools-evm-hardhat': specifier: ~3.1.0 version: link:../../packages/devtools-evm-hardhat '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../../packages/io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -6094,16 +6103,16 @@ importers: version: 5.7.0 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../../packages/devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../../packages/devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/devtools-evm-hardhat': specifier: ~3.1.0 version: link:../../packages/devtools-evm-hardhat '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../../packages/io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -6124,7 +6133,7 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/omnicounter-devtools': specifier: ~4.0.0 version: link:../../packages/omnicounter-devtools @@ -6145,7 +6154,7 @@ importers: version: link:../test-setup-devtools-evm-hardhat '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@layerzerolabs/ua-devtools': specifier: ~4.0.0 version: link:../../packages/ua-devtools @@ -6232,16 +6241,16 @@ importers: version: 5.7.0 '@layerzerolabs/devtools': specifier: ~1.0.0 - version: link:../../packages/devtools + version: 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) '@layerzerolabs/devtools-evm': specifier: ~2.0.0 - version: link:../../packages/devtools-evm + version: 2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/devtools-evm-hardhat': specifier: ~3.1.0 version: link:../../packages/devtools-evm-hardhat '@layerzerolabs/io-devtools': specifier: ~0.2.0 - version: link:../../packages/io-devtools + version: 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': specifier: ^3.0.75 version: 3.0.75 @@ -6268,7 +6277,7 @@ importers: version: 3.0.75 '@layerzerolabs/oapp-evm': specifier: ^0.3.2 - version: link:../../packages/oapp-evm + version: 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2) '@layerzerolabs/omnicounter-devtools': specifier: ~4.0.0 version: link:../../packages/omnicounter-devtools @@ -6289,7 +6298,7 @@ importers: version: link:../test-setup-devtools-evm-hardhat '@layerzerolabs/toolbox-hardhat': specifier: ~0.6.11 - version: link:../../packages/toolbox-hardhat + version: 0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) '@layerzerolabs/ua-devtools': specifier: ~4.0.0 version: link:../../packages/ua-devtools @@ -9080,7 +9089,56 @@ packages: '@kinobi-so/visitors-core': 0.21.5 dev: false - /@layerzerolabs/devtools-evm-hardhat@2.0.9(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@1.0.6)(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12): + /@layerzerolabs/devtools-cli@0.0.7: + resolution: {integrity: sha512-AijfRxDj7pRjme+Ida0bGTIPx54CIy1E01jyS8+NMwlDIe67I4WbEUcjX895XoF2tOu8w15TD3iq//DCe7s8gQ==} + engines: {node: '>=18'} + hasBin: true + dependencies: + yoga-layout-prebuilt: 1.10.0 + dev: true + + /@layerzerolabs/devtools-evm-hardhat@2.0.9(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@1.0.6)(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12): + resolution: {integrity: sha512-7vNPHtypjx3IjLV5+wPHq1nOOt5FWy2Bw4pBmPBt5XMsz8uIFuVtrYMr7CraICkwMOZUYYeu5EnJeT6erhRDIA==} + peerDependencies: + '@ethersproject/abi': ^5.7.0 + '@ethersproject/abstract-signer': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/providers': ^5.7.0 + '@layerzerolabs/devtools': ~0.4.8 + '@layerzerolabs/devtools-evm': ~1.0.6 + '@layerzerolabs/io-devtools': ~0.1.16 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@nomiclabs/hardhat-ethers': ^2.2.3 + fp-ts: ^2.16.2 + hardhat: ^2.22.10 + hardhat-deploy: ^0.12.1 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/devtools': 0.4.10(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 1.0.6(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/export-deployments': 0.0.16 + '@layerzerolabs/io-devtools': 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.22.12) + '@safe-global/protocol-kit': 1.3.0(ethers@5.7.2) + fp-ts: 2.16.2 + hardhat: 2.22.12(ts-node@10.9.2)(typescript@5.5.3) + hardhat-deploy: 0.12.4 + micro-memoize: 4.1.2 + p-memoize: 4.0.4 + zod: 3.22.4 + transitivePeerDependencies: + - bufferutil + - encoding + - ethers + - supports-color + - utf-8-validate + dev: true + + /@layerzerolabs/devtools-evm-hardhat@2.0.9(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12): resolution: {integrity: sha512-7vNPHtypjx3IjLV5+wPHq1nOOt5FWy2Bw4pBmPBt5XMsz8uIFuVtrYMr7CraICkwMOZUYYeu5EnJeT6erhRDIA==} peerDependencies: '@ethersproject/abi': ^5.7.0 @@ -9100,10 +9158,92 @@ packages: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/contracts': 5.7.0 '@ethersproject/providers': 5.7.2 - '@layerzerolabs/devtools': 0.4.10(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) - '@layerzerolabs/devtools-evm': 1.0.6(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/export-deployments': 0.0.16 + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.22.12) + '@safe-global/protocol-kit': 1.3.0(ethers@5.7.2) + fp-ts: 2.16.2 + hardhat: 2.22.12(ts-node@10.9.2)(typescript@5.5.3) + hardhat-deploy: 0.12.4 + micro-memoize: 4.1.2 + p-memoize: 4.0.4 + zod: 3.22.4 + transitivePeerDependencies: + - bufferutil + - encoding + - ethers + - supports-color + - utf-8-validate + dev: true + + /@layerzerolabs/devtools-evm-hardhat@4.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12): + resolution: {integrity: sha512-RqF6hrVhkJ/O83cYXi744TPOaqBzi4W4+daVHpZsp1W32hDbojYNcXwHi7jldt7BOL0KT/t4A5lBVIcGzCh0YQ==} + peerDependencies: + '@ethersproject/abi': ^5.7.0 + '@ethersproject/abstract-signer': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/providers': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/devtools-evm': ~3.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@nomiclabs/hardhat-ethers': ^2.2.3 + fp-ts: ^2.16.2 + hardhat: ^2.22.10 + hardhat-deploy: ^0.12.1 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/export-deployments': 0.0.16 + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.22.12) + '@safe-global/protocol-kit': 1.3.0(ethers@5.7.2) + fp-ts: 2.16.2 + hardhat: 2.22.12(ts-node@10.9.2)(typescript@5.5.3) + hardhat-deploy: 0.12.1 + micro-memoize: 4.1.2 + p-memoize: 4.0.4 + zod: 3.22.4 + transitivePeerDependencies: + - bufferutil + - encoding + - ethers + - supports-color + - utf-8-validate + dev: true + + /@layerzerolabs/devtools-evm-hardhat@4.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12): + resolution: {integrity: sha512-RqF6hrVhkJ/O83cYXi744TPOaqBzi4W4+daVHpZsp1W32hDbojYNcXwHi7jldt7BOL0KT/t4A5lBVIcGzCh0YQ==} + peerDependencies: + '@ethersproject/abi': ^5.7.0 + '@ethersproject/abstract-signer': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/providers': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/devtools-evm': ~3.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@nomiclabs/hardhat-ethers': ^2.2.3 + fp-ts: ^2.16.2 + hardhat: ^2.22.10 + hardhat-deploy: ^0.12.1 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) '@layerzerolabs/export-deployments': 0.0.16 - '@layerzerolabs/io-devtools': 0.1.17(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': 3.0.86 '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.22.12) '@safe-global/protocol-kit': 1.3.0(ethers@5.7.2) @@ -9121,7 +9261,7 @@ packages: - utf-8-validate dev: true - /@layerzerolabs/devtools-evm@1.0.6(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(fp-ts@2.16.2)(zod@3.22.4): + /@layerzerolabs/devtools-evm@1.0.6(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(fp-ts@2.16.2)(zod@3.22.4): resolution: {integrity: sha512-9sHP5l2IGu2ccZnMkyh5zu5sCQLBOYYlU+9gziMCH5CsrnVCeP9/MvOumxpVWxxi76sEaajJGsTgEkjJ17aBPA==} peerDependencies: '@ethersproject/abi': ^5.7.0 @@ -9146,8 +9286,8 @@ packages: '@ethersproject/constants': 5.7.0 '@ethersproject/contracts': 5.7.0 '@ethersproject/providers': 5.7.2 - '@layerzerolabs/devtools': 0.4.10(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) - '@layerzerolabs/io-devtools': 0.1.17(zod@3.22.4) + '@layerzerolabs/devtools': 0.4.10(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': 3.0.86 '@safe-global/api-kit': 1.3.1 '@safe-global/protocol-kit': 1.3.0(ethers@5.7.2) @@ -9162,83 +9302,443 @@ packages: - utf-8-validate dev: true - /@layerzerolabs/devtools@0.4.10(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4): - resolution: {integrity: sha512-Y9kjUQuyNfm9Vs07+Mk0+KkqHPwHN2cLSzKhe5Tp+52R7d4fI5zsn33IaJsqqGWxSDL1sKq7gFMTdtglTdsA8A==} + /@layerzerolabs/devtools-evm@2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4): + resolution: {integrity: sha512-Tt1I+QZu9/0Do8CXb4l3w3gNyPYbfYwU16DgrNtBorzeCNlud7irLE+VMvTzE5lWa8EakHg5cRkaxuumD1dAew==} peerDependencies: - '@ethersproject/bytes': ~5.7.0 - '@layerzerolabs/io-devtools': ~0.1.16 + '@ethersproject/abi': ^5.7.0 + '@ethersproject/abstract-provider': ^5.7.0 + '@ethersproject/abstract-signer': ^5.7.0 + '@ethersproject/address': ~5.7.0 + '@ethersproject/bignumber': ^5.7.0 + '@ethersproject/constants': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/providers': ^5.7.0 + '@layerzerolabs/devtools': ~1.0.0 + '@layerzerolabs/io-devtools': ~0.2.0 '@layerzerolabs/lz-definitions': ^3.0.75 + fp-ts: ^2.16.2 zod: ^3.22.4 dependencies: - '@ethersproject/bytes': 5.7.0 - '@layerzerolabs/io-devtools': 0.1.17(zod@3.22.4) - '@layerzerolabs/lz-definitions': 3.0.86 - bs58: 6.0.0 - exponential-backoff: 3.1.1 - js-yaml: 4.1.0 + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/devtools': 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + '@safe-global/api-kit': 1.3.1 + '@safe-global/protocol-kit': 1.3.0(ethers@5.7.2) + ethers: 5.7.2 + fp-ts: 2.16.2 + p-memoize: 4.0.4 zod: 3.22.4 - dev: true - - /@layerzerolabs/eslint-config-next@2.3.44(typescript@5.5.3): - resolution: {integrity: sha512-WlBSy47LGPILdrNgzPiRtQf/hAY62IN37ncUsQwcr8T7cyX1HZREx2qljuXpvduLDAKn5otsm0XIqHuCRUHEFg==} - dependencies: - '@typescript-eslint/eslint-plugin': 7.7.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.1)(typescript@5.5.3) - '@typescript-eslint/parser': 7.7.1(eslint@8.57.1)(typescript@5.5.3) - eslint: 8.57.1 - eslint-config-prettier: 9.1.0(eslint@8.57.1) - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.1)(eslint-plugin-import@2.29.1)(eslint@8.57.1) - eslint-plugin-autofix: 2.2.0(eslint@8.57.1) - eslint-plugin-compat: 4.2.0(eslint@8.57.1) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) - eslint-plugin-prettier: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.1)(prettier@3.2.5) - eslint-plugin-unused-imports: 3.2.0(@typescript-eslint/eslint-plugin@7.7.1)(eslint@8.57.1) - prettier: 3.2.5 transitivePeerDependencies: - - '@types/eslint' - - eslint-import-resolver-node - - eslint-import-resolver-webpack + - bufferutil + - encoding - supports-color - - typescript - dev: true + - utf-8-validate - /@layerzerolabs/evm-sdks-core@3.0.59: - resolution: {integrity: sha512-LLzPakU4UVnyakSEi4VpztY5v0eLlcQnrl/aoHjdKjDOzqOlEaoQbb7BZJSmTyNbaVc/5qzgUhyL9aXuYuaBxg==} + /@layerzerolabs/devtools-evm@2.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(fp-ts@2.16.2)(zod@3.22.4): + resolution: {integrity: sha512-Tt1I+QZu9/0Do8CXb4l3w3gNyPYbfYwU16DgrNtBorzeCNlud7irLE+VMvTzE5lWa8EakHg5cRkaxuumD1dAew==} + peerDependencies: + '@ethersproject/abi': ^5.7.0 + '@ethersproject/abstract-provider': ^5.7.0 + '@ethersproject/abstract-signer': ^5.7.0 + '@ethersproject/address': ~5.7.0 + '@ethersproject/bignumber': ^5.7.0 + '@ethersproject/constants': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/providers': ^5.7.0 + '@layerzerolabs/devtools': ~1.0.0 + '@layerzerolabs/io-devtools': ~0.2.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + fp-ts: ^2.16.2 + zod: ^3.22.4 dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/devtools': 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + '@safe-global/api-kit': 1.3.1 + '@safe-global/protocol-kit': 1.3.0(ethers@5.7.2) ethers: 5.7.2 + fp-ts: 2.16.2 + p-memoize: 4.0.4 + zod: 3.22.4 transitivePeerDependencies: - bufferutil + - encoding + - supports-color - utf-8-validate - dev: false + dev: true - /@layerzerolabs/evm-sdks-core@3.0.75: - resolution: {integrity: sha512-Fym0KcwfSTuO4J/q/5SVN5IA7MlwcZAgfFluT0oEL6Nl5dSkEBx1kKeKgJjjnV6gl9XNZ6ovEsQcBws3oPF/mw==} + /@layerzerolabs/devtools-evm@3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4): + resolution: {integrity: sha512-k3oqoB8f4eQf111WtrFQOhzLaxsjEZn/N3o7Bbyn8HlNPPWCyockAfXZfTiJ5p5YXRBDJVO2RkwxsqE00wHnOw==} + peerDependencies: + '@ethersproject/abi': ^5.7.0 + '@ethersproject/abstract-provider': ^5.7.0 + '@ethersproject/abstract-signer': ^5.7.0 + '@ethersproject/address': ~5.7.0 + '@ethersproject/bignumber': ^5.7.0 + '@ethersproject/constants': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/providers': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + fp-ts: ^2.16.2 + zod: ^3.22.4 dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/devtools': 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + '@safe-global/api-kit': 1.3.1 + '@safe-global/protocol-kit': 1.3.0(ethers@5.7.2) ethers: 5.7.2 + fp-ts: 2.16.2 + p-memoize: 4.0.4 + zod: 3.22.4 transitivePeerDependencies: - bufferutil + - encoding + - supports-color - utf-8-validate - - /@layerzerolabs/export-deployments@0.0.16: - resolution: {integrity: sha512-tI+mKMx51qCrj+G42mrVR+5jAiRaiLCpnXiogjW7E3krbNbJenI1eYYX7U62ssXWXwTZfYSJ1Bw/zLAbs59sqw==} - hasBin: true - dependencies: - typescript: 5.5.3 dev: true - /@layerzerolabs/io-devtools@0.1.17(zod@3.22.4): - resolution: {integrity: sha512-3Todi2pGZFNlkKGb758AQ4inZOcxiiZHMLRfZyfNIyjslHa2vna2yOh4fQNvfIAZVKjZ0y80XNf6jkgPXz5RsQ==} + /@layerzerolabs/devtools-evm@3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4): + resolution: {integrity: sha512-k3oqoB8f4eQf111WtrFQOhzLaxsjEZn/N3o7Bbyn8HlNPPWCyockAfXZfTiJ5p5YXRBDJVO2RkwxsqE00wHnOw==} peerDependencies: - ink: ^3.2.0 - ink-gradient: ^2.0.0 - ink-table: ^3.1.0 - react: ^17.0.2 - yoga-layout-prebuilt: ^1.9.6 - zod: ^3.22.4 - peerDependenciesMeta: - ink: - optional: true - ink-gradient: - optional: true + '@ethersproject/abi': ^5.7.0 + '@ethersproject/abstract-provider': ^5.7.0 + '@ethersproject/abstract-signer': ^5.7.0 + '@ethersproject/address': ~5.7.0 + '@ethersproject/bignumber': ^5.7.0 + '@ethersproject/constants': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/providers': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + fp-ts: ^2.16.2 + zod: ^3.22.4 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + '@safe-global/api-kit': 1.3.1 + '@safe-global/protocol-kit': 1.3.0(ethers@5.7.2) + ethers: 5.7.2 + fp-ts: 2.16.2 + p-memoize: 4.0.4 + zod: 3.22.4 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: true + + /@layerzerolabs/devtools-evm@3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(fp-ts@2.16.2)(zod@3.22.4): + resolution: {integrity: sha512-k3oqoB8f4eQf111WtrFQOhzLaxsjEZn/N3o7Bbyn8HlNPPWCyockAfXZfTiJ5p5YXRBDJVO2RkwxsqE00wHnOw==} + peerDependencies: + '@ethersproject/abi': ^5.7.0 + '@ethersproject/abstract-provider': ^5.7.0 + '@ethersproject/abstract-signer': ^5.7.0 + '@ethersproject/address': ~5.7.0 + '@ethersproject/bignumber': ^5.7.0 + '@ethersproject/constants': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/providers': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + fp-ts: ^2.16.2 + zod: ^3.22.4 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + '@safe-global/api-kit': 1.3.1 + '@safe-global/protocol-kit': 1.3.0(ethers@5.7.2) + ethers: 5.7.2 + fp-ts: 2.16.2 + p-memoize: 4.0.4 + zod: 3.22.4 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: true + + /@layerzerolabs/devtools-move@1.0.14(@babel/core@7.23.9)(@types/node@18.18.14)(esbuild@0.19.11)(ts-node@10.9.2)(typescript@5.5.3): + resolution: {integrity: sha512-7uXYeIPlyWCzxH0DM+XnUH2nKdDE3Ut+lyySmHq7/rzX271RQpSh/z5SvYLYLpIFH5DH83AtfFcep89ogOOe2Q==} + engines: {node: '>=18.16.0'} + dependencies: + '@types/chai': 4.3.20 + chai: 4.5.0 + inquirer: 12.4.1(@types/node@18.18.14) + jest: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + ts-jest: 29.2.5(@babel/core@7.23.9)(esbuild@0.19.11)(jest@29.7.0)(typescript@5.5.3) + transitivePeerDependencies: + - '@babel/core' + - '@jest/transform' + - '@jest/types' + - '@types/node' + - babel-jest + - babel-plugin-macros + - esbuild + - node-notifier + - supports-color + - ts-node + - typescript + dev: true + + /@layerzerolabs/devtools@0.4.10(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4): + resolution: {integrity: sha512-Y9kjUQuyNfm9Vs07+Mk0+KkqHPwHN2cLSzKhe5Tp+52R7d4fI5zsn33IaJsqqGWxSDL1sKq7gFMTdtglTdsA8A==} + peerDependencies: + '@ethersproject/bytes': ~5.7.0 + '@layerzerolabs/io-devtools': ~0.1.16 + '@layerzerolabs/lz-definitions': ^3.0.75 + zod: ^3.22.4 + dependencies: + '@ethersproject/bytes': 5.7.0 + '@layerzerolabs/io-devtools': 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + bs58: 6.0.0 + exponential-backoff: 3.1.1 + js-yaml: 4.1.0 + zod: 3.22.4 + dev: true + + /@layerzerolabs/devtools@1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4): + resolution: {integrity: sha512-oz7zXqGSCkuTVe5wpoFF1gNtzQmJLBwCir+t32MbTlG7jamj6Zs9LL8x8/+LXvRNMOVOabTgdIpdEgWLRNVbhg==} + peerDependencies: + '@ethersproject/bytes': ~5.7.0 + '@layerzerolabs/io-devtools': ~0.2.1 + '@layerzerolabs/lz-definitions': ^3.0.75 + zod: ^3.22.4 + dependencies: + '@ethersproject/bytes': 5.7.0 + '@layerzerolabs/io-devtools': 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + bs58: 6.0.0 + exponential-backoff: 3.1.1 + js-yaml: 4.1.0 + zod: 3.22.4 + + /@layerzerolabs/devtools@1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4): + resolution: {integrity: sha512-oz7zXqGSCkuTVe5wpoFF1gNtzQmJLBwCir+t32MbTlG7jamj6Zs9LL8x8/+LXvRNMOVOabTgdIpdEgWLRNVbhg==} + peerDependencies: + '@ethersproject/bytes': ~5.7.0 + '@layerzerolabs/io-devtools': ~0.2.1 + '@layerzerolabs/lz-definitions': ^3.0.75 + zod: ^3.22.4 + dependencies: + '@ethersproject/bytes': 5.7.0 + '@layerzerolabs/io-devtools': 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + bs58: 6.0.0 + exponential-backoff: 3.1.1 + js-yaml: 4.1.0 + zod: 3.22.4 + dev: true + + /@layerzerolabs/devtools@2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4): + resolution: {integrity: sha512-YwXVZ8fdfyJ3oc2nEVbaAs+vLkc0CuCwcWuTuhMy0GkySoW5kAZyJ3rANUNvOLdhq09VTev2hvlo9q5WeMdy9g==} + peerDependencies: + '@ethersproject/bytes': ~5.7.0 + '@layerzerolabs/io-devtools': ~0.3.1 + '@layerzerolabs/lz-definitions': ^3.0.75 + zod: ^3.22.4 + dependencies: + '@ethersproject/bytes': 5.7.0 + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + bs58: 6.0.0 + exponential-backoff: 3.1.1 + js-yaml: 4.1.0 + zod: 3.22.4 + dev: true + + /@layerzerolabs/devtools@2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4): + resolution: {integrity: sha512-YwXVZ8fdfyJ3oc2nEVbaAs+vLkc0CuCwcWuTuhMy0GkySoW5kAZyJ3rANUNvOLdhq09VTev2hvlo9q5WeMdy9g==} + peerDependencies: + '@ethersproject/bytes': ~5.7.0 + '@layerzerolabs/io-devtools': ~0.3.1 + '@layerzerolabs/lz-definitions': ^3.0.75 + zod: ^3.22.4 + dependencies: + '@ethersproject/bytes': 5.7.0 + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + bs58: 6.0.0 + exponential-backoff: 3.1.1 + js-yaml: 4.1.0 + zod: 3.22.4 + dev: true + + /@layerzerolabs/eslint-config-next@2.3.44(typescript@5.5.3): + resolution: {integrity: sha512-WlBSy47LGPILdrNgzPiRtQf/hAY62IN37ncUsQwcr8T7cyX1HZREx2qljuXpvduLDAKn5otsm0XIqHuCRUHEFg==} + dependencies: + '@typescript-eslint/eslint-plugin': 7.7.1(@typescript-eslint/parser@7.7.1)(eslint@8.57.1)(typescript@5.5.3) + '@typescript-eslint/parser': 7.7.1(eslint@8.57.1)(typescript@5.5.3) + eslint: 8.57.1 + eslint-config-prettier: 9.1.0(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.7.1)(eslint-plugin-import@2.29.1)(eslint@8.57.1) + eslint-plugin-autofix: 2.2.0(eslint@8.57.1) + eslint-plugin-compat: 4.2.0(eslint@8.57.1) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) + eslint-plugin-prettier: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.1)(prettier@3.2.5) + eslint-plugin-unused-imports: 3.2.0(@typescript-eslint/eslint-plugin@7.7.1)(eslint@8.57.1) + prettier: 3.2.5 + transitivePeerDependencies: + - '@types/eslint' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + - typescript + dev: true + + /@layerzerolabs/evm-sdks-core@3.0.59: + resolution: {integrity: sha512-LLzPakU4UVnyakSEi4VpztY5v0eLlcQnrl/aoHjdKjDOzqOlEaoQbb7BZJSmTyNbaVc/5qzgUhyL9aXuYuaBxg==} + dependencies: + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@layerzerolabs/evm-sdks-core@3.0.75: + resolution: {integrity: sha512-Fym0KcwfSTuO4J/q/5SVN5IA7MlwcZAgfFluT0oEL6Nl5dSkEBx1kKeKgJjjnV6gl9XNZ6ovEsQcBws3oPF/mw==} + dependencies: + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + /@layerzerolabs/export-deployments@0.0.16: + resolution: {integrity: sha512-tI+mKMx51qCrj+G42mrVR+5jAiRaiLCpnXiogjW7E3krbNbJenI1eYYX7U62ssXWXwTZfYSJ1Bw/zLAbs59sqw==} + hasBin: true + dependencies: + typescript: 5.5.3 + dev: true + + /@layerzerolabs/io-devtools@0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4): + resolution: {integrity: sha512-NqENU8ixAhAyN2Wv8x7n/FVqjnY0Q2J0dIE64aSYNeLCyatINxsg8YSNVu2g7CjShTcqVPOtrU2zydxExDJ2Kw==} + peerDependencies: + ink: ^3.2.0 + ink-gradient: ^2.0.0 + ink-table: ^3.1.0 + react: ^17.0.2 + yoga-layout-prebuilt: ^1.9.6 + zod: ^3.22.4 + peerDependenciesMeta: + ink: + optional: true + ink-gradient: + optional: true + ink-table: + optional: true + react: + optional: true + yoga-layout-prebuilt: + optional: true + dependencies: + chalk: 4.1.2 + ink: 3.2.0(@types/react@17.0.75)(react@17.0.2) + ink-gradient: 2.0.0(ink@3.2.0)(react@17.0.2) + ink-table: 3.1.0(ink@3.2.0)(react@17.0.2) + logform: 2.6.0 + prompts: 2.4.2 + react: 17.0.2 + table: 6.8.2 + winston: 3.11.0 + yoga-layout-prebuilt: 1.10.0 + zod: 3.22.4 + + /@layerzerolabs/io-devtools@0.2.1(ink-gradient@2.0.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4): + resolution: {integrity: sha512-NqENU8ixAhAyN2Wv8x7n/FVqjnY0Q2J0dIE64aSYNeLCyatINxsg8YSNVu2g7CjShTcqVPOtrU2zydxExDJ2Kw==} + peerDependencies: + ink: ^3.2.0 + ink-gradient: ^2.0.0 + ink-table: ^3.1.0 + react: ^17.0.2 + yoga-layout-prebuilt: ^1.9.6 + zod: ^3.22.4 + peerDependenciesMeta: + ink: + optional: true + ink-gradient: + optional: true + ink-table: + optional: true + react: + optional: true + yoga-layout-prebuilt: + optional: true + dependencies: + chalk: 4.1.2 + ink: 3.2.0(@types/react@17.0.75)(react@17.0.2) + ink-gradient: 2.0.0(ink@3.2.0)(react@17.0.2) + logform: 2.6.0 + prompts: 2.4.2 + react: 17.0.2 + table: 6.8.2 + winston: 3.11.0 + yoga-layout-prebuilt: 1.10.0 + zod: 3.22.4 + dev: true + + /@layerzerolabs/io-devtools@0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4): + resolution: {integrity: sha512-sP65pO9Op7vLJV2nd5us3ip30S+ylOvT1JiISZineP6Bj1PaPWlXRmjbbznue1VYnF629l+VJ1nYN7a3f1UOTQ==} + peerDependencies: + ink: ^3.2.0 + ink-gradient: ^2.0.0 + ink-table: ^3.1.0 + react: ^17.0.2 + yoga-layout-prebuilt: ^1.9.6 + zod: ^3.22.4 + peerDependenciesMeta: + ink: + optional: true + ink-gradient: + optional: true ink-table: optional: true react: @@ -9247,10 +9747,15 @@ packages: optional: true dependencies: chalk: 4.1.2 + ink: 3.2.0(@types/react@17.0.75)(react@17.0.2) + ink-gradient: 2.0.0(ink@3.2.0)(react@17.0.2) + ink-table: 3.1.0(ink@3.2.0)(react@17.0.2) logform: 2.6.0 prompts: 2.4.2 + react: 17.0.2 table: 6.8.2 winston: 3.11.0 + yoga-layout-prebuilt: 1.10.0 zod: 3.22.4 dev: true @@ -9483,6 +9988,28 @@ packages: dependencies: tiny-invariant: 1.3.3 + /@layerzerolabs/lz-evm-messagelib-v2@2.0.11(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@layerzerolabs/lz-evm-protocol-v2@2.0.11)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2): + resolution: {integrity: sha512-i6nZvzxzH+3bMzGRxIzf6fFXTzxQIZ1vyduAoFTy3U2zK9xZUHunKFfpC+vqCY1goNzjBquX4VnClWMWlc5ZIA==} + peerDependencies: + '@axelar-network/axelar-gmp-sdk-solidity': ^5.6.3 + '@chainlink/contracts-ccip': ^0.7.6 + '@layerzerolabs/lz-evm-protocol-v2': ^2.0.11 + '@layerzerolabs/lz-evm-v1-0.7': ^2.0.11 + '@openzeppelin/contracts': ^4.8.1 + '@openzeppelin/contracts-upgradeable': ^4.8.1 + hardhat-deploy: ^0.12.1 + solidity-bytes-utils: ^0.8.0 + dependencies: + '@axelar-network/axelar-gmp-sdk-solidity': 5.10.0 + '@chainlink/contracts-ccip': 0.7.6(ethers@5.7.2) + '@layerzerolabs/lz-evm-protocol-v2': 2.0.11(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) + '@openzeppelin/contracts': 5.1.0 + '@openzeppelin/contracts-upgradeable': 5.1.0(@openzeppelin/contracts@5.1.0) + hardhat-deploy: 0.12.4 + solidity-bytes-utils: 0.8.2 + dev: true + /@layerzerolabs/lz-evm-messagelib-v2@3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2): resolution: {integrity: sha512-CYcZiAqcQkFKf+pxkigFBQCOU60jNeIpnEBMDkIx75hVSazbftqJ/wx9Jv3fVCxr2vQ6nw990b0mbjNBtOY1lw==} peerDependencies: @@ -9593,7 +10120,6 @@ packages: '@openzeppelin/contracts-upgradeable': 5.0.2(@openzeppelin/contracts@5.0.2) hardhat-deploy: 0.12.4 solidity-bytes-utils: 0.8.2 - dev: true /@layerzerolabs/lz-evm-messagelib-v2@3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2): resolution: {integrity: sha512-CYcZiAqcQkFKf+pxkigFBQCOU60jNeIpnEBMDkIx75hVSazbftqJ/wx9Jv3fVCxr2vQ6nw990b0mbjNBtOY1lw==} @@ -9811,6 +10337,58 @@ packages: - utf-8-validate dev: true + /@layerzerolabs/lz-evm-oapp-v2@2.3.44(@layerzerolabs/lz-evm-messagelib-v2@2.0.11)(@layerzerolabs/lz-evm-protocol-v2@2.0.11)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2): + resolution: {integrity: sha512-FNm9+OFKOl+/5JvpV6rMUoHZSePOcLtNJ+GHJuf38xPmEe0ehxFVQBw3iIfaH2dsWzRn/T7ZizV5ouId35FLdg==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^2.3.44 + '@layerzerolabs/lz-evm-protocol-v2': ^2.3.44 + '@layerzerolabs/lz-evm-v1-0.7': ^2.3.44 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + hardhat-deploy: ^0.12.1 + solidity-bytes-utils: ^0.8.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 2.0.11(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@layerzerolabs/lz-evm-protocol-v2@2.0.11)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 2.0.11(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) + '@openzeppelin/contracts': 5.1.0 + '@openzeppelin/contracts-upgradeable': 5.1.0(@openzeppelin/contracts@5.1.0) + hardhat-deploy: 0.12.4 + solidity-bytes-utils: 0.8.2 + dev: true + + /@layerzerolabs/lz-evm-oapp-v2@3.0.145(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2): + resolution: {integrity: sha512-nvRBArgNBuAXUxiOMC3vr95HcnsACp+ZsqPMT7nkAl3EBZj1nacPcd6IDxmDToNQYq6OP/7Pzc3C8PCE6VDOPA==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.145 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.145 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.145 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + hardhat-deploy: ^0.12.1 + solidity-bytes-utils: ^0.8.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.86(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) + '@openzeppelin/contracts': 5.1.0 + '@openzeppelin/contracts-upgradeable': 5.1.0(@openzeppelin/contracts@5.1.0) + hardhat-deploy: 0.12.4 + solidity-bytes-utils: 0.8.2 + dev: true + + /@layerzerolabs/lz-evm-protocol-v2@2.0.11(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2): + resolution: {integrity: sha512-hkcNheUjTOYNxoAnBTSatLLzLe71Y7kcmw1+56aazezyUb6SCu330V4sJg+jsp8Ag6Sb7y1tLLYn1Sa5EWgCxg==} + peerDependencies: + '@openzeppelin/contracts': ^4.8.1 + hardhat-deploy: ^0.12.1 + solidity-bytes-utils: ^0.8.0 + dependencies: + '@openzeppelin/contracts': 5.1.0 + hardhat-deploy: 0.12.4 + solidity-bytes-utils: 0.8.2 + dev: true + /@layerzerolabs/lz-evm-protocol-v2@3.0.75(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5)(hardhat-deploy@0.12.1)(solidity-bytes-utils@0.8.2): resolution: {integrity: sha512-x0rY7XRu9YU5tFjHBWxofdEsWFZ4dDjHGzNYaPKQIpTcoXZbVqnxZhJVcf0YBOpg7phrEOLWWhPXmNLz2nxUTQ==} peerDependencies: @@ -9893,7 +10471,6 @@ packages: '@openzeppelin/contracts-upgradeable': 5.0.2(@openzeppelin/contracts@5.0.2) hardhat-deploy: 0.12.4 solidity-bytes-utils: 0.8.2 - dev: true /@layerzerolabs/lz-evm-protocol-v2@3.0.75(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2): resolution: {integrity: sha512-x0rY7XRu9YU5tFjHBWxofdEsWFZ4dDjHGzNYaPKQIpTcoXZbVqnxZhJVcf0YBOpg7phrEOLWWhPXmNLz2nxUTQ==} @@ -9972,13 +10549,23 @@ packages: /@layerzerolabs/lz-evm-sdk-v1@3.0.75: resolution: {integrity: sha512-KUySJHXMz01mC4FqOCh3sKM0R0xfileh3EhNKIkuZgnWobVtqtBt7pmtzxiqalBatodQDgA7+I4eOEysWCRx1w==} dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/providers': 5.7.2 + '@ethersproject/abi': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/evm-sdks-core': 3.0.75 + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + /@layerzerolabs/lz-evm-sdk-v2@3.0.30: + resolution: {integrity: sha512-UMP/Z8MWrKeklK7zjjbjn+GS9dPUcZsa1Y70uFXGq1j9V/xkLGIH+T9IltKndLR/W+Z/t3UhgjswUVMPd+OSsw==} + dependencies: '@layerzerolabs/evm-sdks-core': 3.0.75 ethers: 5.7.2 transitivePeerDependencies: - bufferutil - utf-8-validate + dev: true /@layerzerolabs/lz-evm-sdk-v2@3.0.75: resolution: {integrity: sha512-GoSMjRCtrwoQrwANc8Bpe/rpdoYIPU0zJWLCrFrh9/70wkIhprH1A7/t3I8lHg2dMcHCxtYjo5eJsFzbu1+OVw==} @@ -10035,7 +10622,6 @@ packages: '@openzeppelin/contracts': 5.0.2 '@openzeppelin/contracts-upgradeable': 5.0.2(@openzeppelin/contracts@5.0.2) hardhat-deploy: 0.12.4 - dev: true /@layerzerolabs/lz-evm-v1-0.7@3.0.75(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4): resolution: {integrity: sha512-6+ZbDYp9Ss2f14qwC8Wm/RNukBFjSw9lNpe96ai2iRyjlKCkd0pXo5/aonXneya7nQL3Gl5hGtOhVyuqHm405Q==} @@ -10414,7 +11000,7 @@ packages: - typescript - utf-8-validate - /@layerzerolabs/lz-solana-sdk-v2@3.0.0(typescript@5.5.3): + /@layerzerolabs/lz-solana-sdk-v2@3.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3): resolution: {integrity: sha512-sPvLXeQUO9QLpjOuWE7V+V8yfoI4E/NBYsH9lO2aPx0LYkQa+88ACgPq43B/zFROUD8238WuSb+doGrn3PKtJQ==} dependencies: '@ethersproject/abi': 5.7.0 @@ -10445,7 +11031,7 @@ packages: - utf-8-validate dev: true - /@layerzerolabs/lz-solana-sdk-v2@3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3): + /@layerzerolabs/lz-solana-sdk-v2@3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3): resolution: {integrity: sha512-zyuqBYxaVtSa+STdcbO/uzzQV2kyxmBX3flNbvOq7kS2QHBivuaYd/XDbNLE54/egQ63yMtFcilqwy3VzNpclw==} dependencies: '@layerzerolabs/lz-corekit-solana': 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) @@ -10553,7 +11139,7 @@ packages: - utf-8-validate dev: true - /@layerzerolabs/lz-solana-sdk-v2@3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3): + /@layerzerolabs/lz-solana-sdk-v2@3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3): resolution: {integrity: sha512-FfZLkFHIOPIFLkevQD0QSrfVR2UgREG6YF6oSR92XPViuVpAq0LAyCTXQi915bdiSdQ/Mwd+9eU/9ZPlk9f6sA==} dependencies: '@layerzerolabs/lz-corekit-solana': 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) @@ -10870,8 +11456,8 @@ packages: '@layerzerolabs/devtools-evm-hardhat': ~2.0.4 '@layerzerolabs/ua-devtools': ~3.0.2 dependencies: - '@layerzerolabs/devtools-evm-hardhat': 2.0.9(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@1.0.6)(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12) - '@layerzerolabs/ua-devtools': 3.0.6(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools@1.1.7)(zod@3.22.4) + '@layerzerolabs/devtools-evm-hardhat': 2.0.9(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12) + '@layerzerolabs/ua-devtools': 3.0.6(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4) dev: true /@layerzerolabs/move-definitions@3.0.59: @@ -10880,12 +11466,263 @@ packages: '@layerzerolabs/lz-definitions': 3.0.75 dev: true - /@layerzerolabs/oft-v2-solana-sdk@3.0.38(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3): + /@layerzerolabs/oapp-evm@0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5): + resolution: {integrity: sha512-P8uxe9A0T3G7WIQEw0dNCpUwUo4m3OFu5yQ3RsTrzX1BrSggTCUy8LgiNqxKVm56A3xMJVLsjzaB3zjXShXi8A==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.75(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.75(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5)(hardhat-deploy@0.12.4) + '@openzeppelin/contracts': 4.9.5 + '@openzeppelin/contracts-upgradeable': 4.9.5 + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@layerzerolabs/oapp-evm@0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2): + resolution: {integrity: sha512-P8uxe9A0T3G7WIQEw0dNCpUwUo4m3OFu5yQ3RsTrzX1BrSggTCUy8LgiNqxKVm56A3xMJVLsjzaB3zjXShXi8A==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.1)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.75(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.1)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.75(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.1) + '@openzeppelin/contracts': 5.0.2 + '@openzeppelin/contracts-upgradeable': 4.9.5 + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@layerzerolabs/oapp-evm@0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2): + resolution: {integrity: sha512-P8uxe9A0T3G7WIQEw0dNCpUwUo4m3OFu5yQ3RsTrzX1BrSggTCUy8LgiNqxKVm56A3xMJVLsjzaB3zjXShXi8A==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.75(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.75(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4) + '@openzeppelin/contracts': 5.0.2 + '@openzeppelin/contracts-upgradeable': 5.0.2(@openzeppelin/contracts@5.0.2) + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + /@layerzerolabs/oapp-evm@0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0): + resolution: {integrity: sha512-P8uxe9A0T3G7WIQEw0dNCpUwUo4m3OFu5yQ3RsTrzX1BrSggTCUy8LgiNqxKVm56A3xMJVLsjzaB3zjXShXi8A==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.75(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.75(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) + '@openzeppelin/contracts': 5.1.0 + '@openzeppelin/contracts-upgradeable': 5.1.0(@openzeppelin/contracts@5.1.0) + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@layerzerolabs/oapp-evm@0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2): + resolution: {integrity: sha512-P8uxe9A0T3G7WIQEw0dNCpUwUo4m3OFu5yQ3RsTrzX1BrSggTCUy8LgiNqxKVm56A3xMJVLsjzaB3zjXShXi8A==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.75(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4) + '@openzeppelin/contracts': 5.0.2 + '@openzeppelin/contracts-upgradeable': 4.9.5 + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@layerzerolabs/oapp-evm@0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2): + resolution: {integrity: sha512-P8uxe9A0T3G7WIQEw0dNCpUwUo4m3OFu5yQ3RsTrzX1BrSggTCUy8LgiNqxKVm56A3xMJVLsjzaB3zjXShXi8A==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.86(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.86(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4) + '@openzeppelin/contracts': 5.0.2 + '@openzeppelin/contracts-upgradeable': 5.0.2(@openzeppelin/contracts@5.0.2) + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@layerzerolabs/oapp-evm@0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0): + resolution: {integrity: sha512-P8uxe9A0T3G7WIQEw0dNCpUwUo4m3OFu5yQ3RsTrzX1BrSggTCUy8LgiNqxKVm56A3xMJVLsjzaB3zjXShXi8A==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.86(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) + '@openzeppelin/contracts': 5.1.0 + '@openzeppelin/contracts-upgradeable': 5.1.0(@openzeppelin/contracts@5.1.0) + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@layerzerolabs/oft-evm-upgradeable@3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2): + resolution: {integrity: sha512-s2X7qttIkDLcVCef2w/hDPgegPiCguuT1xcOrI0FpMg9mwl/FdoF8B+oj5r8cbqB8DSWleLt5Miu3IeOzXvayg==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@layerzerolabs/oapp-evm': ^0.3.2 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.75(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.75(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4) + '@layerzerolabs/oapp-evm': 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) + '@openzeppelin/contracts': 5.0.2 + '@openzeppelin/contracts-upgradeable': 5.0.2(@openzeppelin/contracts@5.0.2) + dev: true + + /@layerzerolabs/oft-evm@3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5): + resolution: {integrity: sha512-Fps4jL9Vg8eBu4A5bvRBYxUYNbycMIRvBqOaIkIbaZSdSx5uMt7C3t1U89cBKQkED1Zh6zyhh1TR2HyCHnvkFg==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@layerzerolabs/oapp-evm': ^0.3.2 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.75(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.75(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5)(hardhat-deploy@0.12.4) + '@layerzerolabs/oapp-evm': 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@4.9.5)(@openzeppelin/contracts@4.9.5) + '@openzeppelin/contracts': 4.9.5 + '@openzeppelin/contracts-upgradeable': 4.9.5 + dev: true + + /@layerzerolabs/oft-evm@3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2): + resolution: {integrity: sha512-Fps4jL9Vg8eBu4A5bvRBYxUYNbycMIRvBqOaIkIbaZSdSx5uMt7C3t1U89cBKQkED1Zh6zyhh1TR2HyCHnvkFg==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@layerzerolabs/oapp-evm': ^0.3.2 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.75(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.75(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4) + '@layerzerolabs/oapp-evm': 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) + '@openzeppelin/contracts': 5.0.2 + '@openzeppelin/contracts-upgradeable': 5.0.2(@openzeppelin/contracts@5.0.2) + + /@layerzerolabs/oft-evm@3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0): + resolution: {integrity: sha512-Fps4jL9Vg8eBu4A5bvRBYxUYNbycMIRvBqOaIkIbaZSdSx5uMt7C3t1U89cBKQkED1Zh6zyhh1TR2HyCHnvkFg==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@layerzerolabs/oapp-evm': ^0.3.2 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.75(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.75(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.75(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) + '@layerzerolabs/oapp-evm': 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.75)(@layerzerolabs/lz-evm-protocol-v2@3.0.75)(@layerzerolabs/lz-evm-v1-0.7@3.0.75)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) + '@openzeppelin/contracts': 5.1.0 + '@openzeppelin/contracts-upgradeable': 5.1.0(@openzeppelin/contracts@5.1.0) + dev: true + + /@layerzerolabs/oft-evm@3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2): + resolution: {integrity: sha512-Fps4jL9Vg8eBu4A5bvRBYxUYNbycMIRvBqOaIkIbaZSdSx5uMt7C3t1U89cBKQkED1Zh6zyhh1TR2HyCHnvkFg==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@layerzerolabs/oapp-evm': ^0.3.2 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.86(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.86(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2)(hardhat-deploy@0.12.4) + '@layerzerolabs/oapp-evm': 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.0.2)(@openzeppelin/contracts@5.0.2) + '@openzeppelin/contracts': 5.0.2 + '@openzeppelin/contracts-upgradeable': 5.0.2(@openzeppelin/contracts@5.0.2) + dev: true + + /@layerzerolabs/oft-evm@3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0): + resolution: {integrity: sha512-Fps4jL9Vg8eBu4A5bvRBYxUYNbycMIRvBqOaIkIbaZSdSx5uMt7C3t1U89cBKQkED1Zh6zyhh1TR2HyCHnvkFg==} + peerDependencies: + '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.75 + '@layerzerolabs/lz-evm-protocol-v2': ^3.0.75 + '@layerzerolabs/lz-evm-v1-0.7': ^3.0.75 + '@layerzerolabs/oapp-evm': ^0.3.2 + '@openzeppelin/contracts': ^4.8.1 || ^5.0.0 + '@openzeppelin/contracts-upgradeable': ^4.8.1 || ^5.0.0 + dependencies: + '@layerzerolabs/lz-evm-messagelib-v2': 3.0.86(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) + '@layerzerolabs/oapp-evm': 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) + '@openzeppelin/contracts': 5.1.0 + '@openzeppelin/contracts-upgradeable': 5.1.0(@openzeppelin/contracts@5.1.0) + dev: true + + /@layerzerolabs/oft-move@1.1.2: + resolution: {integrity: sha512-dlvRYHWJvvUz2VaaIAuMD00w9pfyYNGwqcv/YJHj+fdxCHM5T9d694N7OGhmEkk7HUxoeZoPEOu4Z9HVkslQ7Q==} + engines: {node: '>=18.16.0'} + dev: true + + /@layerzerolabs/oft-v2-solana-sdk@3.0.38(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3): resolution: {integrity: sha512-P06/a5+ixph0u1AQkDZ0P0oFaIAdfGPl/UezMfWXUpiWLth428RT0rrMR6qI7z6X1uxqlUFNIotz2ET1fyFcpQ==} dependencies: '@ethersproject/bytes': 5.7.0 '@layerzerolabs/lz-foundation': 3.0.38(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) - '@layerzerolabs/lz-solana-sdk-v2': 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + '@layerzerolabs/lz-solana-sdk-v2': 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/lz-v2-utilities': 3.0.86 '@metaplex-foundation/beet': 0.7.2 '@metaplex-foundation/beet-solana': 0.4.1 @@ -10911,12 +11748,12 @@ packages: - utf-8-validate dev: true - /@layerzerolabs/oft-v2-solana-sdk@3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3): + /@layerzerolabs/oft-v2-solana-sdk@3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3): resolution: {integrity: sha512-ijbvj6/Gc4O4WLHfqnrBuKUtIhpaYws/ORj2apZFT1RKSgAX8CCJ9aZmn0ClamEG98i+PpXoroPPU46LMOMZyA==} dependencies: '@ethersproject/bytes': 5.7.0 '@layerzerolabs/lz-foundation': 3.0.66(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) - '@layerzerolabs/lz-solana-sdk-v2': 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(typescript@5.5.3) + '@layerzerolabs/lz-solana-sdk-v2': 3.0.86(@swc/core@1.4.0)(@types/node@18.18.14)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.3) '@layerzerolabs/lz-v2-utilities': 3.0.86 '@metaplex-foundation/beet': 0.7.2 '@metaplex-foundation/beet-solana': 0.4.1 @@ -11004,24 +11841,123 @@ packages: - utf-8-validate dev: true + /@layerzerolabs/onesig-core@0.1.0: + resolution: {integrity: sha512-2D4agVrwTxZmWzp8xwOxwQHS28U/IJyvSHadfozHuilSDu2A9KQDFCI5CCppnXYXe7YeTEeUvdeNm4dAVPCiWQ==} + engines: {node: '>=20.10.0'} + dependencies: + '@ethersproject/abstract-signer': 5.7.0 + ethers: 5.7.2 + merkletreejs: 0.3.11 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@layerzerolabs/onesig-evm@0.0.12: + resolution: {integrity: sha512-s2N93IUUr6y16LTy7TZXC93RyeSUacexd5QpEDfXjKDgmDN/JWb9dyZjTzh0JcCk2emAyw5jmiuYhPwRJ+/NrA==} + engines: {node: '>=20.10.0'} + dependencies: + '@layerzerolabs/onesig-core': 0.1.0 + ethers: 5.7.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + /@layerzerolabs/prettier-config-next@2.3.44: resolution: {integrity: sha512-mIsxKLaelXHXXXvMEAE6Jc8IVydra0PesHquHYwvxFKwDhMhzfrnoRLLzbgCX/Zi1q0GGET/oMAKJTs6OWFPxQ==} dependencies: - prettier: 3.2.5 - prettier-plugin-packagejson: 2.5.0(prettier@3.2.5) - prettier-plugin-solidity: 1.3.1(prettier@3.2.5) + prettier: 3.2.5 + prettier-plugin-packagejson: 2.5.0(prettier@3.2.5) + prettier-plugin-solidity: 1.3.1(prettier@3.2.5) + dev: true + + /@layerzerolabs/protocol-devtools-evm@5.0.1(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/protocol-devtools@packages+protocol-devtools)(zod@3.22.4): + resolution: {integrity: sha512-g2RwxOWJITuEKU/j04UscEc57OcU03+vEsS7i3jyz+AKKq2vjXFMf6s9rbeQmu548/8LppnHg/t5QH5R33TPkQ==} + peerDependencies: + '@ethersproject/abstract-provider': ^5.7.0 + '@ethersproject/abstract-signer': ^5.7.0 + '@ethersproject/bignumber': ^5.7.0 + '@ethersproject/constants': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/providers': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/devtools-evm': ~3.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@layerzerolabs/protocol-devtools': ~3.0.1 + zod: ^3.22.4 + dependencies: + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/devtools': 1.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.2.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + '@layerzerolabs/protocol-devtools': link:packages/protocol-devtools + p-memoize: 4.0.4 + zod: 3.22.4 + dev: true + + /@layerzerolabs/protocol-devtools-evm@5.0.1(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4): + resolution: {integrity: sha512-g2RwxOWJITuEKU/j04UscEc57OcU03+vEsS7i3jyz+AKKq2vjXFMf6s9rbeQmu548/8LppnHg/t5QH5R33TPkQ==} + peerDependencies: + '@ethersproject/abstract-provider': ^5.7.0 + '@ethersproject/abstract-signer': ^5.7.0 + '@ethersproject/bignumber': ^5.7.0 + '@ethersproject/constants': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/providers': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/devtools-evm': ~3.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@layerzerolabs/protocol-devtools': ~3.0.1 + zod: ^3.22.4 + dependencies: + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/providers': 5.7.2 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + p-memoize: 4.0.4 + zod: 3.22.4 + dev: true + + /@layerzerolabs/protocol-devtools@3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4): + resolution: {integrity: sha512-5LndY2OD0PdodEv5IuhSP3RzbThxmE2B8twcrMGuPixrD1PjiIYqLvm2wznUMV/2NLiQrDdY1bOpd+5q9weibw==} + peerDependencies: + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + zod: ^3.22.4 + dependencies: + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + zod: 3.22.4 dev: true - /@layerzerolabs/protocol-devtools@1.1.7(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4): - resolution: {integrity: sha512-hY1VqFhBmGHDDCcsc6y0gYWlPd7pMMHp2EmZ01lzFdTnbYkF6rwC23EhSnb+AlMBxGpBwyFaNYRGTOZQx78ytA==} + /@layerzerolabs/protocol-devtools@3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4): + resolution: {integrity: sha512-5LndY2OD0PdodEv5IuhSP3RzbThxmE2B8twcrMGuPixrD1PjiIYqLvm2wznUMV/2NLiQrDdY1bOpd+5q9weibw==} peerDependencies: - '@layerzerolabs/devtools': ~0.4.8 - '@layerzerolabs/io-devtools': ~0.1.16 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 '@layerzerolabs/lz-definitions': ^3.0.75 zod: ^3.22.4 dependencies: - '@layerzerolabs/devtools': 0.4.10(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) - '@layerzerolabs/io-devtools': 0.1.17(zod@3.22.4) + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': 3.0.86 zod: 3.22.4 dev: true @@ -11065,7 +12001,7 @@ packages: - utf-8-validate dev: false - /@layerzerolabs/test-devtools-evm-foundry@5.1.0(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@packages+oapp-evm)(@layerzerolabs/oft-evm@packages+oft-evm)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0): + /@layerzerolabs/test-devtools-evm-foundry@5.1.0(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@0.3.3)(@layerzerolabs/oft-evm@3.2.1)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0): resolution: {integrity: sha512-LDfBMeb5VQRMRXadpNgUe5Knib5FdCQ24S2o+kWMS/qPS6ZbPGe7fnhFPhcifautuhMS8i9Rk7cMjoAxRGFdfQ==} peerDependencies: '@layerzerolabs/lz-evm-messagelib-v2': ^3.0.12 @@ -11079,12 +12015,22 @@ packages: '@layerzerolabs/lz-evm-messagelib-v2': 3.0.86(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@eth-optimism/contracts@0.6.0)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) '@layerzerolabs/lz-evm-protocol-v2': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) - '@layerzerolabs/oapp-evm': link:packages/oapp-evm - '@layerzerolabs/oft-evm': link:packages/oft-evm + '@layerzerolabs/oapp-evm': 0.3.3(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) + '@layerzerolabs/oft-evm': 3.2.1(@layerzerolabs/lz-evm-messagelib-v2@3.0.86)(@layerzerolabs/lz-evm-protocol-v2@3.0.86)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@layerzerolabs/oapp-evm@0.3.3)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0) '@openzeppelin/contracts': 5.1.0 '@openzeppelin/contracts-upgradeable': 5.1.0(@openzeppelin/contracts@5.1.0) dev: true + /@layerzerolabs/test-devtools-evm-hardhat@0.5.2(hardhat@2.22.12)(solidity-bytes-utils@0.8.2): + resolution: {integrity: sha512-mBZRczjNJdMSsHUjl2EQCCXutS4Yo6s6K0Bc32kSl3MNKIHZZMOEf6Hkj1guVSx/m3l3VZBr+3s0xc9FiyoQgQ==} + peerDependencies: + hardhat: ^2.22.10 + solidity-bytes-utils: ^0.8.2 + dependencies: + hardhat: 2.22.12(ts-node@10.9.2)(typescript@5.5.3) + solidity-bytes-utils: 0.8.2 + dev: true + /@layerzerolabs/ton@15.2.0-rc.3(@jest/globals@29.7.0)(@layerzerolabs/ton@15.2.0-rc.3)(@ton/core@0.59.0)(@ton/crypto@3.3.0)(@types/node@18.18.14)(chai@4.5.0)(typescript@5.5.3): resolution: {integrity: sha512-Aq7htcWn31DxSYs8l0sJcQ76uAJRPy50lg6M2G+qNLSXpO01sPcUSb8oK/TmCKo+S+rDIFWUNKFjT0B/rll1YQ==} peerDependencies: @@ -11199,6 +12145,116 @@ packages: - typescript dev: true + /@layerzerolabs/toolbox-foundry@0.1.13: + resolution: {integrity: sha512-3rC+BVEPgcHLHPO4qn3KqYUG1vhDtr1m/gsaI1S635MK+19475U8HYATznAzHKwi09cf9uEv5C7fdtHXgIw8sQ==} + dev: true + + /@layerzerolabs/toolbox-hardhat@0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2): + resolution: {integrity: sha512-vw1bfm8q12ZpQ+k0dB58FFWtHuYmPKPxIb9M6nKkLikgpFWeL3/tLg4sXzr/rNTSGrxR7Ut5IY0FTUVx5lI3HQ==} + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.2 + ethers: ^5.7.2 + hardhat: ^2.22.10 + hardhat-deploy: ^0.12.1 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/devtools-evm-hardhat': 4.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + '@layerzerolabs/lz-evm-sdk-v1': 3.0.75 + '@layerzerolabs/lz-evm-sdk-v2': 3.0.75 + '@layerzerolabs/lz-v2-utilities': 3.0.86 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/protocol-devtools-evm': 5.0.1(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4) + '@layerzerolabs/test-devtools-evm-hardhat': 0.5.2(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/ua-devtools': 5.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/lz-v2-utilities@3.0.75)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4) + '@layerzerolabs/ua-devtools-evm': 7.0.0(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/lz-v2-utilities@3.0.75)(@layerzerolabs/protocol-devtools-evm@5.0.1)(@layerzerolabs/protocol-devtools@3.0.1)(@layerzerolabs/ua-devtools@5.0.1)(zod@3.22.4) + '@layerzerolabs/ua-devtools-evm-hardhat': 9.0.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@layerzerolabs/devtools-evm-hardhat@4.0.1)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/protocol-devtools-evm@5.0.1)(@layerzerolabs/protocol-devtools@3.0.1)(@layerzerolabs/ua-devtools-evm@7.0.0)(@layerzerolabs/ua-devtools@5.0.1)(ethers@5.7.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12) + '@nomicfoundation/hardhat-ethers': 3.0.5(ethers@5.7.2)(hardhat@2.22.12) + ethers: 5.7.2 + fp-ts: 2.16.2 + hardhat: 2.22.12(ts-node@10.9.2)(typescript@5.5.3) + hardhat-deploy: 0.12.1 + ink: 3.2.0(@types/react@17.0.75)(react@17.0.2) + ink-gradient: 2.0.0(ink@3.2.0)(react@17.0.2) + ink-table: 3.1.0(ink@3.2.0)(react@17.0.2) + react: 17.0.2 + yoga-layout-prebuilt: 1.10.0 + zod: 3.22.4 + transitivePeerDependencies: + - '@ethersproject/abstract-provider' + - '@ethersproject/abstract-signer' + - '@ethersproject/bignumber' + - '@ethersproject/constants' + - '@ethersproject/providers' + - '@nomiclabs/hardhat-ethers' + - '@types/react' + - bufferutil + - encoding + - solidity-bytes-utils + - supports-color + - utf-8-validate + dev: true + + /@layerzerolabs/toolbox-hardhat@0.6.12(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/providers@5.7.2)(@nomicfoundation/hardhat-ethers@3.0.5)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12)(solidity-bytes-utils@0.8.2): + resolution: {integrity: sha512-vw1bfm8q12ZpQ+k0dB58FFWtHuYmPKPxIb9M6nKkLikgpFWeL3/tLg4sXzr/rNTSGrxR7Ut5IY0FTUVx5lI3HQ==} + peerDependencies: + '@nomicfoundation/hardhat-ethers': ^3.0.2 + ethers: ^5.7.2 + hardhat: ^2.22.10 + hardhat-deploy: ^0.12.1 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/devtools-evm-hardhat': 4.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + '@layerzerolabs/lz-evm-sdk-v1': 3.0.75 + '@layerzerolabs/lz-evm-sdk-v2': 3.0.75 + '@layerzerolabs/lz-v2-utilities': 3.0.86 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/protocol-devtools-evm': 5.0.1(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/protocol-devtools@packages+protocol-devtools)(zod@3.22.4) + '@layerzerolabs/test-devtools-evm-hardhat': 0.5.2(hardhat@2.22.12)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/ua-devtools': 5.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4) + '@layerzerolabs/ua-devtools-evm': 7.0.0(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools-evm@5.0.1)(@layerzerolabs/protocol-devtools@3.0.1)(@layerzerolabs/ua-devtools@5.0.1)(zod@3.22.4) + '@layerzerolabs/ua-devtools-evm-hardhat': 9.0.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@layerzerolabs/devtools-evm-hardhat@4.0.1)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/protocol-devtools-evm@5.0.1)(@layerzerolabs/protocol-devtools@3.0.1)(@layerzerolabs/ua-devtools-evm@7.0.0)(@layerzerolabs/ua-devtools@5.0.1)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12) + '@nomicfoundation/hardhat-ethers': 3.0.5(ethers@5.7.2)(hardhat@2.22.12) + ethers: 5.7.2 + fp-ts: 2.16.2 + hardhat: 2.22.12(ts-node@10.9.2)(typescript@5.5.3) + hardhat-deploy: 0.12.4 + ink: 3.2.0(@types/react@17.0.75)(react@17.0.2) + ink-gradient: 2.0.0(ink@3.2.0)(react@17.0.2) + ink-table: 3.1.0(ink@3.2.0)(react@17.0.2) + react: 17.0.2 + yoga-layout-prebuilt: 1.10.0 + zod: 3.22.4 + transitivePeerDependencies: + - '@ethersproject/abstract-provider' + - '@ethersproject/abstract-signer' + - '@ethersproject/bignumber' + - '@ethersproject/constants' + - '@ethersproject/providers' + - '@nomiclabs/hardhat-ethers' + - '@types/react' + - bufferutil + - encoding + - solidity-bytes-utils + - supports-color + - utf-8-validate + dev: true + /@layerzerolabs/tron-utilities@3.0.81(@types/node@18.18.14)(chai@4.5.0)(typescript@5.5.3): resolution: {integrity: sha512-bWv3GJJ6J/Wu79zlYEe6Cqv7UwzxC8tkA4rcHv6REnrbR/7iEaLcqLrVA/G1KWhOiUj5Rjqdws0bFpjJHdxXxQ==} dependencies: @@ -11282,7 +12338,145 @@ packages: - typescript - utf-8-validate - /@layerzerolabs/ua-devtools@3.0.6(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools@1.1.7)(zod@3.22.4): + /@layerzerolabs/ua-devtools-evm-hardhat@9.0.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@layerzerolabs/devtools-evm-hardhat@4.0.1)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/protocol-devtools-evm@5.0.1)(@layerzerolabs/protocol-devtools@3.0.1)(@layerzerolabs/ua-devtools-evm@7.0.0)(@layerzerolabs/ua-devtools@5.0.1)(ethers@5.7.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12): + resolution: {integrity: sha512-Wm/88JToOgFAJO0nKnpGMxQDD8mN37VFhz/ejE0DWbXsukp7IdX4ld4gQKM0MU7Yiajardhlvpa3Mwg+xHi8KQ==} + peerDependencies: + '@ethersproject/abi': ^5.7.0 + '@ethersproject/bytes': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/hash': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/devtools-evm': ~3.0.0 + '@layerzerolabs/devtools-evm-hardhat': ~4.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@layerzerolabs/protocol-devtools': ~3.0.0 + '@layerzerolabs/protocol-devtools-evm': ~5.0.0 + '@layerzerolabs/ua-devtools': ~5.0.0 + '@layerzerolabs/ua-devtools-evm': ~7.0.0 + ethers: ^5.7.2 + hardhat: ^2.22.10 + hardhat-deploy: ^0.12.1 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/devtools-evm-hardhat': 4.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.1)(hardhat@2.22.12) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/protocol-devtools-evm': 5.0.1(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4) + '@layerzerolabs/ua-devtools': 5.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/lz-v2-utilities@3.0.75)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4) + '@layerzerolabs/ua-devtools-evm': 7.0.0(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/lz-v2-utilities@3.0.75)(@layerzerolabs/protocol-devtools-evm@5.0.1)(@layerzerolabs/protocol-devtools@3.0.1)(@layerzerolabs/ua-devtools@5.0.1)(zod@3.22.4) + ethers: 5.7.2 + hardhat: 2.22.12(ts-node@10.9.2)(typescript@5.5.3) + hardhat-deploy: 0.12.1 + p-memoize: 4.0.4 + typescript: 5.5.3 + dev: true + + /@layerzerolabs/ua-devtools-evm-hardhat@9.0.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/hash@5.7.0)(@layerzerolabs/devtools-evm-hardhat@4.0.1)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/protocol-devtools-evm@5.0.1)(@layerzerolabs/protocol-devtools@3.0.1)(@layerzerolabs/ua-devtools-evm@7.0.0)(@layerzerolabs/ua-devtools@5.0.1)(ethers@5.7.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12): + resolution: {integrity: sha512-Wm/88JToOgFAJO0nKnpGMxQDD8mN37VFhz/ejE0DWbXsukp7IdX4ld4gQKM0MU7Yiajardhlvpa3Mwg+xHi8KQ==} + peerDependencies: + '@ethersproject/abi': ^5.7.0 + '@ethersproject/bytes': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@ethersproject/hash': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/devtools-evm': ~3.0.0 + '@layerzerolabs/devtools-evm-hardhat': ~4.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@layerzerolabs/protocol-devtools': ~3.0.0 + '@layerzerolabs/protocol-devtools-evm': ~5.0.0 + '@layerzerolabs/ua-devtools': ~5.0.0 + '@layerzerolabs/ua-devtools-evm': ~7.0.0 + ethers: ^5.7.2 + hardhat: ^2.22.10 + hardhat-deploy: ^0.12.1 + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/devtools-evm-hardhat': 4.0.1(@ethersproject/abi@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@nomiclabs/hardhat-ethers@2.2.3)(ethers@5.7.2)(fp-ts@2.16.2)(hardhat-deploy@0.12.4)(hardhat@2.22.12) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/protocol-devtools-evm': 5.0.1(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/protocol-devtools@packages+protocol-devtools)(zod@3.22.4) + '@layerzerolabs/ua-devtools': 5.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4) + '@layerzerolabs/ua-devtools-evm': 7.0.0(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools-evm@5.0.1)(@layerzerolabs/protocol-devtools@3.0.1)(@layerzerolabs/ua-devtools@5.0.1)(zod@3.22.4) + ethers: 5.7.2 + hardhat: 2.22.12(ts-node@10.9.2)(typescript@5.5.3) + hardhat-deploy: 0.12.4 + p-memoize: 4.0.4 + typescript: 5.5.3 + dev: true + + /@layerzerolabs/ua-devtools-evm@7.0.0(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/lz-v2-utilities@3.0.75)(@layerzerolabs/protocol-devtools-evm@5.0.1)(@layerzerolabs/protocol-devtools@3.0.1)(@layerzerolabs/ua-devtools@5.0.1)(zod@3.22.4): + resolution: {integrity: sha512-FPm6ESqm2SBOJjCbRnkWCMg6o5zlkoeLUavD8v1hlZeiY4i33wIHccQPtxMz8Yz/ZD8leQ8TiKJJJ9sdVGk7tQ==} + peerDependencies: + '@ethersproject/constants': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/devtools-evm': ~3.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@layerzerolabs/lz-v2-utilities': ^3.0.75 + '@layerzerolabs/protocol-devtools': ~3.0.0 + '@layerzerolabs/protocol-devtools-evm': ~5.0.0 + '@layerzerolabs/ua-devtools': ~5.0.0 + zod: ^3.22.4 + dependencies: + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + '@layerzerolabs/lz-v2-utilities': 3.0.75 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/protocol-devtools-evm': 5.0.1(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4) + '@layerzerolabs/ua-devtools': 5.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/lz-v2-utilities@3.0.75)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4) + p-memoize: 4.0.4 + zod: 3.22.4 + dev: true + + /@layerzerolabs/ua-devtools-evm@7.0.0(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools-evm@5.0.1)(@layerzerolabs/protocol-devtools@3.0.1)(@layerzerolabs/ua-devtools@5.0.1)(zod@3.22.4): + resolution: {integrity: sha512-FPm6ESqm2SBOJjCbRnkWCMg6o5zlkoeLUavD8v1hlZeiY4i33wIHccQPtxMz8Yz/ZD8leQ8TiKJJJ9sdVGk7tQ==} + peerDependencies: + '@ethersproject/constants': ^5.7.0 + '@ethersproject/contracts': ^5.7.0 + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/devtools-evm': ~3.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@layerzerolabs/lz-v2-utilities': ^3.0.75 + '@layerzerolabs/protocol-devtools': ~3.0.0 + '@layerzerolabs/protocol-devtools-evm': ~5.0.0 + '@layerzerolabs/ua-devtools': ~5.0.0 + zod: ^3.22.4 + dependencies: + '@ethersproject/constants': 5.7.0 + '@ethersproject/contracts': 5.7.0 + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/devtools-evm': 3.0.0(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/address@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(fp-ts@2.16.2)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + '@layerzerolabs/lz-v2-utilities': 3.0.86 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/protocol-devtools-evm': 5.0.1(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@ethersproject/bignumber@5.7.0)(@ethersproject/constants@5.7.0)(@ethersproject/contracts@5.7.0)(@ethersproject/providers@5.7.2)(@layerzerolabs/devtools-evm@3.0.0)(@layerzerolabs/devtools@1.0.1)(@layerzerolabs/io-devtools@0.2.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/protocol-devtools@packages+protocol-devtools)(zod@3.22.4) + '@layerzerolabs/ua-devtools': 5.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4) + p-memoize: 4.0.4 + zod: 3.22.4 + dev: true + + /@layerzerolabs/ua-devtools@3.0.6(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4): resolution: {integrity: sha512-hZbhNB7iIrKrrkOvDMF74niBCBj5icHmmlYbCSV3S6BKeLuKnX5i6zvlMTq/v5kgU0CZ0kNS37PFHfhSkW+oMw==} peerDependencies: '@layerzerolabs/devtools': ~0.4.8 @@ -11292,11 +12486,47 @@ packages: '@layerzerolabs/protocol-devtools': ~1.1.6 zod: ^3.22.4 dependencies: - '@layerzerolabs/devtools': 0.4.10(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) - '@layerzerolabs/io-devtools': 0.1.17(zod@3.22.4) + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.86 + '@layerzerolabs/lz-v2-utilities': 3.0.86 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + zod: 3.22.4 + dev: true + + /@layerzerolabs/ua-devtools@5.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(@layerzerolabs/lz-v2-utilities@3.0.75)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4): + resolution: {integrity: sha512-acoxyJAYqF+di2/akGuWLa5Gdt7Z/8LLZD0LqOui34yjPuHYH88L4xxmKxqrs4Ga/uQnRKcF6Cauy9pjlQCj1A==} + peerDependencies: + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@layerzerolabs/lz-v2-utilities': ^3.0.75 + '@layerzerolabs/protocol-devtools': ~3.0.1 + zod: ^3.22.4 + dependencies: + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) + '@layerzerolabs/lz-definitions': 3.0.75 + '@layerzerolabs/lz-v2-utilities': 3.0.75 + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.75)(zod@3.22.4) + zod: 3.22.4 + dev: true + + /@layerzerolabs/ua-devtools@5.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(@layerzerolabs/lz-v2-utilities@3.0.86)(@layerzerolabs/protocol-devtools@3.0.1)(zod@3.22.4): + resolution: {integrity: sha512-acoxyJAYqF+di2/akGuWLa5Gdt7Z/8LLZD0LqOui34yjPuHYH88L4xxmKxqrs4Ga/uQnRKcF6Cauy9pjlQCj1A==} + peerDependencies: + '@layerzerolabs/devtools': ~2.0.0 + '@layerzerolabs/io-devtools': ~0.3.0 + '@layerzerolabs/lz-definitions': ^3.0.75 + '@layerzerolabs/lz-v2-utilities': ^3.0.75 + '@layerzerolabs/protocol-devtools': ~3.0.1 + zod: ^3.22.4 + dependencies: + '@layerzerolabs/devtools': 2.0.1(@ethersproject/bytes@5.7.0)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/io-devtools': 0.3.1(ink-gradient@2.0.0)(ink-table@3.1.0)(ink@3.2.0)(react@17.0.2)(yoga-layout-prebuilt@1.10.0)(zod@3.22.4) '@layerzerolabs/lz-definitions': 3.0.86 '@layerzerolabs/lz-v2-utilities': 3.0.86 - '@layerzerolabs/protocol-devtools': 1.1.7(@layerzerolabs/devtools@0.4.10)(@layerzerolabs/io-devtools@0.1.17)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) + '@layerzerolabs/protocol-devtools': 3.0.1(@layerzerolabs/devtools@2.0.1)(@layerzerolabs/io-devtools@0.3.1)(@layerzerolabs/lz-definitions@3.0.86)(zod@3.22.4) zod: 3.22.4 dev: true @@ -12119,7 +13349,6 @@ packages: '@openzeppelin/contracts': 5.0.2 dependencies: '@openzeppelin/contracts': 5.0.2 - dev: true /@openzeppelin/contracts-upgradeable@5.1.0(@openzeppelin/contracts@5.1.0): resolution: {integrity: sha512-AIElwP5Ck+cslNE+Hkemf5SxjJoF4wBvvjxc27Rp+9jaPs/CLIaUBMYe1FNzhdiN0cYuwGRmYaRHmmntuiju4Q==} @@ -12142,7 +13371,6 @@ packages: /@openzeppelin/contracts@5.0.2: resolution: {integrity: sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==} - dev: true /@openzeppelin/contracts@5.1.0: resolution: {integrity: sha512-p1ULhl7BXzjjbha5aqst+QMLY+4/LCWADXOCsmLHRM77AqiPjnd9vvUN9sosUfhL9JGKpZ0TjEGxgvnizmWGSA==} @@ -13319,6 +14547,53 @@ packages: - utf-8-validate dev: true + /@stargatefinance/stg-definitions-v2@5.0.2: + resolution: {integrity: sha512-FWK2JQdeoXOeH+hAZ3d+jDcVOcjHy+nXPXThHUrPE4BbE+xlx2W63bqaSm7LvnhJKSGucfb2iVaj4HWyswFPUg==} + dev: true + + /@stargatefinance/stg-evm-v1@1.0.33: + resolution: {integrity: sha512-funR7QssJn+9m8tAO+2nMB2+9ke1FplY5/Jt1RGReFR4ZXhlMKWvbos4KNh7L6k6tu2c+9oQOjn8bPiGnGwmew==} + dependencies: + exponential-backoff: 3.1.1 + dev: true + + /@stargatefinance/stg-evm-v2@5.0.3(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(@types/node@18.18.14)(chai@4.5.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2)(typescript@5.5.3): + resolution: {integrity: sha512-5kHuAPniRH25GC74R/JjLyQtOBfDJtIXXtqyt2pONwq9QOgmooxpLZ9WKbDc0lRmm1P4Sm5s1d+FR7XAt7noJQ==} + dependencies: + '@layerzerolabs/lz-definitions': 3.0.86 + '@layerzerolabs/lz-evm-messagelib-v2': 2.0.11(@axelar-network/axelar-gmp-sdk-solidity@5.10.0)(@chainlink/contracts-ccip@0.7.6)(@layerzerolabs/lz-evm-protocol-v2@2.0.11)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-oapp-v2': 2.3.44(@layerzerolabs/lz-evm-messagelib-v2@2.0.11)(@layerzerolabs/lz-evm-protocol-v2@2.0.11)(@layerzerolabs/lz-evm-v1-0.7@3.0.86)(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-protocol-v2': 2.0.11(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4)(solidity-bytes-utils@0.8.2) + '@layerzerolabs/lz-evm-sdk-v2': 3.0.30 + '@layerzerolabs/lz-evm-v1-0.7': 3.0.86(@openzeppelin/contracts-upgradeable@5.1.0)(@openzeppelin/contracts@5.1.0)(hardhat-deploy@0.12.4) + '@layerzerolabs/lz-utilities': 3.0.86(@types/node@18.18.14)(chai@4.5.0)(typescript@5.5.3) + '@layerzerolabs/lz-v2-utilities': 3.0.86 + '@layerzerolabs/onesig-core': 0.1.0 + '@layerzerolabs/onesig-evm': 0.0.12 + '@stargatefinance/stg-definitions-v2': 5.0.2 + '@stargatefinance/stg-evm-v1': 1.0.33 + '@types/sinon': 17.0.3 + ethers: 5.7.2 + transitivePeerDependencies: + - '@axelar-network/axelar-gmp-sdk-solidity' + - '@chainlink/contracts-ccip' + - '@jest/globals' + - '@openzeppelin/contracts' + - '@openzeppelin/contracts-upgradeable' + - '@swc/core' + - '@swc/wasm' + - '@types/node' + - bufferutil + - chai + - debug + - encoding + - hardhat-deploy + - solidity-bytes-utils + - supports-color + - typescript + - utf-8-validate + dev: true + /@swc/core-darwin-arm64@1.4.0: resolution: {integrity: sha512-UTJ/Vz+s7Pagef6HmufWt6Rs0aUu+EJF4Pzuwvr7JQQ5b1DZeAAUeUtkUTFx/PvCbM8Xfw4XdKBUZfrIKCfW8A==} engines: {node: '>=10'} @@ -15253,6 +16528,10 @@ packages: resolution: {integrity: sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==} engines: {node: '>=4.5'} + /buffer-reverse@1.0.1: + resolution: {integrity: sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==} + dev: true + /buffer-to-arraybuffer@0.0.5: resolution: {integrity: sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ==} @@ -16102,6 +17381,10 @@ packages: resolution: {integrity: sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg==} engines: {node: '>=8'} + /crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + dev: true + /csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -19863,6 +21146,34 @@ packages: - babel-plugin-macros - supports-color + /jest-cli@29.7.0(@types/node@18.18.14): + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@18.18.14)(ts-node@10.9.2) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + /jest-cli@29.7.0(@types/node@18.18.14)(ts-node@10.9.2): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -20275,6 +21586,27 @@ packages: merge-stream: 2.0.0 supports-color: 8.1.1 + /jest@29.7.0(@types/node@18.18.14): + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(@types/node@18.18.14) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + /jest@29.7.0(@types/node@18.18.14)(ts-node@10.9.2): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -20970,6 +22302,17 @@ packages: semaphore-async-await: 1.5.1 dev: true + /merkletreejs@0.3.11: + resolution: {integrity: sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==} + engines: {node: '>= 7.6.0'} + dependencies: + bignumber.js: 9.1.2 + buffer-reverse: 1.0.1 + crypto-js: 4.2.0 + treeify: 1.1.0 + web3-utils: 1.10.4 + dev: true + /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} @@ -24005,6 +25348,11 @@ packages: hasBin: true dev: true + /treeify@1.1.0: + resolution: {integrity: sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==} + engines: {node: '>=0.6'} + dev: true + /triple-beam@1.4.1: resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} engines: {node: '>= 14.0.0'} From 8ddeba5714655c912cc8850b67b34f66f0c6e948 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Thu, 13 Nov 2025 15:44:48 -0800 Subject: [PATCH 34/47] chore: clean comments --- examples/oft-composers/scripts/supplyAave.s.sol | 8 +------- examples/oft-composers/tasks/supplyAave.ts | 4 ---- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/examples/oft-composers/scripts/supplyAave.s.sol b/examples/oft-composers/scripts/supplyAave.s.sol index 0927ca662..650e631ec 100644 --- a/examples/oft-composers/scripts/supplyAave.s.sol +++ b/examples/oft-composers/scripts/supplyAave.s.sol @@ -84,10 +84,4 @@ contract SupplyAaveScript is Script { erc20.approve(spender, type(uint256).max); } } -} - -/* - forge script scripts/supplyAave.s.sol:SupplyAaveScript \ - --rpc-url https://arbitrum.gateway.tenderly.co \ - --broadcast -vv --via-ir -*/ +} \ No newline at end of file diff --git a/examples/oft-composers/tasks/supplyAave.ts b/examples/oft-composers/tasks/supplyAave.ts index 660c177e0..0f08d3760 100644 --- a/examples/oft-composers/tasks/supplyAave.ts +++ b/examples/oft-composers/tasks/supplyAave.ts @@ -164,7 +164,3 @@ task('stargate:supply-aave', 'Sends tokens through Stargate and composes into Aa .addOptionalParam('refundAddress', 'Address receiving any leftover native fee') .addOptionalParam('payInLzToken', 'Set to true to pay LayerZero fees with the LZ token (default false)', 'false') .setAction(async (args: SendArgs, hre) => sendSupply(hre, args)) - -/* -pnpm hardhat stargate:supply-aave --network arbitrum-mainnet --stargate 0xe8cdf27acd73a434d661c84887215f7598e7d0d3 --dst-eid 30184 --composer 0xb38c4fc4b7c7672EfdA6f8b3a386e615049eed30 --amount-ld 1000000 -*/ From 03ddcb9028cf60a3b12d3f6226381422b9a0c0cb Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Sun, 16 Nov 2025 22:38:09 -0500 Subject: [PATCH 35/47] chore: add deploy vars --- examples/oft-composers/.env.example | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/oft-composers/.env.example b/examples/oft-composers/.env.example index 197ba1d67..bb044889c 100644 --- a/examples/oft-composers/.env.example +++ b/examples/oft-composers/.env.example @@ -12,4 +12,8 @@ # # You don't need to set both of these values, just pick the one that you prefer and set that one MNEMONIC= -PRIVATE_KEY= \ No newline at end of file +PRIVATE_KEY= + +# Composer deployment variables +AAVE_V3_POOL_ADDRESS= +STARGATE_POOL_ADDRESS= \ No newline at end of file From 447f3522a7e95b0dd1925b59fa969bee91a5da21 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Sun, 16 Nov 2025 22:38:43 -0500 Subject: [PATCH 36/47] feat: add refund on source --- .../AaveV3Composer/AaveV3Composer.sol | 71 +++++++++++++++---- .../AaveV3Composer/IAaveV3Composer.sol | 27 +++---- 2 files changed, 66 insertions(+), 32 deletions(-) diff --git a/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol b/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol index e34aac7ea..3c2fa1c73 100644 --- a/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol +++ b/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol @@ -7,6 +7,7 @@ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.s import { ILayerZeroComposer } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol"; import { OFTComposeMsgCodec } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol"; import { IOAppCore } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol"; +import { IOFT, SendParam, MessagingFee } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; import { IStargate } from "@stargatefinance/stg-evm-v2/src/interfaces/IStargate.sol"; import { IAaveV3Composer } from "./IAaveV3Composer.sol"; @@ -105,34 +106,76 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { * `abi.encode(address onBehalfOf)`. * * - * @param _oft Address of the originating OFT; must equal the trusted `stargate`. + * @param _sender Address of the stargate contract; must equal the trusted `stargate`. * @dev _guid Message hash (unused, but kept for future extensibility). * @param _message ABI-encoded compose payload containing recipient address. * @dev _executor Executor that relayed the message (unused). * @dev _extraData Extra data from executor (unused). */ function lzCompose( - address _oft, - bytes32 /* _guid */, + address _sender, + bytes32 _guid, bytes calldata _message, address /* _executor */, bytes calldata /* _extraData */ ) external payable { - // Step 1️: Authenticate call logic source. - if (_oft != STARGATE) revert UnauthorizedStargatePool(); - if (msg.sender != ENDPOINT) revert UnauthorizedEndpoint(); + // Authenticate call logic source. + if (_sender != STARGATE) revert OnlyValidComposerCaller(_sender); + if (msg.sender != ENDPOINT) revert OnlyEndpoint(msg.sender); - // Step 2️: Decode the recipient address and amount from the message. - address _to = abi.decode(OFTComposeMsgCodec.composeMsg(_message), (address)); + // Decode the amount in local decimals and the compose message from the message. uint256 amountLD = OFTComposeMsgCodec.amountLD(_message); - // Step 3: Execute the supply or refund to target recipient. - try AAVE.supply(TOKEN_IN, amountLD, _to, 0) { - // 0 is the referral code - emit SupplyExecuted(_to, amountLD); + // Try to decompose the message, refund if it fails. + try this.handleCompose{ value: msg.value }(_message, amountLD) { + emit Sent(_guid); } catch { - IERC20(TOKEN_IN).safeTransfer(_to, amountLD); - emit SupplyFailedAndRefunded(_to, amountLD); + _refund(STARGATE, _message, amountLD, tx.origin, msg.value); + emit Refunded(_guid); } } + + /** + * @notice Handles the compose operation for OFT (Omnichain Fungible Token) transactions + * @dev This function can only be called by the contract itself (self-call restriction) + * Decodes the compose message to extract SendParam and minimum message value + * @param _message The original message that was sent + * @param _amountLD The amount of tokens to supply + */ + function handleCompose(bytes calldata _message, uint256 _amountLD) external payable { + if (msg.sender != address(this)) revert OnlySelf(msg.sender); + + address _to = abi.decode(OFTComposeMsgCodec.composeMsg(_message), (address)); + + // Try to execute the supply or refund to target recipient. + try AAVE.supply(TOKEN_IN, _amountLD, _to, 0) { + emit Supplied(_to, _amountLD); + } catch { + _refund(STARGATE, _message, _amountLD, tx.origin, msg.value); + emit SupplyFailedAndRefunded(_to, _amountLD); + } + } + + /** + * @dev Internal function to refund input tokens to sender on source during a failed transaction + * @param _stargate The OFT contract address used for refunding + * @param _message The original message that was sent + * @param _amount The amount of tokens to refund + * @param _refundAddress Address to receive the refund + * @param _msgValue The amount of native tokens sent with the transaction + */ + function _refund( + address _stargate, + bytes calldata _message, + uint256 _amount, + address _refundAddress, + uint256 _msgValue + ) internal virtual { + SendParam memory refundSendParam; + refundSendParam.dstEid = OFTComposeMsgCodec.srcEid(_message); + refundSendParam.to = OFTComposeMsgCodec.composeFrom(_message); + refundSendParam.amountLD = _amount; + + IOFT(_stargate).send{ value: _msgValue }(refundSendParam, MessagingFee(_msgValue, 0), _refundAddress); + } } diff --git a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol b/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol index 06d31bf55..9ede8fd18 100644 --- a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol +++ b/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol @@ -10,25 +10,16 @@ pragma solidity ^0.8.0; * contract definitions from implementation logic. */ interface IAaveV3Composer { - /// @notice Custom errors for more gas-efficient reverts. + /// ========================== Error Messages ===================================== error InvalidAavePool(); error InvalidStargatePool(); - error UnauthorizedStargatePool(); - error UnauthorizedEndpoint(); + error OnlyValidComposerCaller(address sender); + error OnlyEndpoint(address endpoint); + error OnlySelf(address caller); - /** - * @notice Emitted when a token supply is successfully executed. - * - * @param recipient The address of the recipient of the aTokens tokens. - * @param amountLD The amount of LD tokens being supplied. - */ - event SupplyExecuted(address indexed recipient, uint256 amountLD); - - /** - * @notice Emitted when a token supply fails and the OFT tokens are refunded to the recipient. - * - * @param recipient The address of the recipient of the aTokens tokens. - * @param amountLD The amount of LD tokens being refunded. - */ - event SupplyFailedAndRefunded(address indexed recipient, uint256 amountLD); + /// ========================== EVENTS ===================================== + event Sent(bytes32 guid); + event Refunded(bytes32 guid); + event Supplied(address indexed recipient, uint256 amountLd); + event SupplyFailedAndRefunded(address indexed recipient, uint256 amountLd); } From 3ed94f47d19d15f1652d8d6a958965cfcbe08a6e Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Sun, 16 Nov 2025 22:39:13 -0500 Subject: [PATCH 37/47] chore: update tests --- .../test/foundry/AaveV3Composer.t.sol | 108 ++++++++++++------ .../test/mocks/StargatePoolMock.sol | 39 +++++++ 2 files changed, 110 insertions(+), 37 deletions(-) diff --git a/examples/oft-composers/test/foundry/AaveV3Composer.t.sol b/examples/oft-composers/test/foundry/AaveV3Composer.t.sol index addc64612..1e922dac5 100644 --- a/examples/oft-composers/test/foundry/AaveV3Composer.t.sol +++ b/examples/oft-composers/test/foundry/AaveV3Composer.t.sol @@ -24,7 +24,7 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; * @title AaveV3ComposerTest * @notice Unit tests for the `AaveV3Composer` contract. */ -contract AaveV3ComposerTest is TestHelperOz5 { +contract AaveV3ComposerTest is TestHelperOz5, IAaveV3Composer { // ---------------------------- // ============ Setup =========== // ---------------------------- @@ -72,10 +72,10 @@ contract AaveV3ComposerTest is TestHelperOz5 { * @dev Asserts dependencies, endpoints, and allowances are configured as expected. */ function test_constructor() public view { - assertEq(address(composer.aave()), address(aave)); - assertEq(composer.endpoint(), address(endpoints[bEid])); - assertEq(composer.stargate(), address(stargate)); - assertEq(composer.tokenIn(), address(token)); + assertEq(address(composer.AAVE()), address(aave)); + assertEq(composer.ENDPOINT(), address(endpoints[bEid])); + assertEq(composer.STARGATE(), address(stargate)); + assertEq(composer.TOKEN_IN(), address(token)); assertEq(IERC20(address(token)).allowance(address(composer), address(aave)), type(uint256).max); } @@ -87,43 +87,71 @@ contract AaveV3ComposerTest is TestHelperOz5 { * @notice Tests that a successful `lzCompose` call supplies tokens to Aave. * @dev Confirms the mock pool receives the correct parameters and token balance updates. */ - function test_lzCompose_supply() public { - bytes memory composeMsg = abi.encode(receiver); - bytes memory fullMessage = OFTComposeMsgCodec.encode( - 1, - aEid, - amountLD, - abi.encodePacked(addressToBytes32(userA), composeMsg) - ); + function test_lzCompose_supply_emitsEventsAndSupplies() public { + bytes memory fullMessage = _buildMessageForReceiver(receiver); + + vm.expectEmit(true, false, false, true); + emit Supplied(receiver, amountLD); + vm.expectEmit(false, false, false, true); + emit Sent(bytes32(0)); + vm.prank(address(endpoints[bEid])); composer.lzCompose(address(stargate), bytes32(0), fullMessage, address(0), bytes("")); + assertEq(aave.lastAsset(), address(token)); assertEq(aave.lastAmount(), amountLD); assertEq(aave.lastOnBehalfOf(), receiver); assertEq(aave.tokenBalance(), amountLD); assertEq(token.balanceOf(address(composer)), initialBalance - amountLD); + assertEq(stargate.refundCallCount(), 0); } /** * @notice Tests the fallback path when the Aave pool reverts. * @dev Ensures the composer transfers tokens directly to the receiver on failure. */ - function test_lzCompose_fallback() public { + function test_lzCompose_supplyFailureRefundsAndEmits() public { aave.setShouldRevert(true); - uint256 composerBalanceBefore = token.balanceOf(address(composer)); - uint256 receiverBalanceBefore = token.balanceOf(receiver); - bytes memory composeMsg = abi.encode(receiver); + + bytes memory fullMessage = _buildMessageForReceiver(receiver); + address originUser = makeAddr("originUser"); + + vm.expectEmit(true, false, false, true); + emit SupplyFailedAndRefunded(receiver, amountLD); + vm.expectEmit(false, false, false, true); + emit Sent(bytes32(0)); + + vm.startPrank(address(endpoints[bEid]), originUser); + composer.lzCompose(address(stargate), bytes32(0), fullMessage, address(0), bytes("")); + vm.stopPrank(); + + assertEq(aave.tokenBalance(), 0); + assertEq(stargate.refundCallCount(), 1); + assertEq(stargate.lastRefundDstEid(), aEid); + assertEq(stargate.lastRefundTo(), addressToBytes32(userA)); + assertEq(stargate.lastRefundAmount(), amountLD); + assertEq(stargate.lastRefundAddress(), originUser); + } + + function test_lzCompose_handleComposeRevertEmitsRefunded() public { + bytes memory invalidComposeMsg = new bytes(0); bytes memory fullMessage = OFTComposeMsgCodec.encode( 1, aEid, amountLD, - abi.encodePacked(addressToBytes32(userA), composeMsg) + abi.encodePacked(addressToBytes32(userA), invalidComposeMsg) ); + + vm.expectEmit(false, false, false, true); + emit Refunded(bytes32(0)); + vm.prank(address(endpoints[bEid])); composer.lzCompose(address(stargate), bytes32(0), fullMessage, address(0), bytes("")); - assertEq(token.balanceOf(address(composer)), composerBalanceBefore - amountLD); - assertEq(token.balanceOf(receiver), receiverBalanceBefore + amountLD); - assertEq(aave.tokenBalance(), 0); + + assertEq(stargate.refundCallCount(), 1); + assertEq(stargate.lastRefundDstEid(), aEid); + assertEq(stargate.lastRefundTo(), addressToBytes32(userA)); + assertEq(stargate.lastRefundAmount(), amountLD); } /** @@ -131,16 +159,13 @@ contract AaveV3ComposerTest is TestHelperOz5 { * @dev Expects the `UnauthorizedStargatePool` error from `IAaveV3Composer`. */ function test_lzCompose_unauthorizedStargate() public { - bytes memory composeMsg = abi.encode(receiver); - bytes memory fullMessage = OFTComposeMsgCodec.encode( - 1, - aEid, - amountLD, - abi.encodePacked(addressToBytes32(userA), composeMsg) + bytes memory fullMessage = _buildMessageForReceiver(receiver); + vm.startPrank(address(endpoints[bEid])); + vm.expectRevert( + abi.encodeWithSelector(IAaveV3Composer.OnlyValidComposerCaller.selector, address(0x1234)) ); - vm.prank(address(endpoints[bEid])); - vm.expectRevert(IAaveV3Composer.UnauthorizedStargatePool.selector); composer.lzCompose(address(0x1234), bytes32(0), fullMessage, address(0), bytes("")); + vm.stopPrank(); } /** @@ -148,14 +173,23 @@ contract AaveV3ComposerTest is TestHelperOz5 { * @dev Expects the `UnauthorizedEndpoint` error from `IAaveV3Composer`. */ function test_lzCompose_unauthorizedEndpoint() public { - bytes memory composeMsg = abi.encode(receiver); - bytes memory fullMessage = OFTComposeMsgCodec.encode( - 1, - aEid, - amountLD, - abi.encodePacked(addressToBytes32(userA), composeMsg) - ); - vm.expectRevert(IAaveV3Composer.UnauthorizedEndpoint.selector); + bytes memory fullMessage = _buildMessageForReceiver(receiver); + vm.expectRevert(abi.encodeWithSelector(IAaveV3Composer.OnlyEndpoint.selector, address(this))); composer.lzCompose(address(stargate), bytes32(0), fullMessage, address(0), bytes("")); } + + // --------------------------------------------------------------------- + // Helpers + // --------------------------------------------------------------------- + + function _buildMessageForReceiver(address _receiver) internal view returns (bytes memory) { + bytes memory composeMsg = abi.encode(_receiver); + return + OFTComposeMsgCodec.encode( + 1, + aEid, + amountLD, + abi.encodePacked(addressToBytes32(userA), composeMsg) + ); + } } diff --git a/examples/oft-composers/test/mocks/StargatePoolMock.sol b/examples/oft-composers/test/mocks/StargatePoolMock.sol index fde395be8..e6f02da58 100644 --- a/examples/oft-composers/test/mocks/StargatePoolMock.sol +++ b/examples/oft-composers/test/mocks/StargatePoolMock.sol @@ -2,11 +2,32 @@ pragma solidity ^0.8.20; import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; +import { MessagingFee, MessagingReceipt, OFTReceipt, SendParam } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; +/** + * @dev Minimal mock that exposes the pieces of the Stargate/OFT contract the composer interacts with. + * It records every `send` invocation so tests can assert refund behaviour without needing a full OFT. + */ contract StargatePoolMock { ILayerZeroEndpointV2 private immutable _endpoint; address private immutable _token; + uint32 public lastRefundDstEid; + bytes32 public lastRefundTo; + uint256 public lastRefundAmount; + address public lastRefundAddress; + uint256 public lastRefundMsgValue; + uint256 public refundCallCount; + + event MockSend( + address indexed caller, + uint32 dstEid, + bytes32 to, + uint256 amountLD, + address refundAddress, + uint256 msgValue + ); + constructor(address endpoint_, address token_) { _endpoint = ILayerZeroEndpointV2(endpoint_); _token = token_; @@ -19,4 +40,22 @@ contract StargatePoolMock { function token() external view returns (address) { return _token; } + + function send( + SendParam calldata _sendParam, + MessagingFee calldata _fee, + address _refundAddress + ) external payable returns (MessagingReceipt memory receipt, OFTReceipt memory oftReceipt) { + lastRefundDstEid = _sendParam.dstEid; + lastRefundTo = _sendParam.to; + lastRefundAmount = _sendParam.amountLD; + lastRefundAddress = _refundAddress; + lastRefundMsgValue = msg.value; + refundCallCount++; + + emit MockSend(msg.sender, _sendParam.dstEid, _sendParam.to, _sendParam.amountLD, _refundAddress, msg.value); + + receipt = MessagingReceipt({ guid: bytes32(0), nonce: 0, fee: _fee }); + oftReceipt = OFTReceipt({ amountSentLD: _sendParam.amountLD, amountReceivedLD: _sendParam.amountLD }); + } } From ff80a12338f458e7ddb04b56001e57f2324c446a Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Sun, 16 Nov 2025 22:39:42 -0500 Subject: [PATCH 38/47] chore: minor updates --- examples/oft-composers/tasks/supplyAave.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/oft-composers/tasks/supplyAave.ts b/examples/oft-composers/tasks/supplyAave.ts index 0f08d3760..a04061123 100644 --- a/examples/oft-composers/tasks/supplyAave.ts +++ b/examples/oft-composers/tasks/supplyAave.ts @@ -51,7 +51,7 @@ async function sendSupply(hre: HardhatRuntimeEnvironment, args: SendArgs) { // 1. Build compose message payload expected by AaveV3Composer (address) const composeMsg = abiCoder.encode(['address'], [args.tokenReceiver ?? signer.address]) - const composeGasLimit = ethers.BigNumber.from(args.composeGasLimit ?? '200000').toString() + const composeGasLimit = ethers.BigNumber.from(args.composeGasLimit ?? '395000').toString() const extraOptions = Options.newOptions() .addExecutorComposeOption( @@ -149,12 +149,12 @@ async function sendSupply(hre: HardhatRuntimeEnvironment, args: SendArgs) { value: valueToSend, }) - logger.info(`Stargate transaction submitted: ${tx.hash}`) + logger.info(`Transaction submitted: ${tx.hash}`) await tx.wait() - logger.info(`Stargate transaction confirmed.`) + logger.info(`Transaction confirmed.`) } -task('stargate:supply-aave', 'Sends tokens through Stargate and composes into AaveV3Composer') +task('aave:supply', 'Sends tokens through Stargate and composes into AaveV3Composer') .addParam('stargate', 'Stargate pool address') .addParam('dstEid', 'Destination endpoint ID') .addParam('composer', 'Composer contract address on the destination chain') From b9496d8b2ccbbec78751b29b9eaf350d0b71ff24 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Sun, 16 Nov 2025 22:40:07 -0500 Subject: [PATCH 39/47] feat: add uni deployer --- .../oft-composers/deploy/UniswapV3Composer.ts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 examples/oft-composers/deploy/UniswapV3Composer.ts diff --git a/examples/oft-composers/deploy/UniswapV3Composer.ts b/examples/oft-composers/deploy/UniswapV3Composer.ts new file mode 100644 index 000000000..169048d10 --- /dev/null +++ b/examples/oft-composers/deploy/UniswapV3Composer.ts @@ -0,0 +1,41 @@ +import assert from 'assert' + +import { type DeployFunction } from 'hardhat-deploy/types' + +const contractName = 'UniswapV3Composer' + +const deploy: DeployFunction = async (hre) => { + const { deployments, getNamedAccounts, ethers, network } = hre + const { deploy } = deployments + + const { deployer } = await getNamedAccounts() + assert(deployer, 'Missing named deployer account') + + const swapRouter = process.env.SWAP_ROUTER_ADDRESS + assert(swapRouter, 'Missing SWAP_ROUTER_ADDRESS environment variable') + + const oft = process.env.OFT_ADDRESS + assert(oft, 'Missing OFT_ADDRESS environment variable') + + const { isAddress } = ethers.utils + assert(isAddress(swapRouter), `SWAP_ROUTER_ADDRESS (${swapRouter}) is not a valid address`) + assert(isAddress(oft), `OFT_ADDRESS (${oft}) is not a valid address`) + + console.log(`Network: ${network.name}`) + console.log(`Deployer: ${deployer}`) + console.log(`Swap router: ${swapRouter}`) + console.log(`OFT: ${oft}`) + + const { address } = await deploy(contractName, { + from: deployer, + args: [swapRouter, oft], + log: true, + skipIfAlreadyDeployed: false, + }) + + console.log(`Deployed contract: ${contractName}, network: ${network.name}, address: ${address}`) +} + +deploy.tags = [contractName] + +export default deploy From d6c0bfce39f69995462b930a29bbb21f0f73d755 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Mon, 17 Nov 2025 19:59:45 -0500 Subject: [PATCH 40/47] chore: add composer example --- packages/create-lz-oapp/src/config.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index d97d7e0c7..82081a5d9 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -214,6 +214,17 @@ export const getExamples = (): Example[] => { }, ] : []), + ...(process.env.LZ_ENABLE_OFT_COMPOSERS + ? [ + { + id: 'oft-composers', + label: 'OFT Composers', + repository, + directory: 'examples/oft-composers', + ref, + }, + ] + : []), ...(process.env.LZ_ENABLE_COMPOSER_EXAMPLE ? [ { From 2d01144b50be8ab8716f7a1e2b2e2f9c2ff10aa4 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Mon, 17 Nov 2025 20:00:29 -0500 Subject: [PATCH 41/47] chore: update readme --- examples/oft-composers/README.md | 291 ++++++++++++++++++++++--------- 1 file changed, 212 insertions(+), 79 deletions(-) diff --git a/examples/oft-composers/README.md b/examples/oft-composers/README.md index 4cf7de2c7..8ff5ab62c 100644 --- a/examples/oft-composers/README.md +++ b/examples/oft-composers/README.md @@ -18,145 +18,278 @@ A Composer library to integrate LayerZero composer contracts with the Omnichain Fungible Token (OFT) standard.

-- [What is an Omnichain Fungible Token?](#what-is-an-omnichain-fungible-token) -- [Using Composer with OFTs](#using-composer-with-ofts) -- [LayerZero Hardhat Helper Tasks](#layerzero-hardhat-helper-tasks) -- [Developing & Deploying Contracts](#developing-contracts) -- [Connecting Contracts](#connecting-contracts) +## Table of Contents -## What is an Omnichain Fungible Token? +- [Prerequisite Knowledge](#prerequisite-knowledge) +- [Introduction](#introduction) +- [Requirements](#requirements) +- [Scaffold this Example](#scaffold-this-example) +- [Helper Tasks](#helper-tasks) +- [Setup](#setup) + - [1. Environment Configuration](#1-environment-configuration) + - [2. Network Configuration](#2-network-configuration) + - [3. Composer Deployment Configuration](#3-composer-deployment-configuration) +- [Build](#build) +- [Deploy](#deploy) + - [UniswapV3 Composer Deployment](#uniswapv3-composer-deployment) + - [AaveV3 Composer Deployment](#aavev3-composer-deployment) +- [Enable Messaging (for manually deployed OFTs only)](#enable-messaging-for-manually-deployed-ofts-only) +- [Stargate to Aave Supply Task](#stargate-to-aave-supply-task) +- [Next Steps](#next-steps) +- [Production Deployment Checklist](#production-deployment-checklist) +- [Appendix](#appendix) + - [Running Tests](#running-tests) + - [Adding Other Chains](#adding-other-chains) + - [LayerZero Hardhat Helper Tasks (Detailed)](#layerzero-hardhat-helper-tasks-detailed) + - [Troubleshooting](#troubleshooting) -The Omnichain Fungible Token (OFT) standard extends the ERC20 interface to enable seamless cross-chain token transfers without the need for asset wrapping or intermediary chains. By combining LayerZero’s OApp Contract Standard with ERC20’s `_burn` and `_mint` methods, OFTs maintain a unified token supply across multiple blockchains. +## Prerequisite Knowledge -LayerZero +Before diving into this repository you should understand: -Learn more about OFTs in the [OFT Quickstart](https://docs.layerzero.network/v2/developers/evm/oft/quickstart). +- [OFT Standard](https://docs.layerzero.network/v2/developers/evm/oft/quickstart) — how omnichain ERC20s are minted/burned across chains. +- [Composer Pattern](https://docs.layerzero.network/v2/developers/evm/composer/overview) — how OFT transfers can be extended with compose payloads. +- [Target Protocols](https://docs.uniswap.org/contracts/v3) — Uniswap V3 swaps and [Aave v3](https://docs.aave.com/developers/core-contracts/pool) lending flow. -## Using Composer with OFTs +## Introduction -This repository is not only a template for OFTs, it’s a fully featured **composer library** that empowers you to build composable, cross-chain applications using LayerZero’s composer contracts in combination with the OFT standard. +The OFT Composer library demonstrates how to run **post-bridge workflows** on the destination chain. Two ready-to-run contracts live in `contracts/` and their deployment scripts live in `deploy/`: -For example, our repository includes an example contract (see [UniswapV3Composer.sol](./contracts/UniswapV3Composer.sol)) that demonstrates how to: +- `UniswapV3Composer` routes bridged tokens into a Uniswap V3 swap. +- `AaveV3Composer` routes bridged tokens through Stargate and supplies them to an Aave v3 pool. -- Receive cross-chain messages via LayerZero. -- Decode composable messages (using `OFTComposeMsgCodec`) to extract parameters. -- Execute token swaps on Uniswap V3 after an OFT transfer. -- Gracefully handle failures by refunding tokens. +The example mirrors the [OVault walkthrough](./EX_README.md) so you can reuse the same workflow: configure networks, deploy composable endpoints, wire messaging, and finally execute cross-chain operations with helpful Hardhat tasks. -This composability approach lets you extend basic omnichain token transfers with additional logic—such as token swaps, lending, or other decentralized finance features. For more information on composability, visit the [What is Composability?](https://docs.layerzero.network/v2/concepts/applications/composer-standard) documentation and the [EVM Composer Overview](https://docs.layerzero.network/v2/developers/evm/composer/overview). +## Requirements -## LayerZero Hardhat Helper Tasks +- git +- Node.js ≥ 18.18 +- pnpm ≥ 8.15 (enable via `corepack enable`) -LayerZero Devtools offers several helper tasks to deploy, configure, connect, and wire your OFT and composer contracts across multiple chains. These tasks streamline operations like: +## Scaffold this Example + +```bash +LZ_ENABLE_OFT_COMPOSERS=1 npx create-lz-oapp@latest +``` + +## Helper Tasks + +Run `pnpm hardhat` to list every built-in task. The most relevant tasks for this example are: + +- `lz:deploy` — deploy and tag composer contracts per network. +- `lz:oapp:config:init` / `lz:oapp:wire` — bootstrap and apply messaging configs. +- `lz:oft:send` — send OFT tokens without composer logic (useful for smoke tests). +- `aave:supply` — bridge tokens through Stargate and compose into `AaveV3Composer`. -- **Deploying Contracts:** - ```bash - npx hardhat lz:deploy - ``` - Deploy your contracts to networks specified in your `hardhat.config.ts`. +## Setup -- **Initializing Configuration:** +### 1. Environment Configuration - ```bash - npx hardhat lz:oapp:config:init --contract-name YOUR_CONTRACT_NAME --oapp-config FILE_NAME - ``` +Copy the template and fill in every value before running builds, deploys, or tasks: - Generate a default `layerzero.config.ts` file for setting up cross-chain pathways. +```bash +cp .env.example .env +``` -- **Wiring Contracts:** +```bash +PRIVATE_KEY="0xyourdeployer" +``` - ```bash - npx hardhat lz:oapp:wire --oapp-config YOUR_LAYERZERO_CONFIG_FILE - ``` +- `SWAP_ROUTER_ADDRESS` / `OFT_ADDRESS` are required by `deploy/UniswapV3Composer.ts`. +- `AAVE_V3_POOL_ADDRESS` / `STARGATE_POOL_ADDRESS` are required by `deploy/AaveV3Composer.ts` and by the `aave:supply` task. +- Add any other per-chain secrets (like Tenderly keys) that your Hardhat networks need. + +### 2. Network Configuration + +Edit `hardhat.config.ts` and align networks with the Endpoint IDs you intend to use. Example configuration: + +```ts +const config: HardhatUserConfig = { + networks: { + base: { + eid: EndpointId.BASESEP_V2_TESTNET, + url: process.env.RPC_URL_BASESEP_TESTNET ?? 'https://base-sepolia.gateway.tenderly.co', + accounts, + }, + arbitrum: { + eid: EndpointId.ARBSEP_V2_TESTNET, + url: process.env.RPC_URL_ARBSEP_TESTNET ?? 'https://arbitrum-sepolia.gateway.tenderly.co', + accounts, + }, + }, + // ... +} +``` - Connect your deployed contracts by executing the necessary configuration functions. +Ensure every network listed here has a matching `RPC_URL_*` entry in `.env`. -- **Viewing Current Configurations:** - ```bash - npx hardhat lz:oapp:config:get --oapp-config YOUR_OAPP_CONFIG - ``` - Review the active, custom, and default configurations for each pathway. +### 3. Composer Deployment Configuration -For more details, refer to the [LayerZero Hardhat Helper Tasks Documentation](https://docs.layerzero.network/v2/developers/evm/create-lz-oapp/deploying). +Both composers rely on addresses passed through constructor arguments. Decide which chain will host each composer and verify you have the corresponding addresses: -## Developing Contracts +- **Uniswap:** needs the canonical SwapRouter (per chain) plus the OFT that forwards tokens to it. +- **Aave:** needs the Aave v3 Pool on the hub chain plus the Stargate pool on the source chain you’ll send from. -### Installing dependencies +## Build -We recommend using `pnpm` (or your preferred package manager): +Install dependencies and compile contracts: ```bash pnpm install +pnpm compile # runs both Hardhat + Forge toolchains ``` -### Compiling your contracts +Need a specific tool only? Run `pnpm compile:hardhat` or `pnpm compile:forge`. -This project supports both Hardhat and Forge compilations: +Run unit tests with `pnpm test`, or select suites via `pnpm test:hardhat` / `pnpm test:forge`. -```bash -pnpm compile -``` +## Deploy + +### UniswapV3 Composer Deployment -To compile with a specific tool: +- Script: `examples/oft-composers/deploy/UniswapV3Composer.ts` +- Required `.env` keys: `PRIVATE_KEY`, `SWAP_ROUTER_ADDRESS`, `OFT_ADDRESS`, the `RPC_URL_*` for the destination network. +- Constructor: `(swapRouter, oft)`. ```bash -pnpm compile:hardhat -pnpm compile:forge +SWAP_ROUTER_ADDRESS="0xUniswapRouterOnBase" \ +OFT_ADDRESS="0xAssetOFTOnBase" \ +pnpm hardhat deploy --tags UniswapV3Composer --network base ``` -### Running tests +The script validates addresses via `ethers.utils.isAddress` and prints the deployed composer address. Rerun the command whenever you update swap routes or need to redeploy; set `skipIfAlreadyDeployed` to `true` if you want Hardhat Deploy to keep the existing instance. + +### AaveV3 Composer Deployment -Both Hardhat and Forge tests are supported: +- Script: `examples/oft-composers/deploy/AaveV3Composer.ts` +- Required `.env` keys: `PRIVATE_KEY`, `AAVE_V3_POOL_ADDRESS`, `STARGATE_POOL_ADDRESS`, relevant `RPC_URL_*`. +- Constructor: `(aavePool, stargatePool)`. ```bash -pnpm test +AAVE_V3_POOL_ADDRESS="0xAavePoolOnBase" \ +STARGATE_POOL_ADDRESS="0xStargatePoolOnArbitrum" \ +pnpm hardhat deploy --tags AaveV3Composer --network base ``` -Or run specific tests: +The script asserts both addresses exist and belong to deployed contracts before broadcasting. Double-check that the Stargate pool you specify supports the token you’ll bridge (e.g., USDC on Arbitrum Sepolia) and that the Aave pool lives on the hub chain that will execute the supply. -```bash -pnpm test:hardhat -pnpm test:forge -``` +## Enable Messaging (for manually deployed OFTs only) -## Deploying Contracts +If you manually deployed OFTs (Asset/Share, adapters, or any custom OApp), you still need to wire them with LayerZero. There are two ways to do it—pick the one that matches your tooling: -1. **Set Up Deployer Wallet:** +### Option A — Use the generated `layerzero.config.ts` (default DVNs & Executors) - - Rename `.env.example` to `.env`. - - Configure your mnemonic or private key. +1. This example already ships a `layerzero.config.ts` that targets LayerZero’s default DVNs/Executors. Update the contract names/EIDs if you changed them during deployment. +2. Run wiring directly: -2. **Fund Your Account:** - Ensure your deployer wallet is funded with the appropriate native tokens. + ```bash + pnpm hardhat lz:oapp:wire --oapp-config layerzero.custom.config.ts + ``` + +This is the quickest path and mirrors the standard OFT example in `EX_README.md`. + +### Option B — Manual configs + +1. Generate per-mesh config scaffolding: -3. **Deploy Contracts:** ```bash - npx hardhat lz:deploy + npx hardhat lz:oapp:config:init --contract-name MyOFT --oapp-config layerzero.custom.config.ts ``` - Use the `--help` flag for additional CLI options. -## Connecting Contracts +2. Fill in DVNs, executors, and enforced gas options using the `TwoWayConfig` helpers. -1. **Configure Connections:** - Generate and customize your `layerzero.config.ts` file: +3. Wire each config once all contracts exist: ```bash - npx hardhat lz:oapp:config:init --contract-name [YOUR_CONTRACT_NAME] --oapp-config [CONFIG_NAME] + pnpm hardhat lz:oapp:wire --oapp-config layerzero.custom.config.ts ``` -2. **Define Network Pathways:** - Specify contracts and their interconnections (e.g., Ethereum <--> Arbitrum) in your configuration file. +Skip this entire section if you are using the Aave/Stargate composer workflow described below—Stargate pools already implement OFT semantics, so no extra wiring is required beyond configuring Stargate itself. + +## Stargate to Aave Supply Task + +File: `examples/oft-composers/tasks/supplyAave.ts` + +This task bridges tokens through Stargate and composes into `AaveV3Composer` to finalize a supply on Base. Example scenario: composer lives on **Base Sepolia (EID 30184)**, and you send USDC from **Arbitrum Sepolia (EID 30110)**. + + +1. Run the task with CLI parameters (replace placeholders with live addresses/amounts): -3. **Apply Configuration:** - Connect your deployed contracts by running: ```bash - npx hardhat lz:oapp:wire --oapp-config layerzero.config.ts + pnpm hardhat aave:supply \ + --stargate <0xStargatePoolAddress> \ + --dst-eid 30184 \ + --composer <0xComposerAddress> \ + --amount-ld 1000000 ``` -Join our community on [Discord](https://discord-layerzero.netlify.app/discord) or follow us on [Twitter](https://twitter.com/LayerZero_Labs) for updates. + - `amount-ld` is specified in local decimals (1,000,000 = 1 USDC if the pool uses 6 decimals). + - `compose-gas-limit` defaults to `395000`, which matches the gas used in `Options.newOptions()` inside `supplyAave.ts`. + +2. The task automatically: + - Encodes the compose payload (receiver address). + - Quotes Stargate fees and approves ERC20 transfers when needed. + - Sends the transaction with the correct messaging fee (native or LZ token). + +Monitor progress on [LayerZero Scan](https://testnet.layerzeroscan.com/) if anything fails in-flight. + +## Next Steps + +1. Track composer executions by indexing emitted events (see `OFTComposeMsgCodec` usage). +2. Parameterize gas limits per pathway to control costs tightly. +3. Add slippage controls by extending the compose payload and guarding on-chain execution. + +## Production Deployment Checklist + +- [ ] **Security Stack** + - [ ] Configure DVNs to meet your trust requirements. + - [ ] Set confirmation blocks per pathway (e.g., Base ↔ Arbitrum). + - [ ] Register Executor options with sufficient gas for swaps + lending calls. +- [ ] **Gas & Options** + - [ ] Profile composer gas usage under real traffic. + - [ ] Tune `lzCompose` gas for each workflow (swap vs. supply). + - [ ] Fall back to `lz:oft:send` for simple transfers when compose logic is unnecessary. +- [ ] **Composer Config** + - [ ] Store composer addresses in a registry so tasks can fetch them dynamically. + - [ ] Guard swap/supply logic with allowlists if you expose arbitrary payloads. + - [ ] Monitor Stargate pools for liquidity before large sends. + +## Appendix + +### Running Tests + +```bash +pnpm test +pnpm test:hardhat # only Hardhat +pnpm test:forge # only Forge +``` + +### Adding Other Chains + +1. Append new networks to `hardhat.config.ts` and `.env`. +2. Add composer and OFT addresses for the new chain to your deployment config. +3. Extend `layerzero.*.config.ts` pathways so the new chain can talk to existing hubs/spokes. +4. Re-run `lz:oapp:wire` with the updated config file. + +### LayerZero Hardhat Helper Tasks (Detailed) + +```bash +pnpm hardhat # list every task +pnpm hardhat lz:deploy # deploy tagged contracts +pnpm hardhat lz:oft:send # OFT transfers without compose logic +pnpm hardhat lz:oapp:wire --oapp-config layerzero.composer.config.ts +pnpm hardhat aave:supply # Stargate send + compose into Aave +``` + +### Troubleshooting + +1. **Missing `.env` entries** — double-check every section above; deployments will `assert(...)` if required addresses are absent. +2. **Composer revert (swap or supply)** — inspect the compose payload and ensure gas limits cover both the OFT receive and the protocol action. +3. **Slippage exceeded** — consider passing `--oft-cmd` or extending the payload so the composer can enforce min amounts. +4. **Allowance errors** — rerun `aave:supply` after the script auto-approves the Stargate pool; you may need to increase allowance for repeated sends. --- -By following these steps, you leverage LayerZero’s composer library to build and deploy innovative, composable cross-chain applications powered by the OFT standard. +Need help? Reach out in the [LayerZero Discord](https://discord-layerzero.netlify.app/discord) or check the [Developer Docs](https://docs.layerzero.network/). From b90bbb50d9b6cfcf2302194df3f390ab5c935f2d Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Mon, 17 Nov 2025 23:40:18 -0500 Subject: [PATCH 42/47] chore: minor changes + addressed feedback --- .../{AaveV3Composer => }/AaveV3Composer.sol | 20 +++++++++---------- .../UniswapV3Composer.sol | 2 +- .../IAaveV3Composer.sol | 0 .../IAaveV3Pool.sol | 2 +- .../interfaces/IStargateEndpoint.sol | 8 ++++++++ .../IUniswapV3Composer.sol | 0 6 files changed, 20 insertions(+), 12 deletions(-) rename examples/oft-composers/contracts/{AaveV3Composer => }/AaveV3Composer.sol (94%) rename examples/oft-composers/contracts/{UniswapV3Composer => }/UniswapV3Composer.sol (99%) rename examples/oft-composers/contracts/{AaveV3Composer => interfaces}/IAaveV3Composer.sol (100%) rename examples/oft-composers/contracts/{AaveV3Composer => interfaces}/IAaveV3Pool.sol (97%) create mode 100644 examples/oft-composers/contracts/interfaces/IStargateEndpoint.sol rename examples/oft-composers/contracts/{UniswapV3Composer => interfaces}/IUniswapV3Composer.sol (100%) diff --git a/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol b/examples/oft-composers/contracts/AaveV3Composer.sol similarity index 94% rename from examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol rename to examples/oft-composers/contracts/AaveV3Composer.sol index 3c2fa1c73..b9d3000d6 100644 --- a/examples/oft-composers/contracts/AaveV3Composer/AaveV3Composer.sol +++ b/examples/oft-composers/contracts/AaveV3Composer.sol @@ -4,14 +4,14 @@ pragma solidity ^0.8.19; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { ILayerZeroComposer } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol"; import { OFTComposeMsgCodec } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol"; -import { IOAppCore } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol"; import { IOFT, SendParam, MessagingFee } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; -import { IStargate } from "@stargatefinance/stg-evm-v2/src/interfaces/IStargate.sol"; +import { ILayerZeroComposer } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol"; +import { IStargateEndpoint } from "./interfaces/IStargateEndpoint.sol"; + +import { IAaveV3Composer } from "./interfaces/IAaveV3Composer.sol"; +import { IAaveV3Pool } from "./interfaces/IAaveV3Pool.sol"; -import { IAaveV3Composer } from "./IAaveV3Composer.sol"; -import { IPool } from "./IAaveV3Pool.sol"; /** * @title AaveV3Composer @@ -25,7 +25,7 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { using SafeERC20 for IERC20; /// @notice Aave V3 pool that receives supplied liquidity. - IPool public immutable AAVE; + IAaveV3Pool public immutable AAVE; /// @notice LayerZero Endpoint trusted to invoke `lzCompose`. address public immutable ENDPOINT; @@ -64,16 +64,16 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { if (_stargatePool == address(0)) revert InvalidStargatePool(); // Initialize the Aave pool. - AAVE = IPool(_aavePool); + AAVE = IAaveV3Pool(_aavePool); // Initialize the Stargate Pool. STARGATE = _stargatePool; // Gran the endpoint from the StargatePool. - ENDPOINT = address(IOAppCore(STARGATE).endpoint()); + ENDPOINT = address(IStargateEndpoint(_stargatePool).endpoint()); // Grab the underlying token from the StargatePool. - TOKEN_IN = IStargate(_stargatePool).token(); + TOKEN_IN = IOFT(_stargatePool).token(); // Grant a one-time unlimited allowance so Aave can pull funds during supply. IERC20(TOKEN_IN).approve(address(AAVE), type(uint256).max); @@ -176,6 +176,6 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { refundSendParam.to = OFTComposeMsgCodec.composeFrom(_message); refundSendParam.amountLD = _amount; - IOFT(_stargate).send{ value: _msgValue }(refundSendParam, MessagingFee(_msgValue, 0), _refundAddress); + IOFT(_stargate).send{ value: _msgValue }(refundSendParam, MessagingFee({ nativeFee: _msgValue, lzTokenFee: 0 }), _refundAddress); } } diff --git a/examples/oft-composers/contracts/UniswapV3Composer/UniswapV3Composer.sol b/examples/oft-composers/contracts/UniswapV3Composer.sol similarity index 99% rename from examples/oft-composers/contracts/UniswapV3Composer/UniswapV3Composer.sol rename to examples/oft-composers/contracts/UniswapV3Composer.sol index 54fc5fdd9..9836d8e6f 100644 --- a/examples/oft-composers/contracts/UniswapV3Composer/UniswapV3Composer.sol +++ b/examples/oft-composers/contracts/UniswapV3Composer.sol @@ -12,7 +12,7 @@ import { IOFT } from "@layerzerolabs/oft-evm/contracts/interfaces/IOFT.sol"; import { OFTComposeMsgCodec } from "@layerzerolabs/oft-evm/contracts/libs/OFTComposeMsgCodec.sol"; import { IOAppCore } from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppCore.sol"; -import { IUniswapV3Composer } from "./IUniswapV3Composer.sol"; +import { IUniswapV3Composer } from "./interfaces/IUniswapV3Composer.sol"; /** * @title UniswapV3Composer diff --git a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol b/examples/oft-composers/contracts/interfaces/IAaveV3Composer.sol similarity index 100% rename from examples/oft-composers/contracts/AaveV3Composer/IAaveV3Composer.sol rename to examples/oft-composers/contracts/interfaces/IAaveV3Composer.sol diff --git a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol b/examples/oft-composers/contracts/interfaces/IAaveV3Pool.sol similarity index 97% rename from examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol rename to examples/oft-composers/contracts/interfaces/IAaveV3Pool.sol index 11bedfbe1..c82c91700 100644 --- a/examples/oft-composers/contracts/AaveV3Composer/IAaveV3Pool.sol +++ b/examples/oft-composers/contracts/interfaces/IAaveV3Pool.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.0; * @author Aave * @notice Defines the basic interface for an Aave Pool. */ -interface IPool { +interface IAaveV3Pool { /** * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. * - E.g. User supplies 100 USDC and gets in return 100 aUSDC diff --git a/examples/oft-composers/contracts/interfaces/IStargateEndpoint.sol b/examples/oft-composers/contracts/interfaces/IStargateEndpoint.sol new file mode 100644 index 000000000..42062f8fd --- /dev/null +++ b/examples/oft-composers/contracts/interfaces/IStargateEndpoint.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; + +interface IStargateEndpoint { + function endpoint() external view returns (ILayerZeroEndpointV2); +} \ No newline at end of file diff --git a/examples/oft-composers/contracts/UniswapV3Composer/IUniswapV3Composer.sol b/examples/oft-composers/contracts/interfaces/IUniswapV3Composer.sol similarity index 100% rename from examples/oft-composers/contracts/UniswapV3Composer/IUniswapV3Composer.sol rename to examples/oft-composers/contracts/interfaces/IUniswapV3Composer.sol From 739ea88536680cd416ac6373885849e55c283b45 Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Mon, 17 Nov 2025 23:40:42 -0500 Subject: [PATCH 43/47] chore: modify test according contract changes --- examples/oft-composers/test/foundry/AaveV3Composer.t.sol | 4 ++-- examples/oft-composers/test/foundry/UniswapV3Composer.t.sol | 4 ++-- examples/oft-composers/test/mocks/AaveV3PoolMock.sol | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/oft-composers/test/foundry/AaveV3Composer.t.sol b/examples/oft-composers/test/foundry/AaveV3Composer.t.sol index 1e922dac5..5651d45b5 100644 --- a/examples/oft-composers/test/foundry/AaveV3Composer.t.sol +++ b/examples/oft-composers/test/foundry/AaveV3Composer.t.sol @@ -6,8 +6,8 @@ import "forge-std/Test.sol"; import { TestHelperOz5 } from "@layerzerolabs/test-devtools-evm-foundry/contracts/TestHelperOz5.sol"; // Composer contracts -import { AaveV3Composer } from "../../contracts/AaveV3Composer/AaveV3Composer.sol"; -import { IAaveV3Composer } from "../../contracts/AaveV3Composer/IAaveV3Composer.sol"; +import { AaveV3Composer } from "../../contracts/AaveV3Composer.sol"; +import { IAaveV3Composer } from "../../contracts/interfaces/IAaveV3Composer.sol"; // LayerZero helpers import { OFTComposeMsgCodec } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol"; diff --git a/examples/oft-composers/test/foundry/UniswapV3Composer.t.sol b/examples/oft-composers/test/foundry/UniswapV3Composer.t.sol index cdd58f1ac..5ce0678c1 100644 --- a/examples/oft-composers/test/foundry/UniswapV3Composer.t.sol +++ b/examples/oft-composers/test/foundry/UniswapV3Composer.t.sol @@ -3,9 +3,9 @@ pragma solidity ^0.8.20; // Import necessary testing libraries and contracts import "forge-std/Test.sol"; -import { UniswapV3Composer } from "../../contracts/UniswapV3Composer/UniswapV3Composer.sol"; +import { UniswapV3Composer } from "../../contracts/UniswapV3Composer.sol"; import { ISwapRouter } from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; -import { IUniswapV3Composer } from "../../contracts/UniswapV3Composer/IUniswapV3Composer.sol"; +import { IUniswapV3Composer } from "../../contracts/interfaces/IUniswapV3Composer.sol"; // Mock imports import { OFTMock } from "../mocks/OFTMock.sol"; diff --git a/examples/oft-composers/test/mocks/AaveV3PoolMock.sol b/examples/oft-composers/test/mocks/AaveV3PoolMock.sol index 18a1f3192..997a157c7 100644 --- a/examples/oft-composers/test/mocks/AaveV3PoolMock.sol +++ b/examples/oft-composers/test/mocks/AaveV3PoolMock.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.20; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { IPool } from "../../contracts/AaveV3Composer/IAaveV3Pool.sol"; +import { IAaveV3Pool } from "../../contracts/interfaces/IAaveV3Pool.sol"; -contract AaveV3PoolMock is IPool { +contract AaveV3PoolMock is IAaveV3Pool { address public lastAsset; uint256 public lastAmount; address public lastOnBehalfOf; From 579c838758afa92ea636b8a4b61526297e6f0e8e Mon Sep 17 00:00:00 2001 From: John Nguyen Date: Tue, 18 Nov 2025 16:40:49 -0500 Subject: [PATCH 44/47] chore: modify default networks --- examples/oft-composers/hardhat.config.ts | 12 ++++---- examples/oft-composers/layerzero.config.ts | 34 ++++------------------ 2 files changed, 11 insertions(+), 35 deletions(-) diff --git a/examples/oft-composers/hardhat.config.ts b/examples/oft-composers/hardhat.config.ts index ce521a782..ad201dc45 100644 --- a/examples/oft-composers/hardhat.config.ts +++ b/examples/oft-composers/hardhat.config.ts @@ -55,14 +55,14 @@ const config: HardhatUserConfig = { ], }, networks: { - 'arbitrum-mainnet': { - eid: EndpointId.ARBITRUM_V2_MAINNET, - url: process.env.RPC_URL_ARBITRUM || 'https://arbitrum.gateway.tenderly.co', + 'arbitrum-sepolia': { + eid: EndpointId.ARBSEP_V2_TESTNET, + url: process.env.RPC_URL_ARB_SEPOLIA || 'https://arbitrum-sepolia.gateway.tenderly.co', accounts, }, - 'base-mainnet': { - eid: EndpointId.BASE_V2_MAINNET, - url: process.env.RPC_URL_BASE || 'https://base.gateway.tenderly.co', + 'ethereum-sepolia': { + eid: EndpointId.SEPOLIA_V2_TESTNET, + url: process.env.RPC_URL_SEPOLIA || 'https://sepolia.gateway.tenderly.co', accounts, }, hardhat: { diff --git a/examples/oft-composers/layerzero.config.ts b/examples/oft-composers/layerzero.config.ts index 5a239c8ed..7f3380ed9 100644 --- a/examples/oft-composers/layerzero.config.ts +++ b/examples/oft-composers/layerzero.config.ts @@ -7,53 +7,29 @@ const sepoliaContract: OmniPointHardhat = { contractName: 'MyOFT', } -const fujiContract: OmniPointHardhat = { - eid: EndpointId.AVALANCHE_V2_TESTNET, - contractName: 'MyOFT', -} - -const amoyContract: OmniPointHardhat = { - eid: EndpointId.AMOY_V2_TESTNET, +const arbitrumSepoliaContract: OmniPointHardhat = { + eid: EndpointId.ARBSEP_V2_TESTNET, contractName: 'MyOFT', } const config: OAppOmniGraphHardhat = { contracts: [ - { - contract: fujiContract, - }, { contract: sepoliaContract, }, { - contract: amoyContract, + contract: arbitrumSepoliaContract, }, ], connections: [ - { - from: fujiContract, - to: sepoliaContract, - }, - { - from: fujiContract, - to: amoyContract, - }, { from: sepoliaContract, - to: fujiContract, + to: arbitrumSepoliaContract, }, { - from: sepoliaContract, - to: amoyContract, - }, - { - from: amoyContract, + from: arbitrumSepoliaContract, to: sepoliaContract, }, - { - from: amoyContract, - to: fujiContract, - }, ], } From b57ae3bbc8d8f0e5d24d52ad4f775f008bf78f80 Mon Sep 17 00:00:00 2001 From: lzJxhn Date: Thu, 20 Nov 2025 10:09:02 -0300 Subject: [PATCH 45/47] chore: clean old composer config --- packages/create-lz-oapp/src/config.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/create-lz-oapp/src/config.ts b/packages/create-lz-oapp/src/config.ts index 82081a5d9..4a0667150 100644 --- a/packages/create-lz-oapp/src/config.ts +++ b/packages/create-lz-oapp/src/config.ts @@ -225,17 +225,6 @@ export const getExamples = (): Example[] => { }, ] : []), - ...(process.env.LZ_ENABLE_COMPOSER_EXAMPLE - ? [ - { - id: 'oft-composer-library', - label: 'OFT Composer Library', - repository, - directory: 'examples/oft-composer-library', - ref, - }, - ] - : []), ...(process.env.LZ_ENABLE_EXPERIMENTAL_OMNI_CALL_EXAMPLE ? [ { From 392bf104adf9f068476666d35200945d346cce37 Mon Sep 17 00:00:00 2001 From: lzJxhn Date: Thu, 20 Nov 2025 10:11:09 -0300 Subject: [PATCH 46/47] chore: rename --- examples/oft-composers/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/oft-composers/README.md b/examples/oft-composers/README.md index 8ff5ab62c..6c19e0238 100644 --- a/examples/oft-composers/README.md +++ b/examples/oft-composers/README.md @@ -8,14 +8,14 @@ Homepage | Docs | Developers

-

LayerZero OFT Composer Library

+

LayerZero OFT Composer Examples

Quickstart | Configuration | Message Execution Options | Composer Overview

- A Composer library to integrate LayerZero composer contracts with the Omnichain Fungible Token (OFT) standard. + A set of Composer examples to integrate LayerZero composer contracts with the Omnichain Fungible Token (OFT) standard.

## Table of Contents @@ -58,7 +58,7 @@ The OFT Composer library demonstrates how to run **post-bridge workflows** on th - `UniswapV3Composer` routes bridged tokens into a Uniswap V3 swap. - `AaveV3Composer` routes bridged tokens through Stargate and supplies them to an Aave v3 pool. -The example mirrors the [OVault walkthrough](./EX_README.md) so you can reuse the same workflow: configure networks, deploy composable endpoints, wire messaging, and finally execute cross-chain operations with helpful Hardhat tasks. +Learn more about [OFT (Omnichain Fungible Token)](https://docs.layerzero.network/v2/concepts/glossary#oft-omnichain-fungible-token) ## Requirements @@ -222,7 +222,8 @@ This task bridges tokens through Stargate and composes into `AaveV3Composer` to --stargate <0xStargatePoolAddress> \ --dst-eid 30184 \ --composer <0xComposerAddress> \ - --amount-ld 1000000 + --amount-ld 1000000 \ + --network ``` - `amount-ld` is specified in local decimals (1,000,000 = 1 USDC if the pool uses 6 decimals). From 7947ba9f749ab37ccd18d7bd7d857242bfbd0f40 Mon Sep 17 00:00:00 2001 From: lzJxhn Date: Thu, 20 Nov 2025 10:18:02 -0300 Subject: [PATCH 47/47] chore: renamed stargatePool --- .../contracts/AaveV3Composer.sol | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/examples/oft-composers/contracts/AaveV3Composer.sol b/examples/oft-composers/contracts/AaveV3Composer.sol index b9d3000d6..e4deb396f 100644 --- a/examples/oft-composers/contracts/AaveV3Composer.sol +++ b/examples/oft-composers/contracts/AaveV3Composer.sol @@ -30,8 +30,8 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { /// @notice LayerZero Endpoint trusted to invoke `lzCompose`. address public immutable ENDPOINT; - /// @notice Stargate OFT that is authorized to trigger Aave supplies on this chain. - address public immutable STARGATE; + /// @notice OFT that is authorized to trigger Aave supplies on this chain. + address public immutable OFT_IN; /// @notice Underlying ERC20 token that backs the trusted Stargate OFT. address public immutable TOKEN_IN; @@ -57,23 +57,23 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { * 3. Saves ~5k gas on every compose execution. * * @param _aavePool Address of the target Aave V3 pool. - * @param _stargatePool StargatePool expected to receive the supplied tokens. + * @param _oftIn OFT expected to receive the supplied tokens. */ - constructor(address _aavePool, address _stargatePool) { + constructor(address _aavePool, address _oftIn) { if (_aavePool == address(0)) revert InvalidAavePool(); - if (_stargatePool == address(0)) revert InvalidStargatePool(); + if (_oftIn == address(0)) revert InvalidStargatePool(); // Initialize the Aave pool. AAVE = IAaveV3Pool(_aavePool); - // Initialize the Stargate Pool. - STARGATE = _stargatePool; + // Initialize the OFT address (Stargate Pool / OFT). + OFT_IN = _oftIn; - // Gran the endpoint from the StargatePool. - ENDPOINT = address(IStargateEndpoint(_stargatePool).endpoint()); + // Gran the endpoint from OFT. + ENDPOINT = address(IStargateEndpoint(_oftIn).endpoint()); - // Grab the underlying token from the StargatePool. - TOKEN_IN = IOFT(_stargatePool).token(); + // Grab the underlying token from the OFT. + TOKEN_IN = IOFT(_oftIn).token(); // Grant a one-time unlimited allowance so Aave can pull funds during supply. IERC20(TOKEN_IN).approve(address(AAVE), type(uint256).max); @@ -120,7 +120,7 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { bytes calldata /* _extraData */ ) external payable { // Authenticate call logic source. - if (_sender != STARGATE) revert OnlyValidComposerCaller(_sender); + if (_sender != OFT_IN) revert OnlyValidComposerCaller(_sender); if (msg.sender != ENDPOINT) revert OnlyEndpoint(msg.sender); // Decode the amount in local decimals and the compose message from the message. @@ -130,7 +130,7 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { try this.handleCompose{ value: msg.value }(_message, amountLD) { emit Sent(_guid); } catch { - _refund(STARGATE, _message, amountLD, tx.origin, msg.value); + _refund(OFT_IN, _message, amountLD, tx.origin, msg.value); emit Refunded(_guid); } } @@ -151,21 +151,21 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { try AAVE.supply(TOKEN_IN, _amountLD, _to, 0) { emit Supplied(_to, _amountLD); } catch { - _refund(STARGATE, _message, _amountLD, tx.origin, msg.value); + _refund(OFT_IN, _message, _amountLD, tx.origin, msg.value); emit SupplyFailedAndRefunded(_to, _amountLD); } } /** * @dev Internal function to refund input tokens to sender on source during a failed transaction - * @param _stargate The OFT contract address used for refunding + * @param _oftIn The OFT contract address used for refunding * @param _message The original message that was sent * @param _amount The amount of tokens to refund * @param _refundAddress Address to receive the refund * @param _msgValue The amount of native tokens sent with the transaction */ function _refund( - address _stargate, + address _oftIn, bytes calldata _message, uint256 _amount, address _refundAddress, @@ -176,6 +176,6 @@ contract AaveV3Composer is ILayerZeroComposer, IAaveV3Composer { refundSendParam.to = OFTComposeMsgCodec.composeFrom(_message); refundSendParam.amountLD = _amount; - IOFT(_stargate).send{ value: _msgValue }(refundSendParam, MessagingFee({ nativeFee: _msgValue, lzTokenFee: 0 }), _refundAddress); + IOFT(_oftIn).send{ value: _msgValue }(refundSendParam, MessagingFee({ nativeFee: _msgValue, lzTokenFee: 0 }), _refundAddress); } }