Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrate LZ contracts from the relay repo #1184

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions lib/layer-zero/ExampleHTSConnector.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "./hts/HederaTokenService.sol";
import "./hts/IHederaTokenService.sol";
import "./hts/KeyHelper.sol";
import "./HTSConnector.sol";

contract ExampleHTSConnector is Ownable, HTSConnector {
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _delegate
) payable HTSConnector(_name, _symbol, _lzEndpoint, _delegate) Ownable(_delegate) {}
}
16 changes: 16 additions & 0 deletions lib/layer-zero/ExampleHTSConnectorExistingToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "./hts/HederaTokenService.sol";
import "./hts/IHederaTokenService.sol";
import "./hts/KeyHelper.sol";
import "./HTSConnectorExistingToken.sol";

contract ExampleHTSConnectorExistingToken is Ownable, HTSConnectorExistingToken {
constructor(
address _tokenAddress,
address _lzEndpoint,
address _delegate
) payable HTSConnectorExistingToken(_tokenAddress, _lzEndpoint, _delegate) Ownable(_delegate) {}
}
74 changes: 74 additions & 0 deletions lib/layer-zero/ExampleOApp.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.22;

import {OApp, Origin, MessagingFee} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OApp.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract ExampleOApp is OApp {
constructor(address _endpoint, address _owner) OApp(_endpoint, _owner) Ownable(_owner) {}

// Some arbitrary data you want to deliver to the destination chain!
string public data;

/**
* @notice Sends a message from the source to destination chain.
* @param _dstEid Destination chain's endpoint ID.
* @param _message The message to send.
* @param _options Message execution options (e.g., for sending gas to destination).
*/
function send(
uint32 _dstEid,
string memory _message,
bytes calldata _options
) external payable {
// Encodes the message before invoking _lzSend.
// Replace with whatever data you want to send!
bytes memory _payload = abi.encode(_message);
_lzSend(
_dstEid,
_payload,
_options,
// Fee in native gas and ZRO token.
MessagingFee(msg.value, 0),
// Refund address in case of failed source message.
payable(msg.sender)
);
}

/**
* @dev Called when data is received from the protocol. It overrides the equivalent function in the parent contract.
* Protocol messages are defined as packets, comprised of the following parameters.
* @param _origin A struct containing information about where the packet came from.
* @param _guid A global unique identifier for tracking the packet.
* @param payload Encoded message.
*/
function _lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata payload,
address, // Executor address as specified by the OApp.
bytes calldata // Any extra data or options to trigger on receipt.
) internal override {
// Decode the payload to get the message
// In this case, type is string, but depends on your encoding!
data = abi.decode(payload, (string));
}

/**
* @notice Quotes the gas needed to pay for the full omnichain transaction in native gas or ZRO token.
* @param _dstEid Destination chain's endpoint ID.
* @param _message The message.
* @param _options Message execution options (e.g., for sending gas to destination).
* @param _payInLzToken Whether to return fee in ZRO token.
* @return fee A `MessagingFee` struct containing the calculated gas fee in either the native token or ZRO token.
*/
function quote(
uint32 _dstEid,
string memory _message,
bytes memory _options,
bool _payInLzToken
) public view returns (MessagingFee memory fee) {
bytes memory payload = abi.encode(_message);
fee = _quote(_dstEid, payload, _options, _payInLzToken);
}
}
25 changes: 25 additions & 0 deletions lib/layer-zero/ExampleOFT.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.22;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {OFT} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFT.sol";

contract ExampleOFT is OFT {
uint8 decimalsArg = 8;

constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _delegate,
uint256 _initialMint,
uint8 _decimals
) OFT(_name, _symbol, _lzEndpoint, _delegate) Ownable(_delegate) {
_mint(msg.sender, _initialMint);
decimalsArg = _decimals;
}

function decimals() public view override returns (uint8) {
return decimalsArg;
}
}
13 changes: 13 additions & 0 deletions lib/layer-zero/ExampleOFTAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.22;

import {OFTAdapter} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTAdapter.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract ExampleOFTAdapter is OFTAdapter {
constructor(
address _token,
address _lzEndpoint,
address _owner
) OFTAdapter(_token, _lzEndpoint, _owner) Ownable(_owner) {}
}
17 changes: 17 additions & 0 deletions lib/layer-zero/ExampleONFT.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.22;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ONFT721} from "@layerzerolabs/onft-evm/contracts/onft721/ONFT721.sol";

