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

Layer Zero integration #52

Merged
merged 65 commits into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
5c49a2a
forge install: LayerZero
reednaa May 27, 2024
3b4f5ec
feat: initial lz sketch
reednaa May 27, 2024
94fce29
feat: inits
reednaa May 27, 2024
223d1ab
feat: move requirements into our repo
reednaa May 27, 2024
0a53131
feat: compiling in on 0.8
reednaa May 27, 2024
185c277
feat: send in endpoint v2
reednaa May 27, 2024
fe93270
feat: optimise gas queries for LZ
reednaa May 27, 2024
a1f7010
feat: verify LZ packages
reednaa May 27, 2024
cf99735
feat: doc
reednaa May 27, 2024
5bf66f0
feat: save gas by calling verifyable directly
reednaa May 27, 2024
34ec03c
feat: cleanup packet verification
reednaa May 27, 2024
6fbe4e2
feat: cleanup implementation
reednaa May 27, 2024
351f0f9
feat: clean up
reednaa May 27, 2024
51676dd
test: prepare tests
reednaa May 27, 2024
bdab3a9
forge install: LayerZero-v2
reednaa May 27, 2024
afb16e0
feat: Directly import OZ to remove interfaces and simplify testing
reednaa May 27, 2024
4f79b65
test: prepare testing suite for lz
reednaa May 27, 2024
4e8cfba
test: expose allowExternalCall
reednaa May 27, 2024
e1f5ce8
fix: allow contracts to be compiled
reednaa May 27, 2024
98998c8
feat: improve LZ refund
reednaa May 27, 2024
44cee2d
doc: questions for LZ working
reednaa May 27, 2024
34e2d78
feat: setallowInitializePath
reednaa May 27, 2024
3977910
feat: set configs of LZ
reednaa May 27, 2024
8352e12
Modify bridge_contracts
ajimeno04 May 27, 2024
b2327bc
modify .env.example
ajimeno04 May 27, 2024
5e37aa8
update deploy script
ajimeno04 May 27, 2024
7e2df82
feat: update much of the LZ implementation to better fit how LZ is in…
reednaa May 27, 2024
258a1c6
feat: update tests to match ULN removal
reednaa May 27, 2024
c112a30
feat: set options to TYPE_3 only
reednaa May 27, 2024
0196787
feat: documentation updates
reednaa May 27, 2024
df38b56
chore: remove unused comments
reednaa May 27, 2024
4ec0a69
fix: set LAYERZERO_OPTIONS to hex''
reednaa May 27, 2024
7d9c76e
Revert "fix: set LAYERZERO_OPTIONS to hex''"
reednaa May 27, 2024
3fb4a4d
feat: add comment regarding the minimum option length
reednaa May 27, 2024
8051276
feat: make test for LZ
reednaa May 30, 2024
066d731
forge install: solidity-bytes-utils
reednaa May 30, 2024
563215c
test: init config & send packet
reednaa May 31, 2024
5639765
Update deployment contract for new LayerZero escrow contracts
ajimeno04 Jun 2, 2024
689a907
fix: correctly provide all of the package in rawMessage
reednaa Jun 3, 2024
d81d6d8
test: verify packages
reednaa Jun 3, 2024
dffd805
feat: simplify contract very slightly
reednaa Jun 3, 2024
60766c4
feat: more LZ testing
reednaa Jun 3, 2024
f001dbf
test: invalid receiver
reednaa Jun 3, 2024
3129a0f
test: finsh LZ testing
reednaa Jun 3, 2024
1f723ab
update condig and deploy
ajimeno04 Jun 4, 2024
bcdd39c
Bridge contract
ajimeno04 Jun 5, 2024
287daaa
feat: initConfig script for LZ
reednaa Jun 5, 2024
1f9ae2f
feat: add broadcast to git ignore
reednaa Jun 5, 2024
fc4bcb3
feat: small fix for LZ contracts
reednaa Jun 5, 2024
b464270
feat: submit message script
reednaa Jun 5, 2024
869d3f7
feat: process message script
reednaa Jun 6, 2024
d092375
feat: set proofValidPeriod to 1 month
reednaa Jun 6, 2024
f4a4458
test: fix test with proof valid period
reednaa Jun 6, 2024
69a7905
feat: add additional estimateAdditionalCost view function
reednaa Jun 6, 2024
bb8c4d9
feat: final LZ changes & code documentation
reednaa Jun 6, 2024
040e175
feat: set license to MIT
reednaa Jun 17, 2024
0d9f2ba
fix: remove unused import and error
reednaa Jun 17, 2024
2cf24c6
fix: typos
reednaa Jun 17, 2024
f40e0fa
Merge pull request #53 from catalystdao/I4-typos
reednaa Jun 17, 2024
8126d94
Merge pull request #55 from catalystdao/W11-incorrect-SPDX-license-id…
reednaa Jun 17, 2024
5e016f8
Merge pull request #54 from catalystdao/W12-Unused-code
reednaa Jun 17, 2024
15bdf09
fix: Last types of verifiable
reednaa Jun 21, 2024
db0c96e
feat: further types
reednaa Jun 21, 2024
aea83f4
Merge pull request #56 from catalystdao/I4-typos
reednaa Jun 21, 2024
948ad86
feat: update ackee audit
reednaa Jun 24, 2024
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: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ mumbai=
sepolia=
basesepolia=
arbitrumsepolia=
optimismsepolia=
optimismsepolia=
basttestnet=
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ out/
lcov.info

