From abe0643f7b0cb03a6c5a99b8944185eac636171f Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Mon, 23 Oct 2023 20:30:36 +0800 Subject: [PATCH 1/5] support arb<>mantle usdt --- helix-contract/address/ln-product.json | 14 +++++++++++++- helix-contract/deploy/deploy_ln_create2.js | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/helix-contract/address/ln-product.json b/helix-contract/address/ln-product.json index 5124de28..e65c0859 100644 --- a/helix-contract/address/ln-product.json +++ b/helix-contract/address/ln-product.json @@ -4,7 +4,11 @@ "Eth2ArbSendService": "0x78a6831Da2293fbEFd0d8aFB4D1f7CBB751e0119" }, "arbitrum": { - "Eth2ArbReceiveService": "0xc95D939Da72ECe8Bd794d42EaEd28974CDb0ADa2" + "Eth2ArbReceiveService": "0xc95D939Da72ECe8Bd794d42EaEd28974CDb0ADa2", + "layerzeroMessager": "0x509354A4ebf98aCC7a65d2264694A65a2938cac9" + }, + "mantle": { + "layerzeroMessager": "0x61B6B8c7C00aA7F060a2BEDeE6b11927CC9c3eF1" } }, "ProxyAdmin": { @@ -26,5 +30,13 @@ "ring": { "arbitrum": "0x9e523234D36973f9e38642886197D023C88e307e", "ethereum": "0x9469D013805bFfB7D3DEBe5E7839237e535ec483" + }, + "usdt": { + "arbitrum": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", + "mantle": "0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE" + }, + "usdc": { + "arbitrum": "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", + "mantle": "0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9" } } diff --git a/helix-contract/deploy/deploy_ln_create2.js b/helix-contract/deploy/deploy_ln_create2.js index 0506242d..3064121e 100644 --- a/helix-contract/deploy/deploy_ln_create2.js +++ b/helix-contract/deploy/deploy_ln_create2.js @@ -35,6 +35,7 @@ async function main() { //await deployCreate2Deployer('https://rpc.testnet.mantle.xyz', 'v1.0.0'); //await deployCreate2Deployer('https://rpc.goerli.linea.build', 'v1.0.0'); //await deployCreate2Deployer('https://arb1.arbitrum.io/rpc', 'v1.0.0'); + await deployCreate2Deployer('https://rpc.mantle.xyz', 'v1.0.0'); } main() From 552f92e56a143b5ce6e214ca873427f6e3784f71 Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Tue, 31 Oct 2023 17:22:53 +0800 Subject: [PATCH 2/5] deploy polygon & zkSync mainnet --- helix-contract/address/ln-product.json | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/helix-contract/address/ln-product.json b/helix-contract/address/ln-product.json index e65c0859..e304d3c9 100644 --- a/helix-contract/address/ln-product.json +++ b/helix-contract/address/ln-product.json @@ -5,14 +5,21 @@ }, "arbitrum": { "Eth2ArbReceiveService": "0xc95D939Da72ECe8Bd794d42EaEd28974CDb0ADa2", - "layerzeroMessager": "0x509354A4ebf98aCC7a65d2264694A65a2938cac9" + "LayerZeroMessager": "0x509354A4ebf98aCC7a65d2264694A65a2938cac9" + }, + "polygon": { + "LayerZeroMessager": "0x463D1730a8527CA58d48EF70C7460B9920346567" + }, + "zkSync": { + "LayerZeroMessager": "0x96892F3EaD26515592Da38432cFABad991BBd69d" }, "mantle": { - "layerzeroMessager": "0x61B6B8c7C00aA7F060a2BEDeE6b11927CC9c3eF1" + "LayerZeroMessager": "0x61B6B8c7C00aA7F060a2BEDeE6b11927CC9c3eF1" } }, "ProxyAdmin": { - "common": "0x601dE3B81c7cE04BecE3b29e5cEe4F3251d250dB" + "common": "0x601dE3B81c7cE04BecE3b29e5cEe4F3251d250dB", + "zkSync": "0xA0d8a3C04580a8503ed3Ff30deBb22B83EE615F4" }, "LnOppositeBridgeLogic": { "common": "0x90873fa1bbd028F22277567530A22E05f7721D37" @@ -21,19 +28,23 @@ "common": "0x48d769d5C7ff75703cDd1543A1a2ed9bC9044A23" }, "LnDefaultBridgeLogic": { - "common": "0x8af688056c6614acb5A78c62e1f9f49022C0452f" + "common": "0x8af688056c6614acb5A78c62e1f9f49022C0452f", + "zkSync": "0xefD0DE72e407A55E9b624A91E6d5D6A0CE8490D1" }, "LnDefaultBridgeProxy": { - "common": "0x94C614DAeFDbf151E1BB53d6A201ae5fF56A9337" + "common": "0x94C614DAeFDbf151E1BB53d6A201ae5fF56A9337", + "zkSync": "0x767Bc046c989f5e63683fB530f939DD34b91ceAC" }, "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3", "ring": { "arbitrum": "0x9e523234D36973f9e38642886197D023C88e307e", - "ethereum": "0x9469D013805bFfB7D3DEBe5E7839237e535ec483" + "ethereum": "0x9469D013805bFfB7D3DEBe5E7839237e535ec483", + "polygon": "0x9C1C23E60B72Bc88a043bf64aFdb16A02540Ae8f" }, "usdt": { "arbitrum": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", - "mantle": "0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE" + "mantle": "0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE", + "zkSync": "0x493257fD37EDB34451f62EDf8D2a0C418852bA4C" }, "usdc": { "arbitrum": "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", From dd4c9574242eecf80c97bd5913eaeed31459a167 Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Wed, 1 Nov 2023 22:00:47 +0800 Subject: [PATCH 3/5] support scroll testnet --- helix-contract/address/ln-dev.json | 22 ++- .../ln/messager/Eth2ScrollReceiveService.sol | 44 +++++ .../ln/messager/Eth2ScrollSendService.sol | 62 +++++++ .../messager/interface/IScrollMessenger.sol | 12 ++ helix-contract/deploy/deploy_ln_logic.js | 12 +- helix-contract/deploy/deploy_ln_messager.js | 27 ++++ helix-contract/deploy/deploy_ln_proxy.js | 14 +- helix-contract/deploy/deploy_ln_test_token.js | 37 ++++- helix-contract/deploy/flatten-ln.sh | 2 + .../flatten/lnv2/Eth2ScrollReceiveService.sol | 133 +++++++++++++++ .../flatten/lnv2/Eth2ScrollSendService.sol | 152 ++++++++++++++++++ 11 files changed, 512 insertions(+), 5 deletions(-) create mode 100644 helix-contract/contracts/ln/messager/Eth2ScrollReceiveService.sol create mode 100644 helix-contract/contracts/ln/messager/Eth2ScrollSendService.sol create mode 100644 helix-contract/contracts/ln/messager/interface/IScrollMessenger.sol create mode 100644 helix-contract/flatten/lnv2/Eth2ScrollReceiveService.sol create mode 100644 helix-contract/flatten/lnv2/Eth2ScrollSendService.sol diff --git a/helix-contract/address/ln-dev.json b/helix-contract/address/ln-dev.json index 16a9e259..6b46f43a 100644 --- a/helix-contract/address/ln-dev.json +++ b/helix-contract/address/ln-dev.json @@ -10,6 +10,9 @@ "axelarMessager": "0x037c7b64c80251Cf5C64Ed8f731c799Dc1856701", "debugMessager": "0x2e8D237226041FAFe3F66b6cfc54b064923D454E" }, + "sepolia": { + "Eth2ScrollSendService": "0x89AF830781A2C1d3580Db930bea11094F55AfEae" + }, "arbitrum-goerli": { "Eth2ArbReceiveService": "0x102F8D7Cfe692AA79c17E3958aB00D060Df0B88f", "layerzeroMessager": "0x953bE65E685099277F1f09Ebe10746810dC0593D", @@ -26,6 +29,15 @@ "layerzeroMessager": "0xBE4a32f37d11e8227444837DFb3c634d189ccEDc", "axelarMessager": "0xbb593913a4f3E4eE77861f743c697A4cb95837eF", "debugMessager": "0x84f7a56483C100ECb12CbB4A31b7873dAE0d8E9B" + }, + "crab": { + "darwiniaMsglineMessager": "0x1701cEFBb824a107Ce51b3dF87349806A370F7d1" + }, + "arbitrum-sepolia": { + "darwiniaMsglineMessager": "0xCddD3e43dA1e9485d4FcD3782DFba04aADCfC9B2" + }, + "scroll-sepolia": { + "Eth2ScrollReceiveService": "0x9bc1C7567DDBcaF2212185b6665D755d842d01E4" } }, "ProxyAdmin": { @@ -48,14 +60,20 @@ "mantle-goerli": "0xDb06D904AC5Bdff3b8E6Ac96AFedd3381d94CFDD", "arbitrum-goerli": "0x543bf1AC41485dc78039b9351563E4Dd13A288cb", "linea-goerli": "0x8f3663930211f3DE17619FEB2eeB44c9c3F44a06", - "zksync-goerli": "0xb5372ed3bb2CbA63e7908066ac10ee94d30eA839" + "zksync-goerli": "0xb5372ed3bb2CbA63e7908066ac10ee94d30eA839", + "sepolia": "0x876A4f6eCF13EEb101F9E75FCeF58f19Ff383eEB", + "scroll-sepolia": "0x9C80EdD342b5D179c3a87946fC1F0963BfcaAa09" }, "usdc": { "goerli": "0xe9784E0d9A939dbe966b021DE3cd877284DB1B99", "mantle-goerli": "0xD610DE267f7590D5bCCE89489ECd2C1A4AfdF76B", "arbitrum-goerli": "0xBAD026e314a77e727dF643B02f63adA573a3757c", "linea-goerli": "0xeC89AF5FF618bbF667755BE9d63C69F21F1c00C8", - "zksync-goerli": "0xAe60e005C560E869a2bad271e38e3C9D78381aFF" + "zksync-goerli": "0xAe60e005C560E869a2bad271e38e3C9D78381aFF", + "crab": "0x4bA86B5D0F8D2DCB3FC23757cAA6EA71157F74E9", + "arbitrum-sepolia": "0x8A87497488073307E1a17e8A12475a94Afcb413f", + "sepolia": "0x0ac58Df0cc3542beC4cDa71B16D06C3cCc39f405", + "scroll-sepolia": "0x8A87497488073307E1a17e8A12475a94Afcb413f" }, "keyTool": { "goerli": "0xCD45731FFF1b250e9433A1F1F5A609F3A19557A5" diff --git a/helix-contract/contracts/ln/messager/Eth2ScrollReceiveService.sol b/helix-contract/contracts/ln/messager/Eth2ScrollReceiveService.sol new file mode 100644 index 00000000..2cbbf5e2 --- /dev/null +++ b/helix-contract/contracts/ln/messager/Eth2ScrollReceiveService.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +import "./interface/IScrollMessenger.sol"; +import "../base/LnAccessController.sol"; +import "../interface/ILowLevelMessager.sol"; + +// from ethereum to arbitrum messager +contract Eth2ScrollReceiveService is ILowLevelMessageReceiver, LnAccessController { + uint256 immutable public REMOTE_CHAINID; + address immutable public scrollMessager; + address public remoteMessager; + + mapping(address=>address) public appPairs; + + modifier onlyRemoteBridge() { + require(msg.sender == scrollMessager, "invalid caller"); + require(remoteMessager == IScrollMessenger(scrollMessager).xDomainMessageSender(), "invalid remote caller"); + _; + } + + constructor(address _dao, address _scrollMessager, uint256 _remoteChainId) { + _initialize(_dao); + REMOTE_CHAINID = _remoteChainId; + scrollMessager = _scrollMessager; + } + + function setRemoteMessager(address _remoteMessager) onlyDao external { + remoteMessager = _remoteMessager; + } + + function registerRemoteSender(uint256 _remoteChainId, address _remoteBridge) onlyWhiteListCaller external { + require(_remoteChainId == REMOTE_CHAINID, "invalid remote chainId"); + appPairs[msg.sender] = _remoteBridge; + } + + function recvMessage(address _remoteApp, address _localApp, bytes memory _message) onlyRemoteBridge external { + address remoteAppAddress = appPairs[_localApp]; + require(remoteAppAddress == _remoteApp, "invalid remote app"); + (bool result,) = _localApp.call(_message); + require(result == true, "local call failed"); + } +} + diff --git a/helix-contract/contracts/ln/messager/Eth2ScrollSendService.sol b/helix-contract/contracts/ln/messager/Eth2ScrollSendService.sol new file mode 100644 index 00000000..1f437568 --- /dev/null +++ b/helix-contract/contracts/ln/messager/Eth2ScrollSendService.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +import "./interface/IScrollMessenger.sol"; +import "../base/LnAccessController.sol"; +import "../interface/ILowLevelMessager.sol"; + +contract Eth2ScrollSendService is ILowLevelMessageSender, LnAccessController { + uint256 immutable public REMOTE_CHAINID; + IScrollMessenger immutable public scrollMessager; + address public remoteMessager; + mapping(address=>address) public appPairs; + + constructor(address _dao, address _scrollMessager, uint256 _remoteChainId) { + _initialize(_dao); + scrollMessager = IScrollMessenger(_scrollMessager); + REMOTE_CHAINID = _remoteChainId; + } + + function setRemoteMessager(address _remoteMessager) onlyDao external { + remoteMessager = _remoteMessager; + } + + function registerRemoteReceiver(uint256 _remoteChainId, address _remoteBridge) onlyWhiteListCaller external { + require(_remoteChainId == REMOTE_CHAINID, "invalid remote chainId"); + appPairs[msg.sender] = _remoteBridge; + } + + function sendMessage(uint256 _remoteChainId, bytes memory _message, bytes memory _params) onlyWhiteListCaller external payable { + require(_remoteChainId == REMOTE_CHAINID, "invalid remote chainId"); + address remoteAppAddress = appPairs[msg.sender]; + require(remoteAppAddress != address(0), "app not registered"); + + (uint256 l2GasLimit, address refunder) = abi.decode(_params, (uint256, address)); + + bytes memory remoteReceiveCall = abi.encodeWithSelector( + ILowLevelMessageReceiver.recvMessage.selector, + msg.sender, + remoteAppAddress, + _message + ); + scrollMessager.sendMessage{value: msg.value}( + remoteMessager, + 0, + remoteReceiveCall, + l2GasLimit, + refunder + ); + } + + function fee(uint256 _l2GasLimit) external view returns(uint256) { + address messageQueue = scrollMessager.messageQueue(); + return IL1MessageQueue(messageQueue).estimateCrossDomainMessageFee(_l2GasLimit); + } + + function encodeParams( + uint256 _l2GasLimit, + address _refunder + ) external pure returns(bytes memory) { + return abi.encode(_l2GasLimit, _refunder); + } +} diff --git a/helix-contract/contracts/ln/messager/interface/IScrollMessenger.sol b/helix-contract/contracts/ln/messager/interface/IScrollMessenger.sol new file mode 100644 index 00000000..2d1bec68 --- /dev/null +++ b/helix-contract/contracts/ln/messager/interface/IScrollMessenger.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +interface IScrollMessenger { + function sendMessage(address target, uint256 value, bytes calldata message, uint256 gasLimit, address refundAddress) external payable; + function messageQueue() external view returns (address); + function xDomainMessageSender() external view returns (address); +} + +interface IL1MessageQueue { + function estimateCrossDomainMessageFee(uint256 gasLimit) external view returns(uint256); +} diff --git a/helix-contract/deploy/deploy_ln_logic.js b/helix-contract/deploy/deploy_ln_logic.js index 96be6e5f..cb85e5b7 100644 --- a/helix-contract/deploy/deploy_ln_logic.js +++ b/helix-contract/deploy/deploy_ln_logic.js @@ -26,6 +26,16 @@ const lineaNetwork = { deployer: "0xbe6b2860d3c17a719be0A4911EA0EE689e8357f3", }; +const sepoliaNetwork = { + url: "https://rpc-sepolia.rockx.com", + deployer: "0xbe6b2860d3c17a719be0A4911EA0EE689e8357f3", +} + +const scrollSepoliaNetwork = { + url: "https://sepolia-rpc.scroll.io/", + deployer: "0xbe6b2860d3c17a719be0A4911EA0EE689e8357f3", +} + function wallet(url) { const provider = new ethers.providers.JsonRpcProvider(url); const wallet = new ethers.Wallet(privateKey, provider); @@ -50,7 +60,7 @@ async function deployLnOppositeBridge(wallet, deployerAddress, salt) { // 2. deploy mapping token factory async function main() { - const networks = [goerliNetwork, mantleNetwork, arbitrumNetwork, lineaNetwork]; + const networks = [goerliNetwork, mantleNetwork, arbitrumNetwork, lineaNetwork, sepoliaNetwork, scrollSepoliaNetwork]; for (const network of networks) { const w = wallet(network.url); //const logicAddress = await deployLnDefaultBridge(w, network.deployer, "ln-default-logic-v1.0.0"); diff --git a/helix-contract/deploy/deploy_ln_messager.js b/helix-contract/deploy/deploy_ln_messager.js index daa475e7..a41485a6 100644 --- a/helix-contract/deploy/deploy_ln_messager.js +++ b/helix-contract/deploy/deploy_ln_messager.js @@ -64,6 +64,20 @@ const mantleNetwork = { axName: "mantle", } +const scrollNetwork = { + url: "https://sepolia-rpc.scroll.io/", + dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + chainId: 534351, + scrollMessager: "0xBa50f5340FB9F3Bd074bD638c9BE13eCB36E603d", +} + +const sepoliaNetwork = { + url: "https://rpc2.sepolia.org", + dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + chainId: 11155111, + scrollMessager: "0x50c7d3e7f7c656493D1D76aaa1a836CedfCBB16A", +} + function wait(ms) { return new Promise(resolve => setTimeout(() => resolve(), ms)); }; @@ -89,7 +103,10 @@ async function main() { const goerliWallet = wallet(goerliNetwork.url); const mantleWallet = wallet(mantleNetwork.url); const zkSyncWallet = wallet(zkSyncNetwork.url); + const scrollWallet = wallet(scrollNetwork.url); + const sepoliaWallet = wallet(sepoliaNetwork.url); + /* // deploy arb<>eth console.log("deploy arb <> eth messager"); const Eth2ArbReceiveService = await deployContract(arbWallet, "Eth2ArbReceiveService", arbitrumNetwork.dao, goerliNetwork.chainId); @@ -160,7 +177,17 @@ async function main() { await axArbitrum.setRemoteMessager(mantleNetwork.chainId, mantleNetwork.axName, axMantle.address); await axLinea.setRemoteMessager(mantleNetwork.chainId, mantleNetwork.axName, axMantle.address); await axMantle.setRemoteMessager(lineaNetwork.chainId, lineaNetwork.axName, axLinea.address); + */ + // deploy scroll + console.log("deploy scroll <> eth messager"); + const Eth2ScrollReceiveService = await deployContract(scrollWallet, "Eth2ScrollReceiveService", scrollNetwork.dao, scrollNetwork.scrollMessager, sepoliaNetwork.chainId); + const Eth2ScrollSendService = await deployContract(sepoliaWallet, "Eth2ScrollSendService", sepoliaNetwork.dao, sepoliaNetwork.scrollMessager, scrollNetwork.chainId); + await wait(10000); + await Eth2ScrollReceiveService.setRemoteMessager(Eth2ScrollSendService.address); + await Eth2ScrollSendService.setRemoteMessager(Eth2ScrollReceiveService.address); + await wait(10000); + /* // deploy debug messager await deployContract(goerliWallet, "DebugMessager"); diff --git a/helix-contract/deploy/deploy_ln_proxy.js b/helix-contract/deploy/deploy_ln_proxy.js index 82354bad..020a01bb 100644 --- a/helix-contract/deploy/deploy_ln_proxy.js +++ b/helix-contract/deploy/deploy_ln_proxy.js @@ -31,6 +31,18 @@ const mantleGoerliNetwork = { dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", }; +const sepoliaNetwork = { + name: "sepolia", + url: "https://rpc-sepolia.rockx.com", + dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", +}; + +const scrollSepoliaNetwork = { + name: "scroll-sepolia", + url: "https://sepolia-rpc.scroll.io/", + dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", +}; + function wallet(url) { const provider = new ethers.providers.JsonRpcProvider(url); const wallet = new ethers.Wallet(privateKey, provider); @@ -72,7 +84,7 @@ async function deploy() { fs.readFileSync(pathConfig, "utf8") ); - const chains = [goerliNetwork, lineaGoerliNetwork, arbitrumGoerliNetwork, mantleGoerliNetwork]; + const chains = [goerliNetwork, lineaGoerliNetwork, arbitrumGoerliNetwork, mantleGoerliNetwork, sepoliaNetwork, scrollSepoliaNetwork]; for (const chain of chains) { const w = wallet(chain.url); const proxyAdmin = configure.ProxyAdmin.others; diff --git a/helix-contract/deploy/deploy_ln_test_token.js b/helix-contract/deploy/deploy_ln_test_token.js index b073dc5b..57d4eb75 100644 --- a/helix-contract/deploy/deploy_ln_test_token.js +++ b/helix-contract/deploy/deploy_ln_test_token.js @@ -68,6 +68,40 @@ const lineaNetwork = { ], }; +const sepoliaNetwork = { + url: "https://rpc-sepolia.rockx.com", + tokens: [ + { + name: "Helix Test Token USDT", + symbol: "USDT", + decimals: 18 + }, + { + name: "Helix Test Token USDC", + symbol: "USDC", + decimals: 18 + }, + ], +}; + +const scrollSepoliaNetwork = { + url: "https://sepolia-rpc.scroll.io/", + tokens: [ + { + name: "Helix Test Token USDT", + symbol: "USDT", + decimals: 18 + }, + { + name: "Helix Test Token USDC", + symbol: "USDC", + decimals: 18 + }, + ], +}; + + + function wallet(url) { const provider = new ethers.providers.JsonRpcProvider(url); const wallet = new ethers.Wallet(privateKey, provider); @@ -76,7 +110,8 @@ function wallet(url) { // 2. deploy mapping token factory async function main() { - const networks = [goerliNetwork, mantleNetwork, arbitrumNetwork, lineaNetwork]; + //const networks = [goerliNetwork, mantleNetwork, arbitrumNetwork, lineaNetwork, sepoliaNetwork, scrollSepoliaNetwork]; + const networks = [sepoliaNetwork, scrollSepoliaNetwork]; for (const network of networks) { const w = wallet(network.url); diff --git a/helix-contract/deploy/flatten-ln.sh b/helix-contract/deploy/flatten-ln.sh index e80169ce..16febbe1 100644 --- a/helix-contract/deploy/flatten-ln.sh +++ b/helix-contract/deploy/flatten-ln.sh @@ -9,5 +9,7 @@ yarn flat contracts/ln/messager/Eth2LineaReceiveService.sol --output $path/Eth2L yarn flat contracts/ln/messager/Eth2ArbSendService.sol --output $path/Eth2ArbSendService.sol yarn flat contracts/ln/messager/Eth2ArbReceiveService.sol --output $path/Eth2ArbReceiveService.sol yarn flat contracts/ln/messager/LayerZeroMessager.sol --output $path/LayerZeroMessager.sol +yarn flat contracts/ln/messager/Eth2ScrollSendService.sol --output $path/Eth2ScrollSendService.sol +yarn flat contracts/ln/messager/Eth2ScrollReceiveService.sol --output $path/Eth2ScrollReceiveService.sol yarn flat contracts/ln/messager/debugMessager.sol --output $path/debugMessager.sol yarn flat contracts/ln/test/TestToken.sol --output $path/TestToken.sol diff --git a/helix-contract/flatten/lnv2/Eth2ScrollReceiveService.sol b/helix-contract/flatten/lnv2/Eth2ScrollReceiveService.sol new file mode 100644 index 00000000..16cddf79 --- /dev/null +++ b/helix-contract/flatten/lnv2/Eth2ScrollReceiveService.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: MIT + +/** + * .----------------. .----------------. .----------------. .----------------. .----------------. + * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | + * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | + * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | + * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | + * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | + * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | + * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | + * | | | || | | || | | || | | || | | | + * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | + * '----------------' '----------------' '----------------' '----------------' '----------------' ' + * + * + * 11/1/2023 + **/ + +pragma solidity ^0.8.17; + +// File contracts/ln/base/LnAccessController.sol +// License-Identifier: MIT + +/// @title LnAccessController +/// @notice LnAccessController is a contract to control the access permission +/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract +contract LnAccessController { + address public dao; + address public operator; + + mapping(address=>bool) public callerWhiteList; + + modifier onlyDao() { + require(msg.sender == dao, "!dao"); + _; + } + + modifier onlyOperator() { + require(msg.sender == operator, "!operator"); + _; + } + + modifier onlyWhiteListCaller() { + require(callerWhiteList[msg.sender], "caller not in white list"); + _; + } + + function _initialize(address _dao) internal { + dao = _dao; + operator = _dao; + } + + function setOperator(address _operator) onlyDao external { + operator = _operator; + } + + function authoriseAppCaller(address appAddress, bool enable) onlyDao external { + callerWhiteList[appAddress] = enable; + } + + function transferOwnership(address _dao) onlyDao external { + dao = _dao; + } +} + +// File contracts/ln/messager/interface/IScrollMessenger.sol +// License-Identifier: MIT + +interface IScrollMessenger { + function sendMessage(address target, uint256 value, bytes calldata message, uint256 gasLimit, address refundAddress) external payable; + function messageQueue() external view returns (address); + function xDomainMessageSender() external view returns (address); +} + +interface IL1MessageQueue { + function estimateCrossDomainMessageFee(uint256 gasLimit) external view returns(uint256); +} + +// File contracts/ln/interface/ILowLevelMessager.sol +// License-Identifier: MIT + +interface ILowLevelMessageSender { + function registerRemoteReceiver(uint256 remoteChainId, address remoteBridge) external; + function sendMessage(uint256 remoteChainId, bytes memory message, bytes memory params) external payable; +} + +interface ILowLevelMessageReceiver { + function registerRemoteSender(uint256 remoteChainId, address remoteBridge) external; + function recvMessage(address remoteSender, address localReceiver, bytes memory payload) external; +} + +// File contracts/ln/messager/Eth2ScrollReceiveService.sol +// License-Identifier: MIT + + + +// from ethereum to arbitrum messager +contract Eth2ScrollReceiveService is ILowLevelMessageReceiver, LnAccessController { + uint256 immutable public REMOTE_CHAINID; + address immutable public scrollMessager; + address public remoteMessager; + + mapping(address=>address) public appPairs; + + modifier onlyRemoteBridge() { + require(msg.sender == scrollMessager, "invalid caller"); + require(remoteMessager == IScrollMessenger(scrollMessager).xDomainMessageSender(), "invalid remote caller"); + _; + } + + constructor(address _dao, address _scrollMessager, uint256 _remoteChainId) { + _initialize(_dao); + REMOTE_CHAINID = _remoteChainId; + scrollMessager = _scrollMessager; + } + + function setRemoteMessager(address _remoteMessager) onlyDao external { + remoteMessager = _remoteMessager; + } + + function registerRemoteSender(uint256 _remoteChainId, address _remoteBridge) onlyWhiteListCaller external { + require(_remoteChainId == REMOTE_CHAINID, "invalid remote chainId"); + appPairs[msg.sender] = _remoteBridge; + } + + function recvMessage(address _remoteApp, address _localApp, bytes memory _message) onlyRemoteBridge external { + address remoteAppAddress = appPairs[_localApp]; + require(remoteAppAddress == _remoteApp, "invalid remote app"); + (bool result,) = _localApp.call(_message); + require(result == true, "local call failed"); + } +} \ No newline at end of file diff --git a/helix-contract/flatten/lnv2/Eth2ScrollSendService.sol b/helix-contract/flatten/lnv2/Eth2ScrollSendService.sol new file mode 100644 index 00000000..76819c24 --- /dev/null +++ b/helix-contract/flatten/lnv2/Eth2ScrollSendService.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: MIT + +/** + * .----------------. .----------------. .----------------. .----------------. .----------------. + * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | + * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | + * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | + * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | + * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | + * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | + * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | + * | | | || | | || | | || | | || | | | + * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | + * '----------------' '----------------' '----------------' '----------------' '----------------' ' + * + * + * 11/1/2023 + **/ + +pragma solidity ^0.8.17; + +// File contracts/ln/interface/ILowLevelMessager.sol +// License-Identifier: MIT + +interface ILowLevelMessageSender { + function registerRemoteReceiver(uint256 remoteChainId, address remoteBridge) external; + function sendMessage(uint256 remoteChainId, bytes memory message, bytes memory params) external payable; +} + +interface ILowLevelMessageReceiver { + function registerRemoteSender(uint256 remoteChainId, address remoteBridge) external; + function recvMessage(address remoteSender, address localReceiver, bytes memory payload) external; +} + +// File contracts/ln/base/LnAccessController.sol +// License-Identifier: MIT + +/// @title LnAccessController +/// @notice LnAccessController is a contract to control the access permission +/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract +contract LnAccessController { + address public dao; + address public operator; + + mapping(address=>bool) public callerWhiteList; + + modifier onlyDao() { + require(msg.sender == dao, "!dao"); + _; + } + + modifier onlyOperator() { + require(msg.sender == operator, "!operator"); + _; + } + + modifier onlyWhiteListCaller() { + require(callerWhiteList[msg.sender], "caller not in white list"); + _; + } + + function _initialize(address _dao) internal { + dao = _dao; + operator = _dao; + } + + function setOperator(address _operator) onlyDao external { + operator = _operator; + } + + function authoriseAppCaller(address appAddress, bool enable) onlyDao external { + callerWhiteList[appAddress] = enable; + } + + function transferOwnership(address _dao) onlyDao external { + dao = _dao; + } +} + +// File contracts/ln/messager/interface/IScrollMessenger.sol +// License-Identifier: MIT + +interface IScrollMessenger { + function sendMessage(address target, uint256 value, bytes calldata message, uint256 gasLimit, address refundAddress) external payable; + function messageQueue() external view returns (address); + function xDomainMessageSender() external view returns (address); +} + +interface IL1MessageQueue { + function estimateCrossDomainMessageFee(uint256 gasLimit) external view returns(uint256); +} + +// File contracts/ln/messager/Eth2ScrollSendService.sol +// License-Identifier: MIT + + + +contract Eth2ScrollSendService is ILowLevelMessageSender, LnAccessController { + uint256 immutable public REMOTE_CHAINID; + IScrollMessenger immutable public scrollMessager; + address public remoteMessager; + mapping(address=>address) public appPairs; + + constructor(address _dao, address _scrollMessager, uint256 _remoteChainId) { + _initialize(_dao); + scrollMessager = IScrollMessenger(_scrollMessager); + REMOTE_CHAINID = _remoteChainId; + } + + function setRemoteMessager(address _remoteMessager) onlyDao external { + remoteMessager = _remoteMessager; + } + + function registerRemoteReceiver(uint256 _remoteChainId, address _remoteBridge) onlyWhiteListCaller external { + require(_remoteChainId == REMOTE_CHAINID, "invalid remote chainId"); + appPairs[msg.sender] = _remoteBridge; + } + + function sendMessage(uint256 _remoteChainId, bytes memory _message, bytes memory _params) onlyWhiteListCaller external payable { + require(_remoteChainId == REMOTE_CHAINID, "invalid remote chainId"); + address remoteAppAddress = appPairs[msg.sender]; + require(remoteAppAddress != address(0), "app not registered"); + + (uint256 l2GasLimit, address refunder) = abi.decode(_params, (uint256, address)); + + bytes memory remoteReceiveCall = abi.encodeWithSelector( + ILowLevelMessageReceiver.recvMessage.selector, + msg.sender, + remoteAppAddress, + _message + ); + scrollMessager.sendMessage{value: msg.value}( + remoteMessager, + 0, + remoteReceiveCall, + l2GasLimit, + refunder + ); + } + + function fee(uint256 _l2GasLimit) external view returns(uint256) { + address messageQueue = scrollMessager.messageQueue(); + return IL1MessageQueue(messageQueue).estimateCrossDomainMessageFee(_l2GasLimit); + } + + function encodeParams( + uint256 _l2GasLimit, + address _refunder + ) external pure returns(bytes memory) { + return abi.encode(_l2GasLimit, _refunder); + } +} \ No newline at end of file From d80ff6214be401a3193d52654cb46a4e468183fa Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Wed, 8 Nov 2023 14:45:26 +0800 Subject: [PATCH 4/5] deploy on scroll mainnet --- helix-contract/address/ln-product.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/helix-contract/address/ln-product.json b/helix-contract/address/ln-product.json index e304d3c9..d18cf0cd 100644 --- a/helix-contract/address/ln-product.json +++ b/helix-contract/address/ln-product.json @@ -15,6 +15,9 @@ }, "mantle": { "LayerZeroMessager": "0x61B6B8c7C00aA7F060a2BEDeE6b11927CC9c3eF1" + }, + "scroll": { + "LayerZeroMessager": "0x463d1730a8527ca58d48ef70c7460b9920346567" } }, "ProxyAdmin": { @@ -44,7 +47,8 @@ "usdt": { "arbitrum": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", "mantle": "0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE", - "zkSync": "0x493257fD37EDB34451f62EDf8D2a0C418852bA4C" + "zkSync": "0x493257fD37EDB34451f62EDf8D2a0C418852bA4C", + "scroll": "0xf55BEC9cafDbE8730f096Aa55dad6D22d44099Df" }, "usdc": { "arbitrum": "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", From 4a1af8ae9555a437814553788177a3e21625bf69 Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Sun, 12 Nov 2023 18:10:30 +0800 Subject: [PATCH 5/5] testnet base address --- helix-contract/address/ln-dev.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/helix-contract/address/ln-dev.json b/helix-contract/address/ln-dev.json index 16a9e259..71a83d18 100644 --- a/helix-contract/address/ln-dev.json +++ b/helix-contract/address/ln-dev.json @@ -26,6 +26,9 @@ "layerzeroMessager": "0xBE4a32f37d11e8227444837DFb3c634d189ccEDc", "axelarMessager": "0xbb593913a4f3E4eE77861f743c697A4cb95837eF", "debugMessager": "0x84f7a56483C100ECb12CbB4A31b7873dAE0d8E9B" + }, + "base-goerli": { + "layerzeroMessager": "0x463D1730a8527CA58d48EF70C7460B9920346567" } }, "ProxyAdmin": { @@ -48,7 +51,8 @@ "mantle-goerli": "0xDb06D904AC5Bdff3b8E6Ac96AFedd3381d94CFDD", "arbitrum-goerli": "0x543bf1AC41485dc78039b9351563E4Dd13A288cb", "linea-goerli": "0x8f3663930211f3DE17619FEB2eeB44c9c3F44a06", - "zksync-goerli": "0xb5372ed3bb2CbA63e7908066ac10ee94d30eA839" + "zksync-goerli": "0xb5372ed3bb2CbA63e7908066ac10ee94d30eA839", + "base-goerli": "0x876A4f6eCF13EEb101F9E75FCeF58f19Ff383eEB" }, "usdc": { "goerli": "0xe9784E0d9A939dbe966b021DE3cd877284DB1B99",