contract ExampleONFT is ONFT721 {
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _delegate,
uint256 tokenId
) ONFT721(_name, _symbol, _lzEndpoint, _delegate) {
_mint(msg.sender, tokenId);
}
}
13 changes: 13 additions & 0 deletions lib/layer-zero/ExampleONFTAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.22;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ONFT721Adapter} from "@layerzerolabs/onft-evm/contracts/onft721/ONFT721Adapter.sol";

contract ExampleONFTAdapter is ONFT721Adapter {
constructor(
address _token,
address _lzEndpoint,
address _owner
) ONFT721Adapter(_token, _lzEndpoint, _owner) { }
}
116 changes: 116 additions & 0 deletions lib/layer-zero/HTSConnector.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {OFTCore} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTCore.sol";
import "./hts/HederaTokenService.sol";
import "./hts/IHederaTokenService.sol";
import "./hts/KeyHelper.sol";

/**
* @title HTS Connector
* @dev HTS Connector is a HTS token that extends the functionality of the OFTCore contract.
*/
abstract contract HTSConnector is OFTCore, KeyHelper, HederaTokenService {
address public htsTokenAddress;

event TokenCreated(address tokenAddress);

/**
* @dev Constructor for the HTS Connector contract.
* @param _name The name of HTS token
* @param _symbol The symbol of HTS token
* @param _lzEndpoint The LayerZero endpoint address.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(
string memory _name,
string memory _symbol,
address _lzEndpoint,
address _delegate
) payable OFTCore(8, _lzEndpoint, _delegate) {
IHederaTokenService.TokenKey[] memory keys = new IHederaTokenService.TokenKey[](1);
keys[0] = getSingleKey(
KeyType.SUPPLY,
KeyValueType.INHERIT_ACCOUNT_KEY,
bytes("")
);

IHederaTokenService.Expiry memory expiry = IHederaTokenService.Expiry(0, address(this), 8000000);
IHederaTokenService.HederaToken memory token = IHederaTokenService.HederaToken(
_name, _symbol, address(this), "memo", true, 5000, false, keys, expiry
);

(int responseCode, address tokenAddress) = HederaTokenService.createFungibleToken(
token, 1000, int32(int256(uint256(8)))
);
require(responseCode == HederaTokenService.SUCCESS_CODE, "Failed to create HTS token");

int256 transferResponse = HederaTokenService.transferToken(tokenAddress, address(this), msg.sender, 1000);
require(transferResponse == HederaTokenService.SUCCESS_CODE, "HTS: Transfer failed");

htsTokenAddress = tokenAddress;

emit TokenCreated(tokenAddress);
}

/**
* @dev Retrieves the address of the underlying HTS implementation.
* @return The address of the HTS token.
*/
function token() public view returns (address) {
return htsTokenAddress;
}

/**
* @notice Indicates whether the HTS Connector contract requires approval of the 'token()' to send.
* @return requiresApproval Needs approval of the underlying token implementation.
*/
function approvalRequired() external pure virtual returns (bool) {
return false;
}

/**
* @dev Burns tokens from the sender's specified balance.
* @param _from The address to debit the tokens from.
* @param _amountLD The amount of tokens to send in local decimals.
* @param _minAmountLD The minimum amount to send in local decimals.
* @param _dstEid The destination chain ID.
* @return amountSentLD The amount sent in local decimals.
* @return amountReceivedLD The amount received in local decimals on the remote.
*/
function _debit(
address _from,
uint256 _amountLD,
uint256 _minAmountLD,
uint32 _dstEid
) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
(amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);

int256 transferResponse = HederaTokenService.transferToken(htsTokenAddress, _from, address(this), int64(uint64(_amountLD)));
require(transferResponse == HederaTokenService.SUCCESS_CODE, "HTS: Transfer failed");

(int256 response,) = HederaTokenService.burnToken(htsTokenAddress, int64(uint64(amountSentLD)), new int64[](0));
require(response == HederaTokenService.SUCCESS_CODE, "HTS: Burn failed");
}

