Skip to content

Commit

Permalink
Merge pull request #66 from gnosis/feat/reporter
Browse files Browse the repository at this point in the history
feat: reporter, relayer, executor for Hashi v0.2
  • Loading branch information
allemanfredi authored Sep 23, 2024
2 parents c9c300a + 550f4ba commit 5479b75
Show file tree
Hide file tree
Showing 49 changed files with 3,108 additions and 110 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
**/.coverage_contracts
**/dist
**/node_modules
**/types
**/.yarn

# files
Expand Down
46 changes: 46 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
version: "3.8"

services:
mongodb:
image: mongo:latest
container_name: mongodb
ports:
- "27017:27017"
networks:
- mongo-network
volumes:
- mongo-data:/data/db

hashi_relayer:
build:
context: .
dockerfile: packages/relayer/Dockerfile
container_name: hashi_relayer
networks:
- mongo-network
depends_on:
- mongodb

hashi_executor:
build:
context: .
dockerfile: packages/executor/Dockerfile
container_name: hashi_executor
networks:
- mongo-network
depends_on:
- mongodb

hashi_reporter:
build:
context: .
dockerfile: packages/reporter/Dockerfile
container_name: hashi_reporter

networks:
mongo-network:
driver: bridge

volumes:
mongo-data:
driver: local
1 change: 1 addition & 0 deletions packages/evm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
types/
45 changes: 33 additions & 12 deletions packages/evm/contracts/adapters/LayerZero/LayerZeroAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,54 @@ pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ILayerZeroReceiver } from "./interfaces/ILayerZeroReceiver.sol";
import { Origin } from "./interfaces/ILayerZeroEndpointV2.sol";
import { OAppCore } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OAppCore.sol";
import { BlockHashAdapter } from "../BlockHashAdapter.sol";

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

mapping(uint32 => bytes32) public enabledReportersPaths;
mapping(uint32 => address) public enabledReporters;
mapping(uint32 => uint256) public chainIds;

error UnauthorizedLayerZeroReceive();

event ReporterSet(uint256 indexed chainId, uint16 indexed endpointId, address indexed reporter);
event ReporterSet(uint256 indexed chainId, uint32 indexed endpointId, address indexed reporter);

constructor(address lzEndpoint) {
constructor(address lzEndpoint, address delegate) OAppCore(lzEndpoint, delegate) {
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);
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) external payable {
if (
msg.sender != LAYER_ZERO_ENDPOINT ||
enabledReporters[_origin.srcEid] != address(uint160(uint256(_origin.sender)))
) revert UnauthorizedLayerZeroReceive();
(uint256[] memory ids, bytes32[] memory hashes) = abi.decode(_message, (uint256[], bytes32[]));
_storeHashes(chainIds[_origin.srcEid], ids, hashes);
}

function setReporterByChain(uint256 chainId, uint16 endpointId, address reporter) external onlyOwner {
enabledReportersPaths[endpointId] = keccak256(abi.encodePacked(reporter, address(this)));
function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public pure override returns (uint64 nonce) {
return 0;
}

function allowInitializePath(Origin calldata origin) public view override returns (bool) {
return peers[origin.srcEid] == origin.sender;
}

function oAppVersion() public pure virtual override returns (uint64 senderVersion, uint64 receiverVersion) {
return (1, 1);
}

function setReporterByChain(uint256 chainId, uint32 endpointId, address reporter) external onlyOwner {
enabledReporters[endpointId] = reporter;
chainIds[endpointId] = chainId;
emit ReporterSet(chainId, endpointId, reporter);
}
Expand Down
66 changes: 45 additions & 21 deletions packages/evm/contracts/adapters/LayerZero/LayerZeroReporter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,78 @@
pragma solidity ^0.8.20;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ILayerZeroEndpoint } from "./interfaces/ILayerZeroEndpoint.sol";
import { ILayerZeroEndpointV2, MessagingParams, MessagingFee, MessagingReceipt } from "./interfaces/ILayerZeroEndpointV2.sol";
import { Reporter } from "../Reporter.sol";
import { OptionsBuilder } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OptionsBuilder.sol";
import { OAppCore } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OAppCore.sol";

