Skip to content

Conversation

@St0rmBr3w
Copy link
Contributor

@St0rmBr3w St0rmBr3w commented Dec 3, 2024

In this PR:

  • Overview & Purpose:
    The UniswapV3Composer is a specialized component in the LayerZero OFT (Omnichain Fungible Token) ecosystem. It facilitates cross-chain token swaps by interacting with Uniswap V3 upon receiving tokens via LayerZero’s messaging system. Essentially, when tokens are transferred cross-chain using the OFT standard, a composed message containing swap details is generated. The composer decodes this message and executes a token swap on the destination chain—converting the incoming OFT token into another ERC20 token as specified.

  • What the Composer Is & Why It Exists:

    • What It Is: The composer is a contract that decodes structured messages (using the OFTComposeMsgCodec) which encapsulate swap parameters such as target token address, fee tier, recipient, minimum amount out, and slippage settings. It then leverages Uniswap V3's SwapRouter to perform the token swap.
    • Why It Exists: In a multi-chain environment, users often want to immediately convert tokens received on the destination chain to another asset. The composer automates this process, ensuring that swaps are executed securely and efficiently, thereby integrating LayerZero’s robust cross-chain messaging with Uniswap’s decentralized exchange functionality.
  • Interaction with the LayerZero OFT Contract Standard:
    The LayerZero OFT standard provides a framework for seamless cross-chain token transfers. During such transfers, a message is generated that encapsulates both the transfer details and additional swap instructions. The UniswapV3Composer listens for these messages from an authorized LayerZero Endpoint. Once a message is received, the contract:

    1. Verifies Authorization: Ensures the message originates from the designated OFT and trusted LayerZero Endpoint.
    2. Decodes the Message: Extracts the swap parameters including target token, fee tier, recipient, minimum amount expected out, and slippage parameters.
    3. Executes the Swap: Approves the Uniswap V3 router to spend the incoming token and initiates a swap according to the provided parameters.
  • Code Improvements:

    • Custom Errors: Replaced standard require statements with custom errors (InvalidSwapRouter, InvalidEndpoint, InvalidOFT, UnauthorizedOFT, and UnauthorizedEndpoint) to enhance gas efficiency and clarity.
    • Formatting & Lint Fixes: Adjusted line lengths and formatting to comply with style guidelines and resolve lint warnings.
    • Test Updates: Modified test cases to compare custom error selectors (e.g., UniswapV3Composer.UnauthorizedOFT.selector) instead of revert strings.
  • Limitations:

    • The implementation assumes that a valid Uniswap V3 liquidity pool exists on the destination chain for the specified token pair and fee tier.
    • Important: If no valid pool exists, the call to lzCompose will revert, as the swap cannot be executed without a proper liquidity pool. Users must ensure that the necessary pool is available on the destination chain before initiating a cross-chain token swap.

Overall, this PR enhances the security, efficiency, and readability of the composer implementation, ensuring seamless cross-chain token swaps that integrate with the LayerZero OFT standard and Uniswap V3—while also requiring the existence of a valid liquidity pool on the destination chain.

@St0rmBr3w St0rmBr3w changed the title feat: added UniswapV3Composer example 🗞️ Add composer swap examples Dec 11, 2024
@ryandgoulding
Copy link
Contributor

Although this is super cool, there is a lot of custom solidity code. I would recommend this is audited before adding it as an example. Maybe we can combine it with other examples work to save some cycles.

@St0rmBr3w
Copy link
Contributor Author

Although this is super cool, there is a lot of custom solidity code. I would recommend this is audited before adding it as an example. Maybe we can combine it with other examples work to save some cycles.

Yep, the idea would be to get this audited with any other composer examples we want.

Riley mentioned staking, but this really only applies to native assets so Uniswap is the only example we have at the moment.

Do you have any ideas for improving?

@socket-security
Copy link

socket-security bot commented Dec 13, 2024

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

Copy link
Collaborator

@shankars99 shankars99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few things that caught my eye

@shankars99
Copy link
Collaborator

is this ready to merge if the merge conflict is resolved?

@St0rmBr3w St0rmBr3w changed the title 🗞️ Add composer swap examples DEVREL-522 🗞️ Add composer swap examples Jun 11, 2025
@socket-security
Copy link

socket-security bot commented Jun 11, 2025

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​layerzerolabs/​test-devtools-evm-foundry@​5.1.0821007985100

View full report

@St0rmBr3w St0rmBr3w changed the title DEVREL-522 🗞️ Add composer swap examples DEVREL-911 DEVREL-522 🗞️ Add composer swap examples Nov 15, 2025
Comment on lines 230 to 236
{
id: 'oft-composer-library',
label: 'OFT Composer Library',
repository,
directory: 'examples/oft-composer-library',
ref,
},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to change the name from OFT Composer Library to composer examples, we'll need to change this label and directory reference.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed.

In my previous commit i added the correct oft-composers example to this config file, forgot to delete the old version, thanks.

],
},
networks: {
'arbitrum-mainnet': {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lzJxhn does this example only work on mainnet? why do we have mainnet here ? typically for examples, we just use testnet.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed.

i tested on both testnet (e.g. arbsep -> sep) and mainnet (e.g. arb -> base), must have pushed mainnet version in recent commits.

}

const fujiContract: OmniPointHardhat = {
eid: EndpointId.AVALANCHE_V2_TESTNET,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lzJxhn bumping this up

}

const config: OAppOmniGraphHardhat = {
contracts: [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, hardhat config lists base and ethereum, but LZ config here uses a different combination of networks

I would suggest to standardise based on /docs/EXAMPLES_SPECS.md (check on main)

  1. Two chains only: Examples should use only 2 chains by default to reduce testnet setup friction; use “Add other chains” section to scale up if needed. For EVM, prefer using the following in the following order: Arbitrum Sepolia (EndpointId.ARBSEP_V2_TESTNET), Base Sepolia (EndpointId.BASESEP_V2_TESTNET).
  • in hardhat.config.ts, the network names should be like arbitrum-sepolia and base-sepolia (and NOT arbitrum-testnet or base-testnet)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed.

* 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.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _param _stargatePool should be renamed to be something closer to _stargateOFT or just _oftIn or something similar.

While it's true this example uses Stargate, you can supply WETH or other asset pools related to Aave.

For example, Stargate on Scroll uses Hydra OFTs, not pools. All pools are IOFT, but not all IOFTs are pools.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed.

<a href="https://layerzero.network" style="color: #a77dff">Homepage</a> | <a href="https://docs.layerzero.network/" style="color: #a77dff">Docs</a> | <a href="https://layerzero.network/developers" style="color: #a77dff">Developers</a>
</p>

<h1 align="center">LayerZero OFT Composer Library</h1>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready to review in a state where CI passes and the PR is quite upto date with main and you need reviews

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants