Skip to content

Commit

Permalink
feat: update LayerZero adapter to V2
Browse files Browse the repository at this point in the history
  • Loading branch information
zengzengzenghuy committed May 6, 2024
1 parent 1e146b0 commit 6b073de
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 62 deletions.
29 changes: 18 additions & 11 deletions packages/evm/contracts/adapters/LayerZero/LayerZeroAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ILayerZeroReceiver } from "./interfaces/ILayerZeroReceiver.sol";
import { BlockHashAdapter } from "../BlockHashAdapter.sol";
import { ILayerZeroEndpointV2, Origin } from "./interfaces/ILayerZeroEndpointV2.sol";

contract LayerZeroAdapter is BlockHashAdapter, Ownable, ILayerZeroReceiver {
contract LayerZeroAdapter is BlockHashAdapter, Ownable {
string public constant PROVIDER = "layer-zero";
address public immutable LAYER_ZERO_ENDPOINT;

Expand All @@ -20,17 +20,24 @@ contract LayerZeroAdapter is BlockHashAdapter, Ownable, ILayerZeroReceiver {
LAYER_ZERO_ENDPOINT = lzEndpoint;
}

function lzReceive(uint16 srcEndpointId, bytes memory srcPath, uint64 /* nonce */, bytes memory payload) external {
if (msg.sender != LAYER_ZERO_ENDPOINT || enabledReportersPaths[srcEndpointId] != keccak256(srcPath))
revert UnauthorizedLayerZeroReceive();
uint256 sourceChainId = chainIds[srcEndpointId];
(uint256[] memory ids, bytes32[] memory hashes) = abi.decode(payload, (uint256[], bytes32[]));
_storeHashes(sourceChainId, ids, hashes);
}

// set source chain reporter and source chain endpoint Id
function setReporterByChain(uint256 chainId, uint16 endpointId, address reporter) external onlyOwner {
enabledReportersPaths[endpointId] = keccak256(abi.encodePacked(reporter, address(this)));
enabledReportersPaths[endpointId] = bytes32(abi.encodePacked(reporter));
chainIds[endpointId] = chainId;
emit ReporterSet(chainId, endpointId, reporter);
}

function lzReceive(
Origin calldata _origin,
bytes32 /*_guid*/,
bytes calldata _message,
address /*_executor*/,
bytes calldata /*_extraData*/
) external payable {
if (msg.sender != LAYER_ZERO_ENDPOINT || enabledReportersPaths[_origin.srcEid] != _origin.sender)
revert UnauthorizedLayerZeroReceive();
uint256 sourceChainId = chainIds[_origin.srcEid];
(uint256[] memory ids, bytes32[] memory hashes) = abi.decode(_message, (uint256[], bytes32[]));
_storeHashes(sourceChainId, ids, hashes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ILayerZeroEndpoint } from "./interfaces/ILayerZeroEndpoint.sol";
import { ILayerZeroEndpointV2, MessagingParams } from "./interfaces/ILayerZeroEndpointV2.sol";
import { Reporter } from "../Reporter.sol";

contract LayerZeroReporter is Reporter, Ownable {
contract LayerZeroV2Reporter is Reporter, Ownable {
string public constant PROVIDER = "layer-zero";
ILayerZeroEndpoint public immutable LAYER_ZERO_ENDPOINT;
ILayerZeroEndpointV2 public immutable LAYER_ZERO_ENDPOINT;

mapping(uint256 => uint16) public endpointIds;
mapping(uint256 => uint32) public endpointIds;
uint256 public fee;

error EndpointIdNotAvailable();
Expand All @@ -18,7 +18,7 @@ contract LayerZeroReporter is Reporter, Ownable {
event FeeSet(uint256 fee);

constructor(address headerStorage, address yaho, address lzEndpoint) Reporter(headerStorage, yaho) {
LAYER_ZERO_ENDPOINT = ILayerZeroEndpoint(lzEndpoint);
LAYER_ZERO_ENDPOINT = ILayerZeroEndpointV2(lzEndpoint);
}

function setEndpointIdByChainId(uint256 chainId, uint16 endpointId) external onlyOwner {
Expand All @@ -37,18 +37,24 @@ contract LayerZeroReporter is Reporter, Ownable {
uint256[] memory ids,
bytes32[] memory hashes
) internal override returns (bytes32) {
uint16 targetEndpointId = endpointIds[targetChainId];
uint32 targetEndpointId = endpointIds[targetChainId];
if (targetEndpointId == 0) revert EndpointIdNotAvailable();
bytes memory payload = abi.encode(ids, hashes);
bytes memory path = abi.encodePacked(adapter, address(this));
// OptionsBuilder::newOptions
// https://github.com/LayerZero-Labs/LayerZero-v2/blob/1fde89479fdc68b1a54cda7f19efa84483fcacc4/oapp/contracts/oapp/libs/OptionsBuilder.sol#L38
bytes memory options = abi.encodePacked(uint16(3));
bytes memory message = abi.encode(ids, hashes);
MessagingParams memory params = MessagingParams(
endpointIds[targetChainId],
bytes32(abi.encodePacked(adapter)),
message,
options,
false
);

// solhint-disable-next-line check-send-result
LAYER_ZERO_ENDPOINT.send{ value: fee }(
targetEndpointId,
path,
payload,
payable(msg.sender), // _refundAddress: refund address
address(0), // _zroPaymentAddress: future parameter
bytes("") // _adapterParams: adapterParams (see "Advanced Features")
params,
address(0) // refundAddress
);
return bytes32(0);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

struct MessagingParams {
uint32 dstEid;
bytes32 receiver;
bytes message;
bytes options;
bool payInLzToken;
}

struct MessagingReceipt {
bytes32 guid;
uint64 nonce;
MessagingFee fee;
}

struct MessagingFee {
uint256 nativeFee;
uint256 lzTokenFee;
}

struct Origin {
uint32 srcEid;
bytes32 sender;
uint64 nonce;
}

interface ILayerZeroEndpointV2 {
function send(
MessagingParams calldata _params,
address _refundAddress
) external payable returns (MessagingReceipt memory);
}

This file was deleted.

12 changes: 6 additions & 6 deletions packages/evm/tasks/deploy/adapters/layerzero.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { task } from "hardhat/config"
import type { TaskArguments } from "hardhat/types"

import type { LayerZeroAdapter } from "../../../types/contracts/adapters/LayerZero/LayerZeroAdapter"
import type { LayerZeroReporter } from "../../../types/contracts/adapters/LayerZero/LayerZeroReporter"
import type { LayerZeroV2Reporter } from "../../../types/contracts/adapters/LayerZero/LayerZeroV2Reporter"
import type { LayerZeroAdapter__factory } from "../../../types/factories/contracts/adapters/LayerZero/LayerZeroAdapter__factory"
import type { LayerZeroReporter__factory } from "../../../types/factories/contracts/adapters/LayerZero/LayerZeroReporter__factory"
import type { LayerZeroV2Reporter__factory } from "../../../types/factories/contracts/adapters/LayerZero/LayerZeroV2Reporter__factory"
import { verify } from "../index"

task("deploy:LayerZeroAdapter")
Expand All @@ -26,19 +26,19 @@ task("deploy:LayerZeroAdapter")
if (taskArguments.verify) await verify(hre, layerZeroAdapter, constructorArguments)
})

task("deploy:LayerZeroReporter")
task("deploy:LayerZeroV2Reporter")
.addParam("headerStorage", "address of the header storage contract")
.addParam("yaho", "address of the Yaho contract")
.addParam("lzEndpoint", "address of the LayerZero endpoint contract")
.addFlag("verify", "whether to verify the contract on Etherscan")
.setAction(async function (taskArguments: TaskArguments, hre) {
console.log("Deploying LayerZeroReporter...")
const signers: SignerWithAddress[] = await hre.ethers.getSigners()
const layerZeroReporterFactory: LayerZeroReporter__factory = <LayerZeroReporter__factory>(
await hre.ethers.getContractFactory("LayerZeroReporter")
const layerZeroReporterFactory: LayerZeroV2Reporter__factory = <LayerZeroV2Reporter__factory>(
await hre.ethers.getContractFactory("LayerZeroV2Reporter")
)
const constructorArguments = [taskArguments.headerStorage, taskArguments.yaho, taskArguments.lzEndpoint] as const
const layerZeroReporter: LayerZeroReporter = <LayerZeroReporter>(
const layerZeroReporter: LayerZeroV2Reporter = <LayerZeroV2Reporter>(
await layerZeroReporterFactory.connect(signers[0]).deploy(...constructorArguments)
)
await layerZeroReporter.deployed()
Expand Down

0 comments on commit 6b073de

Please sign in to comment.