contract LayerZeroReporter is Reporter, Ownable, OAppCore {
using OptionsBuilder for bytes;

contract LayerZeroReporter 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;
uint256 public fee;
mapping(uint256 => uint32) public endpointIds;
uint128 public fee;
address refundAddress;

error EndpointIdNotAvailable();

event EndpointIdSet(uint256 indexed chainId, uint16 indexed endpointId);
event EndpointIdSet(uint256 indexed chainId, uint32 indexed endpointId);
event FeeSet(uint256 fee);

constructor(address headerStorage, address yaho, address lzEndpoint) Reporter(headerStorage, yaho) {
LAYER_ZERO_ENDPOINT = ILayerZeroEndpoint(lzEndpoint);
constructor(
address headerStorage,
address yaho,
address lzEndpoint,
address delegate,
address refundAddress_,
uint128 defaultFee_
) Reporter(headerStorage, yaho) OAppCore(lzEndpoint, delegate) {
refundAddress = refundAddress_;
fee = defaultFee_;
LAYER_ZERO_ENDPOINT = ILayerZeroEndpointV2(lzEndpoint);
}

function setEndpointIdByChainId(uint256 chainId, uint16 endpointId) external onlyOwner {
function setEndpointIdByChainId(uint256 chainId, uint32 endpointId) external onlyOwner {
endpointIds[chainId] = endpointId;
emit EndpointIdSet(chainId, endpointId);
}

function setFee(uint256 fee_) external onlyOwner {
function setFee(uint128 fee_) external onlyOwner {
fee = fee_;
emit FeeSet(fee);
}

function setDefaultRefundAddress(address refundAddress_) external onlyOwner {
refundAddress = refundAddress_;
}

function oAppVersion() public pure virtual override returns (uint64 senderVersion, uint64 receiverVersion) {
return (1, 1);
}
function _dispatch(
uint256 targetChainId,
address adapter,
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));
// solhint-disable-next-line check-send-result
LAYER_ZERO_ENDPOINT.send{ value: fee }(
bytes memory options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(fee, 0);
bytes memory message = abi.encode(ids, hashes);
MessagingParams memory params = MessagingParams(
targetEndpointId,
path,
payload,
payable(msg.sender), // _refundAddress: refund address
address(0), // _zroPaymentAddress: future parameter
bytes("") // _adapterParams: adapterParams (see "Advanced Features")
bytes32(abi.encode(adapter)),
message,
options,
false // receiver in lz Token
);
return bytes32(0);
// solhint-disable-next-line check-send-result
MessagingFee memory msgFee = LAYER_ZERO_ENDPOINT.quote(params, address(this));
MessagingReceipt memory receipt = LAYER_ZERO_ENDPOINT.send{ value: msgFee.nativeFee }(params, refundAddress);
return receipt.guid;
}

receive() external payable {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// 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 {
event PacketSent(bytes encodedPayload, bytes options, address sendLibrary);

event PacketVerified(Origin origin, address receiver, bytes32 payloadHash);

event PacketDelivered(Origin origin, address receiver);

event LzReceiveAlert(
address indexed receiver,
address indexed executor,
Origin origin,
bytes32 guid,
uint256 gas,
uint256 value,
bytes message,
bytes extraData,
bytes reason
);

event LzTokenSet(address token);

event DelegateSet(address sender, address delegate);

function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory);

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

function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external;

function verifiable(Origin calldata _origin, address _receiver) external view returns (bool);

function initializable(Origin calldata _origin, address _receiver) external view returns (bool);

function lzReceive(
Origin calldata _origin,
address _receiver,
bytes32 _guid,
bytes calldata _message,
bytes calldata _extraData
) external payable;

// oapp can burn messages partially by calling this function with its own business logic if messages are verified in order
function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external;

function setLzToken(address _lzToken) external;

function lzToken() external view returns (address);

function nativeToken() external view returns (address);

function setDelegate(address _delegate) external;
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.20;
import { Origin } from "./ILayerZeroEndpointV2.sol";

interface ILayerZeroReceiver {
// @notice LayerZero endpoint will invoke this function to deliver the message on the destination
// @param _srcChainId - the source endpoint identifier
// @param _srcAddress - the source sending contract address from the source chain
// @param _nonce - the ordered message nonce
// @param _payload - the signed payload is the UA bytes has encoded to be sent
function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;
function lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address _executor,
bytes calldata _extraData
) external payable;

function allowInitializePath(Origin calldata _origin) external view returns (bool);

function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64);
}
5 changes: 5 additions & 0 deletions packages/evm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@nomicfoundation/hardhat-chai-matchers": "^1.0.4",
"@nomicfoundation/hardhat-network-helpers": "^1.0.8",
"@nomicfoundation/hardhat-toolbox": "^2.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.8",
"@nomiclabs/hardhat-ethers": "^2.2.1",
"@nomiclabs/hardhat-etherscan": "^3.1.2",
"@trivago/prettier-plugin-sort-imports": "^4.0.0",
Expand Down Expand Up @@ -93,10 +94,14 @@
"@chainlink/contracts-ccip": "0.7.6",
"@connext/interfaces": "2.0.0",
"@hyperlane-xyz/core": "3.1.10",
"@layerzerolabs/lz-evm-messagelib-v2": "^2.3.29",
"@layerzerolabs/lz-evm-oapp-v2": "^2.3.29",
"@layerzerolabs/lz-evm-protocol-v2": "^2.3.29",
"@openzeppelin/contracts-upgradeable": "4.8.1",
"@polytope-labs/ismp-solidity": "^0.7.1",
"@polytope-labs/solidity-merkle-trees": "0.3.2",
"@routerprotocol/evm-gateway-contracts": "1.1.13",
"solidity-bytes-utils": "^0.8.2",
"solidity-rlp": "2.0.8"
}
}
Loading

0 comments on commit 5479b75

Please sign in to comment.