# Ignores development broadcast logs
!/broadcast
broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/

Expand Down
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@
[submodule "lib/vibc-core-smart-contracts"]
path = lib/vibc-core-smart-contracts
url = https://github.com/open-ibc/vibc-core-smart-contracts
[submodule "lib/LayerZero-v2"]
path = lib/LayerZero-v2
url = https://github.com/LayerZero-Labs/LayerZero-v2
[submodule "lib/solidity-bytes-utils"]
path = lib/solidity-bytes-utils
url = https://github.com/GNSPS/solidity-bytes-utils
Binary file not shown.
1 change: 1 addition & 0 deletions lib/LayerZero-v2
Submodule LayerZero-v2 added at 3fd23f
1 change: 1 addition & 0 deletions lib/solidity-bytes-utils
Submodule solidity-bytes-utils added at e0115c
6 changes: 5 additions & 1 deletion remappings.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
forge-std/=lib/forge-std/src/
openzeppelin/=lib/openzeppelin-contracts/contracts/
vibc-core-smart-contracts/=lib/vibc-core-smart-contracts/contracts/
vibc-core-smart-contracts/=lib/vibc-core-smart-contracts/contracts/
@openzeppelin/=lib/openzeppelin-contracts/
@layerzerolabs/lz-evm-protocol-v2/=lib/LayerZero-v2/protocol/

solidity-bytes-utils/=lib/solidity-bytes-utils/
27 changes: 23 additions & 4 deletions script/Deploy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { BaseMultiChainDeployer} from "./BaseMultiChainDeployer.s.sol";
import { IncentivizedMockEscrow } from "../src/apps/mock/IncentivizedMockEscrow.sol";
import { IncentivizedWormholeEscrow } from "../src/apps/wormhole/IncentivizedWormholeEscrow.sol";
import { IncentivizedPolymerEscrow } from "../src/apps/polymer/vIBCEscrow.sol";
import { IncentivizedLayerZeroEscrow } from "../src/apps/layerzero/IncentivizedLayerZeroEscrow.sol";