/**
* @dev Credits tokens to the specified address.
* @param _to The address to credit the tokens to.
* @param _amountLD The amount of tokens to credit in local decimals.
* @dev _srcEid The source chain ID.
* @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.
*/
function _credit(
address _to,
uint256 _amountLD,
uint32 /*_srcEid*/
) internal virtual override returns (uint256) {
(int256 response, ,) = HederaTokenService.mintToken(htsTokenAddress, int64(uint64(_amountLD)), new bytes[](0));
require(response == HederaTokenService.SUCCESS_CODE, "HTS: Mint failed");

int256 transferResponse = HederaTokenService.transferToken(htsTokenAddress, address(this), _to, int64(uint64(_amountLD)));
require(transferResponse == HederaTokenService.SUCCESS_CODE, "HTS: Transfer failed");

return _amountLD;
}
}
90 changes: 90 additions & 0 deletions lib/layer-zero/HTSConnectorExistingToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {OFTCore} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTCore.sol";
import "./hts/HederaTokenService.sol";
import "./hts/IHederaTokenService.sol";
import "./hts/KeyHelper.sol";

/**
* @title HTS Connector for existing token
* @dev HTSConnectorExistingToken is a contract wrapped for already existing HTS token that extends the functionality of the OFTCore contract.
*/
abstract contract HTSConnectorExistingToken is OFTCore, KeyHelper, HederaTokenService {
address public htsTokenAddress;

/**
* @dev Constructor for the HTSConnectorExistingToken contract.
* @param _tokenAddress Address of already existing HTS token
* @param _lzEndpoint The LayerZero endpoint address.
* @param _delegate The delegate capable of making OApp configurations inside of the endpoint.
*/
constructor(
address _tokenAddress,
address _lzEndpoint,
address _delegate
) payable OFTCore(8, _lzEndpoint, _delegate) {
htsTokenAddress = _tokenAddress;
}

/**
* @dev Retrieves the address of the underlying HTS implementation.
* @return The address of the HTS token.
*/
function token() public view returns (address) {
return htsTokenAddress;
}

/**
* @notice Indicates whether the HTS Connector contract requires approval of the 'token()' to send.
* @return requiresApproval Needs approval of the underlying token implementation.
*/
function approvalRequired() external pure virtual returns (bool) {
return false;
}

/**
* @dev Burns tokens from the sender's specified balance.
* @param _from The address to debit the tokens from.
* @param _amountLD The amount of tokens to send in local decimals.
* @param _minAmountLD The minimum amount to send in local decimals.
* @param _dstEid The destination chain ID.
* @return amountSentLD The amount sent in local decimals.
* @return amountReceivedLD The amount received in local decimals on the remote.
*/
function _debit(
address _from,
uint256 _amountLD,
uint256 _minAmountLD,
uint32 _dstEid
) internal virtual override returns (uint256 amountSentLD, uint256 amountReceivedLD) {
(amountSentLD, amountReceivedLD) = _debitView(_amountLD, _minAmountLD, _dstEid);

int256 transferResponse = HederaTokenService.transferToken(htsTokenAddress, _from, address(this), int64(uint64(_amountLD)));
require(transferResponse == HederaTokenService.SUCCESS_CODE, "HTS: Transfer failed");

(int256 response,) = HederaTokenService.burnToken(htsTokenAddress, int64(uint64(amountSentLD)), new int64[](0));
require(response == HederaTokenService.SUCCESS_CODE, "HTS: Burn failed");
}

/**
* @dev Credits tokens to the specified address.
* @param _to The address to credit the tokens to.
* @param _amountLD The amount of tokens to credit in local decimals.
* @dev _srcEid The source chain ID.
* @return amountReceivedLD The amount of tokens ACTUALLY received in local decimals.
*/
function _credit(
address _to,
uint256 _amountLD,
uint32 /*_srcEid*/
) internal virtual override returns (uint256) {
(int256 response, ,) = HederaTokenService.mintToken(htsTokenAddress, int64(uint64(_amountLD)), new bytes[](0));
require(response == HederaTokenService.SUCCESS_CODE, "HTS: Mint failed");

int256 transferResponse = HederaTokenService.transferToken(htsTokenAddress, address(this), _to, int64(uint64(_amountLD)));
require(transferResponse == HederaTokenService.SUCCESS_CODE, "HTS: Transfer failed");

return _amountLD;
}
}
Loading
Loading