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: implement layerzero adapter #149

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
165943c
WIP: inital conversion into multi-protocol
AntonAndell Jul 20, 2023
d3c2121
feat: setup foundry structure (#79)
sdpisreddevil Sep 18, 2023
0fecbc5
feat: testcase set admin (#80)
sdpisreddevil Sep 18, 2023
c082f15
feat: testcase set protocol fee (#81)
sdpisreddevil Sep 18, 2023
632a3bc
feat: testcase set protocol fee handler (#82)
sdpisreddevil Sep 18, 2023
6227495
fix: add default connection setter (#87)
sdpisreddevil Sep 19, 2023
8959749
fix: rlp encode library encoding fix for protocols (#89)
sdpisreddevil Sep 19, 2023
10d84e8
feat: handle requests multiple testcases (#90)
sdpisreddevil Sep 21, 2023
1237c0f
add successfulResponses record for responses
sdpisreddevil Sep 25, 2023
89b50aa
update successfulResponses variable after response is success
sdpisreddevil Sep 25, 2023
7a96955
feat: execute call testcases (#91)
sdpisreddevil Sep 26, 2023
42b2740
fix: clearing out unused code (#98)
gcranju Sep 26, 2023
e979f07
docs: solidity xcall deployment (#99)
sdpisreddevil Sep 26, 2023
6af358b
feat: rollback testcases (#92)
sdpisreddevil Sep 26, 2023
e1a914e
feat: execute rollback testcases (#93)
sdpisreddevil Sep 26, 2023
d69e2da
fix: testcase for send call message (#88)
sdpisreddevil Sep 26, 2023
665071e
fix: deployment script updated (#100)
gcranju Sep 27, 2023
94d2410
fix: add verify success test cases (#101)
sdpisreddevil Sep 28, 2023
98994e7
tests: Fix testExecuteRollbackMultiProtocol test
sdpisreddevil Oct 11, 2023
b529488
feat: ci add solidity code coverages (#140)
sdpisreddevil Oct 11, 2023
4acea42
refactor: evm folder structure
redlarva Oct 11, 2023
0e901e3
fix: solidity xcall cod coverage
redlarva Oct 11, 2023
e6c5842
feat: added evm multiprotocol dapp
gcranju Oct 11, 2023
086831b
fix: removed unnecessary imports
gcranju Oct 11, 2023
1351c38
fix: remove cache file
redlarva Oct 11, 2023
16c6fb2
fix: add cache to gitignore
redlarva Oct 11, 2023
f683146
Merge pull request #143 from icon-project/refactor/evm-folder-structure
sdpisreddevil Oct 11, 2023
bd6c1fc
feat: added interface for layerzero and install dependencies
redlarva Oct 20, 2023
60fb9ce
feat: implement layerzero adapter
redlarva Oct 20, 2023
f57f14d
Merge remote-tracking branch 'origin/feature/solidity-adapters' into …
redlarva Oct 31, 2023
2578e50
fix: test for layer-zero and wormhole
redlarva Oct 31, 2023
179effb
refactor: clean up
redlarva Oct 31, 2023
65e5f00
feat: add method to update gas limit for layer zero
redlarva Oct 31, 2023
e2c79a7
fix: use contract as refund address
redlarva Nov 2, 2023
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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@
[submodule "contracts/evm/lib/wormhole-solidity-sdk"]
path = contracts/evm/lib/wormhole-solidity-sdk
url = https://github.com/wormhole-foundation/wormhole-solidity-sdk
[submodule "contracts/evm/lib/solidity-examples"]
path = contracts/evm/lib/solidity-examples
url = https://github.com/LayerZero-Labs/solidity-examples
199 changes: 199 additions & 0 deletions contracts/evm/contracts/adapters/LayerZeroAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
pragma abicoder v2;

import "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol";
import "@xcall/utils/Types.sol";
import "@iconfoundation/btp2-solidity-library/interfaces/ICallService.sol";
import "@lz-contracts/interfaces/ILayerZeroReceiver.sol";
import "@lz-contracts/interfaces/ILayerZeroEndpoint.sol";
import "./interfaces/ILayerZeroAdapter.sol";
import "@xcall/contracts/xcall/interfaces/IConnection.sol";

/**
* @title LayerZeroAdapter
* @dev A contract serves as a cross-chain xcall adapter, enabling communication between xcall on different blockchain networks via LayerZero.
*/
contract LayerZeroAdapter is ILayerZeroAdapter, Initializable, ILayerZeroReceiver, IConnection {
bytes constant private EMPTY_BYTES = new bytes(2048);
mapping(uint256 => Types.PendingResponse) private pendingResponses;
mapping(string => uint16) private chainIds;
mapping(uint16 => string) private networkIds;
mapping(string => bytes) private adapterParams;
mapping(string => bytes) private remoteEndpoint;
address private layerZeroEndpoint;
address private xCall;
address private owner;
address private adminAddress;

modifier onlyOwner() {
require(msg.sender == owner, "OnlyOwner");
_;
}

modifier onlyAdmin() {
require(msg.sender == adminAddress, "OnlyAdmin");
_;
}

/**
* @dev Initializes the contract with LayerZero endpoint and xCall address.
* @param _layerZeroEndpoint The address of the LayerZero endpoint contract.
* @param _xCall The address of the xCall contract.
*/
function initialize(address _layerZeroEndpoint, address _xCall) public initializer {
owner = msg.sender;
adminAddress = msg.sender;
layerZeroEndpoint = _layerZeroEndpoint;
xCall = _xCall;

Check warning on line 48 in contracts/evm/contracts/adapters/LayerZeroAdapter.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/adapters/LayerZeroAdapter.sol#L45-L48

Added lines #L45 - L48 were not covered by tests
}

/**
* @dev Configure connection settings for a destination chain.
* @param networkId The network ID of the destination chain.
* @param chainId The chain ID of the destination chain.
* @param endpoint The endpoint or address of the destination chain.
* @param gasLimit The gas limit for the connection on the destination chain.
*/
function configureConnection(
string memory networkId,
uint16 chainId,
bytes memory endpoint,
uint256 gasLimit
) external override onlyAdmin {
require(bytes(networkIds[chainId]).length == 0, "Connection already configured");
networkIds[chainId] = networkId;
chainIds[networkId] = chainId;
remoteEndpoint[networkId] = abi.encodePacked(endpoint, address(this));
if (gasLimit > 0) {
adapterParams[networkId] = abi.encodePacked(uint16(1), gasLimit);

Check warning on line 69 in contracts/evm/contracts/adapters/LayerZeroAdapter.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/adapters/LayerZeroAdapter.sol#L65-L69

Added lines #L65 - L69 were not covered by tests
} else {
adapterParams[networkId] = bytes("");

Check warning on line 71 in contracts/evm/contracts/adapters/LayerZeroAdapter.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/adapters/LayerZeroAdapter.sol#L71

Added line #L71 was not covered by tests
}
}
AntonAndell marked this conversation as resolved.
Show resolved Hide resolved

/**
* @notice set or update gas limit for a destination chain.
* @param networkId The network ID of the destination chain.
* @param gasLimit The gas limit for transactions on the destination chain.
*/
function setGasLimit(
string calldata networkId,
uint256 gasLimit
) external override onlyAdmin {
if (gasLimit > 0) {
adapterParams[networkId] = abi.encodePacked(uint16(1), gasLimit);

Check warning on line 85 in contracts/evm/contracts/adapters/LayerZeroAdapter.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/adapters/LayerZeroAdapter.sol#L84-L85

Added lines #L84 - L85 were not covered by tests
} else {
adapterParams[networkId] = bytes("");

Check warning on line 87 in contracts/evm/contracts/adapters/LayerZeroAdapter.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/adapters/LayerZeroAdapter.sol#L87

Added line #L87 was not covered by tests
}
}

/**
* @dev Get the gas fee required to send a message to a specified destination network.
* @param _to The network ID of the target chain.
* @param _response Indicates whether the response fee is included (true) or not (false).
* @return _fee The fee for sending a message to the given destination network.
*/
function getFee(string memory _to, bool _response) external view override returns (uint256 _fee) {
(_fee,) = ILayerZeroEndpoint(layerZeroEndpoint).estimateFees(chainIds[_to], address(this), EMPTY_BYTES, false, adapterParams[_to]);
}

/**
* @dev Send a message to a specified destination network.
* @param _to The network ID of the destination network.
* @param _svc The name of the service.
* @param _sn The serial number of the message.
* @param _msg The serialized bytes of the service message.
*/
function sendMessage(
string memory _to,
string memory _svc,
int256 _sn,
bytes memory _msg
) external override payable {
require(msg.sender == xCall, "Only xCall can send messages");
uint256 fee;

if (_sn < 0) {
fee = this.getFee(_to, false);
if (address(this).balance < fee) {
uint256 sn = uint256(- _sn);
pendingResponses[sn] = Types.PendingResponse(_msg, _to);
emit ResponseOnHold(sn);
return;
}
} else {
fee = msg.value;
}


ILayerZeroEndpoint(layerZeroEndpoint).send{value: fee}(
chainIds[_to],
remoteEndpoint[_to],
abi.encodePacked(_msg),
payable(address(this)),
address(0x0),
adapterParams[_to]
);
}

/**
* @dev Endpoint that the LayerZero Relayer contract calls to deliver the payload.
* @param sourceChain The source chain ID.
* @param _srcAddress The source address.
* @param _nonce The nonce.
* @param payload The payload to be delivered.
*/
function lzReceive(
uint16 sourceChain,
bytes memory _srcAddress,
uint64 _nonce,
bytes memory payload
) public override {
require(msg.sender == layerZeroEndpoint, "Invalid endpoint caller");
string memory nid = networkIds[sourceChain];
require(keccak256(_srcAddress) == keccak256(abi.encodePacked(remoteEndpoint[nid])), "Source address mismatched");
ICallService(xCall).handleMessage(nid, payload);
}

/**
* @dev Pay and trigger the execution of a stored response to be sent back.
* @param _sn The serial number of the message for which the response is being triggered.
*/
function triggerResponse(uint256 _sn) external override payable {
int256 sn = int256(_sn);
Types.PendingResponse memory resp = pendingResponses[_sn];
delete pendingResponses[_sn];
uint256 fee = msg.value;

ILayerZeroEndpoint(layerZeroEndpoint).send{value: fee}(
chainIds[resp.targetNetwork],
remoteEndpoint[resp.targetNetwork],
abi.encodePacked(resp.msg),
payable(address(this)),
address(0x0),
adapterParams[resp.targetNetwork]
);
}

/**
* @dev Set the address of the admin.
* @param _address The address of the admin.
*/
function setAdmin(address _address) external onlyAdmin {
adminAddress = _address;
}

/**
* @dev Get the address of the admin.
* @return (Address) The address of the admin.
*/
function admin() external view returns (address) {
if (adminAddress == address(0)) {
return owner;

Check warning on line 193 in contracts/evm/contracts/adapters/LayerZeroAdapter.sol

View check run for this annotation

Codecov / codecov/patch

contracts/evm/contracts/adapters/LayerZeroAdapter.sol#L193

Added line #L193 was not covered by tests
}
return adminAddress;
}

fallback() external payable {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import "wormhole-solidity-sdk/interfaces/IWormholeRelayer.sol";
import "wormhole-solidity-sdk/interfaces/IWormholeReceiver.sol";
import "wormhole-solidity-sdk/Utils.sol";

import "./interfaces/IAdapter.sol";
import "./interfaces/IWormholeAdapter.sol";

import "@xcall/utils/Types.sol";
import "@xcall/contracts/xcall/interfaces/IConnection.sol";
import "@iconfoundation/btp2-solidity-library/interfaces/ICallService.sol";
import "@iconfoundation/btp2-solidity-library/interfaces/IConnection.sol";

/**
* @title WormholeAdapter
* @dev This contract serves as a cross-chain xcall adapter, enabling communication between xcall on different blockchain networks via Wormhole.
*/
contract WormholeAdapter is IAdapter, Initializable, IWormholeReceiver, IConnection {
contract WormholeAdapter is IWormholeAdapter, Initializable, IWormholeReceiver, IConnection {
mapping(uint256 => Types.PendingResponse) private pendingResponses;
mapping(string => uint16) private chainIds;
mapping(uint16 => string) private networkIds;
Expand Down
44 changes: 44 additions & 0 deletions contracts/evm/contracts/adapters/interfaces/ILayerZeroAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;

/**
* @title ILayerZeroAdapter.sol - Interface for xCall-LayerZero Adapter
* @dev This interface defines the functions and events for a xCall-LayerZero adapter, allowing communication and message transfer between xCall on different blockchain networks using LayerZero.
*/
interface ILayerZeroAdapter {
/**
* @notice Emitted when a response is put on hold.
* @param _sn The serial number of the response.
*/
event ResponseOnHold(uint256 indexed _sn);

/**
* @notice Configure connection settings for a destination chain.
* @param networkId The network ID of the destination chain.
* @param chainId The chain ID of the destination chain.
* @param endpoint The endpoint or address of the destination chain.
* @param gasLimit The gas limit for transactions on the destination chain.
*/
function configureConnection(
string calldata networkId,
uint16 chainId,
bytes memory endpoint,
uint256 gasLimit
) external;

/**
* @notice set or update gas limit for a destination chain.
* @param networkId The network ID of the destination chain.
* @param gasLimit The gas limit for transactions on the destination chain.
*/
function setGasLimit (
string calldata networkId,
uint256 gasLimit
) external;

/**
* @notice Pay and trigger the execution of a stored response to be sent back.
* @param _sn The serial number of the message for which the response is being triggered.
*/
function triggerResponse(uint256 _sn) external payable;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
pragma solidity >=0.8.0;

/**
* @title IAdapter - Interface for Wormhole-xCall Adapter
* @title IWormholeAdapter.sol - Interface for Wormhole-xCall Adapter
* @dev This interface defines the functions and events for a Wormhole-xCall adapter,
* allowing communication and message transfer between xCall on different blockchain networks.
*/
interface IAdapter {
interface IWormholeAdapter {
/**
* @notice Emitted when a response is put on hold.
* @param _sn The serial number of the response.
Expand Down

This file was deleted.

4 changes: 2 additions & 2 deletions contracts/evm/contracts/xcall/CallService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
pragma solidity >=0.8.0;
pragma abicoder v2;

import "@xcall/contracts/xcall/interfaces/IFeeManage.sol";
import "./interfaces/IFeeManage.sol";
import "./interfaces/IConnection.sol";
import "@xcall/utils/RLPDecodeStruct.sol";
import "@xcall/utils/RLPEncodeStruct.sol";
import "@xcall/utils/Types.sol";

import "@iconfoundation/btp2-solidity-library/interfaces/IConnection.sol";
import "@iconfoundation/btp2-solidity-library/interfaces/IBSH.sol";
import "@iconfoundation/btp2-solidity-library/interfaces/ICallService.sol";
import "@iconfoundation/btp2-solidity-library/interfaces/ICallServiceReceiver.sol";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,16 @@ interface IConnection {
) external view returns (
uint256 _fee
);

/**
* @dev Set the address of the admin.
* @param _address The address of the admin.
*/
function setAdmin(address _address) external;

/**
* @dev Get the address of the admin.
* @return (Address) The address of the admin.
*/
function admin() external view returns (address);
}
1 change: 1 addition & 0 deletions contracts/evm/lib/solidity-examples
Submodule solidity-examples added at 14fe77
2 changes: 2 additions & 0 deletions contracts/evm/remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/
openzeppelin-contracts/=lib/openzeppelin-contracts/
openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/
wormhole-solidity-sdk/=lib/wormhole-solidity-sdk/src/
@lz-contracts/=lib/solidity-examples/contracts/lzApp/
@lz-contracts/utils/=lib/solidity-examples/contracts/libraries/
Loading