contract DeployGeneralisedIncentives is BaseMultiChainDeployer {
using stdJson for string;
Expand All @@ -29,6 +30,7 @@ contract DeployGeneralisedIncentives is BaseMultiChainDeployer {
// define a list of AMB mappings so we can get their addresses.
mapping(string => mapping(string => address)) bridgeContract;


constructor() {
// Here we can define input salts. These are always assumed to be dependent on the secondary argument
// to an AMB. (as the first should be send lost gas to which is fixed.)
Expand Down Expand Up @@ -93,6 +95,24 @@ contract DeployGeneralisedIncentives is BaseMultiChainDeployer {
IncentivizedPolymerEscrow polymerEscrow = new IncentivizedPolymerEscrow{salt: salt}(vm.envAddress("SEND_LOST_GAS_TO"), polymerBridgeContract);

incentive = address(polymerEscrow);

} else if (versionHash == keccak256(abi.encodePacked("LayerZero"))) {
address layerZeroBridgeContract = bridgeContract[version][currentChainKey];
bytes32 salt = deploySalts[layerZeroBridgeContract];
require(layerZeroBridgeContract != address(0), "bridge cannot be address(0)");

address expectedAddress = _getAddress(
abi.encodePacked(
type(IncentivizedLayerZeroEscrow).creationCode,
abi.encode(vm.envAddress("SEND_LOST_GAS_TO"), layerZeroBridgeContract)
),
salt
);

if (expectedAddress.codehash != bytes32(0)) return expectedAddress;

IncentivizedLayerZeroEscrow layerZeroEscrow = new IncentivizedLayerZeroEscrow{salt: salt}(vm.envAddress("SEND_LOST_GAS_TO"), layerZeroBridgeContract);
incentive = address(layerZeroEscrow);
} else {
revert IncentivesVersionNotFound();
}
Expand All @@ -106,8 +126,7 @@ contract DeployGeneralisedIncentives is BaseMultiChainDeployer {
return incentive;
}

modifier load_config() {

modifier load_config() {
string memory pathRoot = vm.projectRoot();
pathToAmbConfig = string.concat(pathRoot, "/script/bridge_contracts.json");

Expand All @@ -119,11 +138,11 @@ contract DeployGeneralisedIncentives is BaseMultiChainDeployer {
// For each bridge, decode their contracts for each chain.
for (uint256 i = 0; i < availableBridges.length; ++i) {
string memory bridge = availableBridges[i];
// Get the chains this bridge support.
// Get the chains this bridge supports.
string[] memory availableBridgesChains = vm.parseJsonKeys(bridge_config, string.concat(".", bridge));
for (uint256 j = 0; j < availableBridgesChains.length; ++j) {
string memory chain = availableBridgesChains[j];
// decode the address
// Decode the address
address _bridgeContract = vm.parseJsonAddress(bridge_config, string.concat(".", bridge, ".", chain, ".bridge"));
bridgeContract[bridge][chain] = _bridgeContract;
}
Expand Down
50 changes: 50 additions & 0 deletions script/SimpleApplication.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

import { ICrossChainReceiver } from "../src/interfaces/ICrossChainReceiver.sol";
import { IIncentivizedMessageEscrow } from "../src/interfaces/IIncentivizedMessageEscrow.sol";

/**
* @title Example application contract
*/
contract SimpleApplication is ICrossChainReceiver {

event Event(bytes message);

IIncentivizedMessageEscrow immutable MESSAGE_ESCROW;

constructor(address messageEscrow_) {
MESSAGE_ESCROW = IIncentivizedMessageEscrow(messageEscrow_);
}

function submitMessage(
bytes32 destinationIdentifier,
bytes calldata destinationAddress,
bytes calldata message,
IIncentivizedMessageEscrow.IncentiveDescription calldata incentive,
uint64 deadline
) external payable returns(uint256 gasRefund, bytes32 messageIdentifier) {
(gasRefund, messageIdentifier) = MESSAGE_ESCROW.submitMessage{value: msg.value}(
destinationIdentifier,
destinationAddress,
message,
incentive,
deadline
);
}

function setRemoteImplementation(bytes32 destinationIdentifier, bytes calldata implementation) external {
MESSAGE_ESCROW.setRemoteImplementation(destinationIdentifier, implementation);
}

function receiveAck(bytes32 /* destinationIdentifier */, bytes32 /* messageIdentifier */, bytes calldata acknowledgement) external {
emit Event(acknowledgement);
}

function receiveMessage(bytes32 /* sourceIdentifierbytes */, bytes32 /* messageIdentifier */, bytes calldata /* fromApplication */, bytes calldata message) external returns(bytes calldata acknowledgement) {
emit Event(message);
return message;
}

receive() external payable {}
}
45 changes: 45 additions & 0 deletions script/SubmitMessage.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

import "forge-std/Script.sol";
import {stdJson} from "forge-std/StdJson.sol";

import { BaseMultiChainDeployer} from "./BaseMultiChainDeployer.s.sol";

// Import all the Apps for deployment here.
import { IMessageEscrowStructs } from "../src/interfaces/IMessageEscrowStructs.sol";
import { IIncentivizedMessageEscrow } from "../src/interfaces/IIncentivizedMessageEscrow.sol";

import { SimpleApplication } from "./SimpleApplication.sol";

contract SubmitMessage is BaseMultiChainDeployer {
function submitMessage(address app, bytes32 destinationIdentifier, bytes memory destinationAddress, string memory message, address refundGasTo) external broadcast {
IMessageEscrowStructs.IncentiveDescription memory incentive = IMessageEscrowStructs.IncentiveDescription({
maxGasDelivery: 200000,
maxGasAck: 200000,
refundGasTo: refundGasTo,
priceOfDeliveryGas: 1 gwei,
priceOfAckGas: 1 gwei,
targetDelta: 0
});

uint256 incentiveValue = 200000 * 1 gwei * 2;

SimpleApplication(payable(app)).submitMessage{value: 2807712706467 + incentiveValue}(
destinationIdentifier,
destinationAddress,
abi.encodePacked(message),
incentive,
0
);
}

function setRemoteImplementation(address app, bytes32 destinationIdentifier, bytes calldata implementation) broadcast external {
SimpleApplication(payable(app)).setRemoteImplementation(destinationIdentifier, implementation);
}

function deploySimpleApplication(string[] memory chains, address escrow) iter_chains_string(chains) broadcast external returns(address app) {
app = address(new SimpleApplication{salt: bytes32(0)}(escrow));
}
}

10 changes: 10 additions & 0 deletions script/bridge_contracts.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,15 @@
"bridge": "0xE2029629f51ab994210d671Dc08b7Ec94899b278",
"escrow": "0x87AE7bC6B565E545bDD51788C43BF9E5cbB72EBD"
}
},
"LayerZero": {
"basesepolia": {
"bridge": "0x6EDCE65403992e310A62460808c4b910D972f10f",
"escrow": "0xDb93559e30F5A3845438DDcf7Ca8A2D6D9005d30"
},
"optimismsepolia": {
"bridge": "0x6EDCE65403992e310A62460808c4b910D972f10f",
"escrow": "0xDb93559e30F5A3845438DDcf7Ca8A2D6D9005d30"
}
}
}
126 changes: 126 additions & 0 deletions script/layerzero/InitConfig.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

import "forge-std/Script.sol";
import {stdJson} from "forge-std/StdJson.sol";

import { BaseMultiChainDeployer} from "../BaseMultiChainDeployer.s.sol";

import { IncentivizedLayerZeroEscrow } from "../../src/apps/layerzero/IncentivizedLayerZeroEscrow.sol";

import { ILayerZeroEndpointV2 } from "LayerZero-v2/protocol/contracts/interfaces/ILayerZeroEndpointV2.sol";

contract InitConfigLayerZero is BaseMultiChainDeployer {
using stdJson for string;

error IncentivesNotFound();

string bridge_config;

bytes32 constant KECCACK_OF_NOTHING = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

// define a list of AMB mappings so we can get their addresses.
mapping(string => address) escrow;
mapping(string => uint32 eid) chainEid;

function _setInitConfig(string[] memory counterPartyChains) internal {
IncentivizedLayerZeroEscrow lzescrow = IncentivizedLayerZeroEscrow(payable(escrow[currentChainKey]));
ILayerZeroEndpointV2 endpoint = ILayerZeroEndpointV2(lzescrow.ENDPOINT());
endpoint.eid();

// Get all eids.
uint32[] memory remoteEids = getEids(counterPartyChains);

// Get 1 example of the send library.
address sendLibrary = endpoint.getSendLibrary(address(lzescrow), remoteEids[0]);

lzescrow.initConfig(sendLibrary, remoteEids);
}

function _initConfig(string[] memory chains, string[] memory counterPartyChains) iter_chains_string(chains) broadcast internal {
_setInitConfig(counterPartyChains);
}

function _loadEids(string[] memory chains) iter_chains_string(chains) internal {
IncentivizedLayerZeroEscrow lzescrow = IncentivizedLayerZeroEscrow(payable(escrow[currentChainKey]));
ILayerZeroEndpointV2 endpoint = ILayerZeroEndpointV2(lzescrow.ENDPOINT());
chainEid[currentChainKey] = endpoint.eid();
}

function _loadAllEids(string[] memory chains, string[] memory counterPartyChains) internal {
_loadEids(combineString(chains, counterPartyChains));
}

function initConfig(string[] memory chains, string[] memory counterPartyChains) load_config external {
_loadAllEids(chains, counterPartyChains);
_initConfig(chains, counterPartyChains);
}

//-- Helpers --//
function getEids(string[] memory chains) public view returns(uint32[] memory eids) {
eids = new uint32[](chains.length);
for (uint256 i = 0; i < chains.length; ++i) {
eids[i] = chainEid[chains[i]];
}
}

function combineString(string[] memory a, string[] memory b) public pure returns (string[] memory all_chains) {
all_chains = new string[](a.length + b.length);
uint256 i = 0;
for (i = 0; i < a.length; ++i) {
all_chains[i] = a[i];
}
uint256 j = 0;
for (uint256 p = 0; p < b.length; ++p) {
string memory selected = b[p];
bool found = false;
for (uint256 q = 0; q < a.length; ++q) {
if (keccak256(abi.encode(a[q])) == keccak256(abi.encode(selected))) {
found = true;
break;
}
}
if (!found) {
all_chains[i+j] = selected;
++j;
}
}
string[] memory all_chains_copy = all_chains;
all_chains = new string[](i+j);
for (i = 0; i < all_chains.length; ++i) {
all_chains[i] = all_chains_copy[i];
}
}

function filter(string[] memory a, string memory val) public pure returns(string[] memory filtered) {
filtered = new string[](a.length - 1);
uint256 j = 0;
for (uint256 i = 0; i < a.length; ++i) {
string memory currentElement = a[i];
if (keccak256(abi.encodePacked(val)) == keccak256(abi.encodePacked(currentElement))) continue;
filtered[j] = currentElement;
++j;
}
require(j == a.length - 1, "Invalid Index"); // May be because val is replicated in a.
}

modifier load_config() {
string memory pathRoot = vm.projectRoot();
string memory pathToAmbConfig = string.concat(pathRoot, "/script/bridge_contracts.json");

bridge_config = vm.readFile(pathToAmbConfig);

string memory bridge = "LayerZero";
// Get the chains this bridge supports.
string[] memory availableBridgesChains = vm.parseJsonKeys(bridge_config, string.concat(".", bridge));
for (uint256 j = 0; j < availableBridgesChains.length; ++j) {
string memory chain = availableBridgesChains[j];
// Decode the address
address escrowContract = vm.parseJsonAddress(bridge_config, string.concat(".", bridge, ".", chain, ".escrow"));
escrow[chain] = escrowContract;
}

_;
}
}

20 changes: 20 additions & 0 deletions script/layerzero/LzTryExecute.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.22;

import "forge-std/Script.sol";
import {stdJson} from "forge-std/StdJson.sol";

import { BaseMultiChainDeployer} from "../BaseMultiChainDeployer.s.sol";

import { IncentivizedLayerZeroEscrow } from "../../src/apps/layerzero/IncentivizedLayerZeroEscrow.sol";

contract LZProcessMessage is BaseMultiChainDeployer {
function processMessage(
address escrow,
bytes calldata rawMessage,
bytes32 feeRecipient
) external broadcast {
IncentivizedLayerZeroEscrow(payable(escrow)).processPacket{value: 2806592784579}(hex"", rawMessage, feeRecipient);
}
}

Loading
Loading