From af8b5726c831a3bd90ca1418a91683eb135b86b6 Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Thu, 1 Feb 2024 17:25:29 +0800 Subject: [PATCH 1/4] add chain info --- helix-contract/address/ln-product.json | 54 ++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/helix-contract/address/ln-product.json b/helix-contract/address/ln-product.json index 5060a32..a7e1854 100644 --- a/helix-contract/address/ln-product.json +++ b/helix-contract/address/ln-product.json @@ -26,6 +26,60 @@ "lzChainId": 102, "lzEndpoint": "0x3c2269811836af69497E5F486A85D7316753cf62", "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" + }, + "linea": { + "name": "linea", + "url": "https://rpc.linea.build", + "dao": "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + "chainId": 59144, + "lzChainId": 183, + "lzEndpoint": "0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7", + "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" + }, + "base": { + "name": "base", + "url": "https://mainnet.base.org", + "dao": "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + "chainId": 8453, + "lzChainId": 184, + "lzEndpoint": "0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7", + "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" + }, + "op": { + "name": "op", + "url": "https://mainnet.optimism.io", + "dao": "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + "chainId": 10, + "lzChainId": 111, + "lzEndpoint": "0x3c2269811836af69497E5F486A85D7316753cf62", + "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" + }, + "gnosis": { + "name": "gnosis", + "url": "https://rpc.gnosischain.com", + "dao": "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + "chainId": 100, + "lzChainId": 145, + "lzEndpoint": "0x9740FF91F1985D8d2B71494aE1A2f723bb3Ed9E4", + "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" + }, + "mantle": { + "name": "mantle", + "url": "https://rpc.mantle.xyz", + "dao": "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + "chainId": 5000, + "lzChainId": 181, + "lzEndpoint": "0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7", + "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" + }, + "scroll": { + "name": "scroll", + "url": "https://rpc.scroll.io", + "dao": "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + "chainId": 534352, + "lzChainId": 214, + "lzEndpoint": "0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7", + "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" } }, "messagers": { From 1bbce6f865acd6d2aed8a5f32053915c95c75734 Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Wed, 7 Feb 2024 09:48:08 +0800 Subject: [PATCH 2/4] xToken deploy on testnet --- helix-contract/address/ln-dev.json | 10 + helix-contract/address/xtoken-dev.json | 14 +- ...sglineMessager.sol => MsgportMessager.sol} | 42 ++-- helix-contract/deploy/deploy_guardv3.js | 49 +++++ .../deploy/deploy_lnv2_configure.js | 12 +- .../deploy/deploy_msgline_messager.js | 49 ++--- helix-contract/deploy/deploy_xtoken_config.js | 24 +-- helix-contract/deploy/deploy_xtoken_logic.js | 39 ++-- helix-contract/deploy/deploy_xtoken_proxy.js | 47 ++--- helix-contract/deploy/deploy_xtoken_test.js | 54 ++--- helix-contract/deploy/flatten-xtoken.sh | 2 +- helix-contract/deploy/proxy.js | 3 +- helix-contract/flatten/xtoken-v3/GuardV3.sol | 170 +++++++-------- .../flatten/xtoken-v3/MsgportMessager.sol | 198 ++++++++++++++++++ .../flatten/xtoken-v3/xTokenBacking.sol | 48 ++--- .../flatten/xtoken-v3/xTokenErc20.sol | 2 +- .../flatten/xtoken-v3/xTokenIssuing.sol | 92 ++++---- 17 files changed, 543 insertions(+), 312 deletions(-) rename helix-contract/contracts/messagers/{MsglineMessager.sol => MsgportMessager.sol} (77%) create mode 100644 helix-contract/deploy/deploy_guardv3.js create mode 100644 helix-contract/flatten/xtoken-v3/MsgportMessager.sol diff --git a/helix-contract/address/ln-dev.json b/helix-contract/address/ln-dev.json index b492aca..b5236ff 100644 --- a/helix-contract/address/ln-dev.json +++ b/helix-contract/address/ln-dev.json @@ -7,6 +7,7 @@ "chainId": 11155111, "lzChainId": 10161, "lzEndpoint": "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + "ormpPort": "0x0000000005d961F950adA391C1511c92bbc64D9F", "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" }, "arbitrum-sepolia": { @@ -16,6 +17,15 @@ "chainId": 421614, "lzChainId": 10231, "lzEndpoint": "0x6098e96a28E02f27B1e6BD381f870F1C8Bd169d3", + "ormpPort": "0x0000000005d961F950adA391C1511c92bbc64D9F", + "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" + }, + "pangolin": { + "name": "pangolin", + "url": "https://pangolin-rpc.darwinia.network", + "dao": "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + "chainId": 43, + "ormpPort": "0x0000000005d961F950adA391C1511c92bbc64D9F", "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" }, "zksync": { diff --git a/helix-contract/address/xtoken-dev.json b/helix-contract/address/xtoken-dev.json index 520fe86..26329a0 100644 --- a/helix-contract/address/xtoken-dev.json +++ b/helix-contract/address/xtoken-dev.json @@ -1,27 +1,27 @@ { "messagers": { - "crab": { - "msglineMessager": "0xf85638B61E0425D6BB91981190B73246e3AF3CA9" + "pangolin": { + "msgportMessager": "0xf7F461728DC89de5EF6615715678b5f5b12bb98A" }, "sepolia": { - "msglineMessager": "0xc876D0873e4060472334E297b2db200Ca10cc806" + "msgportMessager": "0xf7F461728DC89de5EF6615715678b5f5b12bb98A" }, "tron": { "msglineMessager": "TR3nibHkcXovd1nsuNrLWigQboj4uduhKT" } }, "backingProxy": { - "crab": "0xbdC7bbF408931C5d666b4F0520E0D9E9A0B04e99" + "pangolin": "0x94eAb0CB67AB7edaf9A280aCa097F70e4BD780ac" }, "backingLogic": { - "crab": "0x01F53415adC20a2D058DfF14e295Ab955CafD6d6" + "pangolin": "0x1315f7050c66ceBE66983D8981007A1347830310" }, "issuingProxy": { - "sepolia": "0xf22D0bb66b39745Ae6e3fEa3E5859d7f0b367Fd1", + "sepolia": "0x371019523b25Ff4F26d977724f976566b08bf741", "tron": "TJK57bJTvnaNRGFHwbihg1bXtgnyed6sKa" }, "issuingLogic": { - "sepolia": "0xCD1c1C799f3914ECFC5e3653D3Cc846355d3dFC9", + "sepolia": "0x277d44E8E30cE978F742339C0B8ce22847a0fc00", "tron": "TD7VoAQnJDKsWsgZZTeeHvBKY5fogRDVc2" }, "proxyAdmin": { diff --git a/helix-contract/contracts/messagers/MsglineMessager.sol b/helix-contract/contracts/messagers/MsgportMessager.sol similarity index 77% rename from helix-contract/contracts/messagers/MsglineMessager.sol rename to helix-contract/contracts/messagers/MsgportMessager.sol index ab56d18..931840c 100644 --- a/helix-contract/contracts/messagers/MsglineMessager.sol +++ b/helix-contract/contracts/messagers/MsgportMessager.sol @@ -4,20 +4,20 @@ pragma solidity ^0.8.17; import "../utils/AccessController.sol"; import "../interfaces/IMessageLine.sol"; -contract MsglineMessager is Application, AccessController { - IMessageLine public msgline; +contract MsgportMessager is Application, AccessController { + IMessageLine public msgport; struct RemoteMessager { - uint256 msglineRemoteChainId; + uint256 msgportRemoteChainId; address messager; } mapping(address=>bool) public whiteList; - // app remoteChainId => msgline remote messager + // app remoteChainId => msgport remote messager mapping(uint256=>RemoteMessager) public remoteMessagers; // token bridge pair - // hash(msglineRemoteChainId, localAppAddress) => remoteAppAddress + // hash(msgportRemoteChainId, localAppAddress) => remoteAppAddress mapping(bytes32=>address) public remoteAppReceivers; mapping(bytes32=>address) public remoteAppSenders; @@ -30,21 +30,21 @@ contract MsglineMessager is Application, AccessController { } modifier onlyMsgline() { - require(msg.sender == address(msgline), "invalid caller"); + require(msg.sender == address(msgport), "invalid caller"); _; } - constructor(address _dao, address _msgline) { + constructor(address _dao, address _msgport) { _initialize(_dao); - msgline = IMessageLine(_msgline); + msgport = IMessageLine(_msgport); } - function setMsgline(address _msgline) onlyDao external { - msgline = IMessageLine(_msgline); + function setMsgline(address _msgport) onlyDao external { + msgport = IMessageLine(_msgport); } - function setRemoteMessager(uint256 _appRemoteChainId, uint256 _msglineRemoteChainId, address _remoteMessager) onlyDao external { - remoteMessagers[_appRemoteChainId] = RemoteMessager(_msglineRemoteChainId, _remoteMessager); + function setRemoteMessager(uint256 _appRemoteChainId, uint256 _msgportRemoteChainId, address _remoteMessager) onlyDao external { + remoteMessagers[_appRemoteChainId] = RemoteMessager(_msgportRemoteChainId, _remoteMessager); } function setWhiteList(address _caller, bool _enable) external onlyDao { @@ -54,28 +54,28 @@ contract MsglineMessager is Application, AccessController { function registerRemoteReceiver(uint256 _remoteChainId, address _remoteBridge) onlyWhiteList external { RemoteMessager memory remoteMessager = remoteMessagers[_remoteChainId]; require(remoteMessager.messager != address(0), "remote not configured"); - bytes32 key = keccak256(abi.encodePacked(remoteMessager.msglineRemoteChainId, msg.sender)); + bytes32 key = keccak256(abi.encodePacked(remoteMessager.msgportRemoteChainId, msg.sender)); remoteAppReceivers[key] = _remoteBridge; } function registerRemoteSender(uint256 _remoteChainId, address _remoteBridge) onlyWhiteList external { RemoteMessager memory remoteMessager = remoteMessagers[_remoteChainId]; require(remoteMessager.messager != address(0), "remote not configured"); - bytes32 key = keccak256(abi.encodePacked(remoteMessager.msglineRemoteChainId, msg.sender)); + bytes32 key = keccak256(abi.encodePacked(remoteMessager.msgportRemoteChainId, msg.sender)); remoteAppSenders[key] = _remoteBridge; } function sendMessage(uint256 _remoteChainId, bytes memory _message, bytes memory _params) onlyWhiteList external payable { RemoteMessager memory remoteMessager = remoteMessagers[_remoteChainId]; require(remoteMessager.messager != address(0), "remote not configured"); - bytes32 key = keccak256(abi.encodePacked(remoteMessager.msglineRemoteChainId, msg.sender)); + bytes32 key = keccak256(abi.encodePacked(remoteMessager.msgportRemoteChainId, msg.sender)); address remoteAppAddress = remoteAppReceivers[key]; require(remoteAppAddress != address(0), "app pair not registered"); - bytes memory msglinePayload = messagePayload(msg.sender, remoteAppAddress, _message); - msgline.send{ value: msg.value }( - remoteMessager.msglineRemoteChainId, + bytes memory msgportPayload = messagePayload(msg.sender, remoteAppAddress, _message); + msgport.send{ value: msg.value }( + remoteMessager.msgportRemoteChainId, remoteMessager.messager, - msglinePayload, + msgportPayload, _params ); } @@ -83,7 +83,7 @@ contract MsglineMessager is Application, AccessController { function receiveMessage(uint256 _srcAppChainId, address _remoteAppAddress, address _localAppAddress, bytes memory _message) onlyMsgline external { uint256 srcChainId = _fromChainId(); RemoteMessager memory remoteMessager = remoteMessagers[_srcAppChainId]; - require(srcChainId == remoteMessager.msglineRemoteChainId, "invalid remote chainid"); + require(srcChainId == remoteMessager.msgportRemoteChainId, "invalid remote chainid"); require(remoteMessager.messager == _xmsgSender(), "invalid remote messager"); bytes32 key = keccak256(abi.encodePacked(srcChainId, _localAppAddress)); @@ -99,7 +99,7 @@ contract MsglineMessager is Application, AccessController { function messagePayload(address _from, address _to, bytes memory _message) public view returns(bytes memory) { return abi.encodeWithSelector( - MsglineMessager.receiveMessage.selector, + MsgportMessager.receiveMessage.selector, block.chainid, _from, _to, diff --git a/helix-contract/deploy/deploy_guardv3.js b/helix-contract/deploy/deploy_guardv3.js new file mode 100644 index 0000000..18fa243 --- /dev/null +++ b/helix-contract/deploy/deploy_guardv3.js @@ -0,0 +1,49 @@ +const ethUtil = require('ethereumjs-util'); +const abi = require('ethereumjs-abi'); +const secp256k1 = require('secp256k1'); +const fs = require("fs"); + +var Create2 = require("./create2.js"); + +const privateKey = process.env.PRIKEY + +function wallet(configure, network) { + const provider = new ethers.providers.JsonRpcProvider(network.url); + const wallet = new ethers.Wallet(privateKey, provider); + return wallet; +} + +function chainInfo(configure, network) { + return configure.chains[network]; +} + +async function deployGuardV3(wallet, deployerAddress, salt) { + const guardContract = await ethers.getContractFactory("GuardV3", wallet); + const bytecode = Create2.getDeployedBytecode( + guardContract, + ['address[]','address','uint256','uint256'], + [['0x3B9E571AdeCB0c277486036D6097E9C2CCcfa9d9'],wallet.address,1,259200]); + const address = await Create2.deploy(deployerAddress, wallet, bytecode, salt, 8000000); + console.log("finish to deploy guard contract, address: ", address); + return address; +} + +// 2. deploy mapping token factory +async function main() { + const pathConfig = "./address/ln-dev.json"; + const configure = JSON.parse( + fs.readFileSync(pathConfig, "utf8") + ); + + const network = chainInfo(configure, "sepolia"); + const w = wallet(configure, network); + await deployGuardV3(w, network.deployer, "guardv3-v1.0.0"); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); + diff --git a/helix-contract/deploy/deploy_lnv2_configure.js b/helix-contract/deploy/deploy_lnv2_configure.js index e2b70dd..786b389 100644 --- a/helix-contract/deploy/deploy_lnv2_configure.js +++ b/helix-contract/deploy/deploy_lnv2_configure.js @@ -164,11 +164,11 @@ async function registerToken(configure, contractName, srcWallet, dstWallet, srcN const targetToken = await ethers.getContractAt("Erc20", dstTokenAddress, dstWallet); dstDecimals = await targetToken.decimals(); } - let fee = ethers.utils.parseUnits("100", srcDecimals); + let fee = ethers.utils.parseUnits("0.1", srcDecimals); const penaltyDecimals = contractName == "LnOppositeBridge" ? srcDecimals : dstDecimals; let penalty = ethers.utils.parseUnits("1000", penaltyDecimals); if (srcTokenAddress == kNativeTokenAddress || dstTokenAddress == kNativeTokenAddress) { - fee = ethers.utils.parseUnits("0.001", srcDecimals); + fee = ethers.utils.parseUnits("0.0001", srcDecimals); penalty = ethers.utils.parseUnits("0.01", penaltyDecimals); } @@ -340,8 +340,8 @@ async function main() { fs.readFileSync(pathConfig, "utf8") ); - const network01 = configure.chains['arbitrum-sepolia']; - const network02 = configure.chains['zksync']; + const network01 = configure.chains['zksync']; + const network02 = configure.chains['sepolia']; const wallet01 = wallet(network01.url); const wallet02 = wallet(network02.url); @@ -361,8 +361,8 @@ async function main() { //await approveAll(configure, network01, wallet01); //await approveAll(configure, network02, wallet02); - //await registerAllRelayer(configure, pair, "LnDefaultBridge"); - //await registerAllRelayer(configure, pair, "LnOppositeBridge"); + await registerAllRelayer(configure, pair, "LnDefaultBridge"); + await registerAllRelayer(configure, pair, "LnOppositeBridge"); console.log("finished!"); } diff --git a/helix-contract/deploy/deploy_msgline_messager.js b/helix-contract/deploy/deploy_msgline_messager.js index 140ac62..06cef16 100644 --- a/helix-contract/deploy/deploy_msgline_messager.js +++ b/helix-contract/deploy/deploy_msgline_messager.js @@ -2,51 +2,38 @@ const ethUtil = require('ethereumjs-util'); const abi = require('ethereumjs-abi'); const secp256k1 = require('secp256k1'); const fs = require("fs"); - -var ProxyDeployer = require("./proxy.js"); +var Create2 = require("./create2.js"); const privateKey = process.env.PRIKEY -const crabNetwork = { - name: "crab", - url: "https://crab-rpc.darwinia.network", - dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", - deployer: "0xbe6b2860d3c17a719be0A4911EA0EE689e8357f3", - msgline: "0x0000000000D2de3e2444926c4577b0A59F1DD8BC", -}; - -const sepoliaNetwork = { - name: "sepolia", - url: "https://rpc-sepolia.rockx.com", - dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", - deployer: "0xbe6b2860d3c17a719be0A4911EA0EE689e8357f3", - msgline: "0x0000000000D2de3e2444926c4577b0A59F1DD8BC", -}; - function wallet(url) { const provider = new ethers.providers.JsonRpcProvider(url); const wallet = new ethers.Wallet(privateKey, provider); return wallet; } -async function deployMessager(wallet, dao, msgline, deployer) { - const messagerContract = await ethers.getContractFactory("MsglineMessager", wallet); - const messager = await messagerContract.deploy(dao, msgline); - await messager.deployed(); - console.log("finish to deploy messager, address:", messager.address); - return messager.address; +async function deployMessager(wallet, dao, msgport, deployer, salt) { + const messagerContract = await ethers.getContractFactory("MsgportMessager", wallet); + const bytecode = Create2.getDeployedBytecode(messagerContract, ["address", "address"], [dao, msgport]); + const address = await Create2.deploy(deployer, wallet, bytecode, salt, 2000000); + console.log("finish to deploy messager, address:", address); + return address; } -async function deploy() { - const walletCrab = wallet(crabNetwork.url); - await deployMessager(walletCrab, crabNetwork.dao, crabNetwork.msgline, crabNetwork.deployer); - - const walletSepolia = wallet(sepoliaNetwork.url); - await deployMessager(walletSepolia, sepoliaNetwork.dao, sepoliaNetwork.msgline, sepoliaNetwork.deployer); +function wallet(configure, network) { + const provider = new ethers.providers.JsonRpcProvider(network.url); + const wallet = new ethers.Wallet(privateKey, provider); + return wallet; } async function main() { - await deploy(); + const pathConfig = "./address/ln-dev.json"; + const configure = JSON.parse( + fs.readFileSync(pathConfig, "utf8") + ); + const network = configure.chains['pangolin']; + const w = wallet(configure, network); + await deployMessager(w, network.dao, network.ormpPort, network.deployer, "msgport-messager-v1.0.0"); } main() diff --git a/helix-contract/deploy/deploy_xtoken_config.js b/helix-contract/deploy/deploy_xtoken_config.js index 0a1d4d3..63855f3 100644 --- a/helix-contract/deploy/deploy_xtoken_config.js +++ b/helix-contract/deploy/deploy_xtoken_config.js @@ -7,21 +7,21 @@ var ProxyDeployer = require("./proxy.js"); const privateKey = process.env.PRIKEY -const crabNetwork = { - name: "crab", - url: "https://crab-rpc.darwinia.network", +const pangolinNetwork = { + name: "pangolin", + url: "https://pangolin-rpc.darwinia.network", dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", - messager: "0xf85638B61E0425D6BB91981190B73246e3AF3CA9", - backing: "0xbdC7bbF408931C5d666b4F0520E0D9E9A0B04e99", - chainid: 44 + messager: "0xf7F461728DC89de5EF6615715678b5f5b12bb98A", + backing: "0x94eAb0CB67AB7edaf9A280aCa097F70e4BD780ac", + chainid: 43 }; const sepoliaNetwork = { name: "sepolia", url: "https://rpc-sepolia.rockx.com", dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", - messager: "0xc876D0873e4060472334E297b2db200Ca10cc806", - issuing: "0xf22D0bb66b39745Ae6e3fEa3E5859d7f0b367Fd1", + messager: "0xf7F461728DC89de5EF6615715678b5f5b12bb98A", + issuing: "0x371019523b25Ff4F26d977724f976566b08bf741", chainid: 11155111 }; @@ -32,14 +32,14 @@ function wallet(url) { } async function deploy() { - const backingNetwork = crabNetwork; + const backingNetwork = pangolinNetwork; const issuingNetwork = sepoliaNetwork; - const walletBacking = wallet(crabNetwork.url); + const walletBacking = wallet(pangolinNetwork.url); const walletIssuing = wallet(sepoliaNetwork.url); // connect messager - const backingMessager = await ethers.getContractAt("MsglineMessager", backingNetwork.messager, walletBacking); - const issuingMessager = await ethers.getContractAt("MsglineMessager", issuingNetwork.messager, walletIssuing); + const backingMessager = await ethers.getContractAt("MsgportMessager", backingNetwork.messager, walletBacking); + const issuingMessager = await ethers.getContractAt("MsgportMessager", issuingNetwork.messager, walletIssuing); await backingMessager.setRemoteMessager(issuingNetwork.chainid, issuingNetwork.chainid, issuingMessager.address, {gasLimit: 2000000}); await issuingMessager.setRemoteMessager(backingNetwork.chainid, backingNetwork.chainid, backingMessager.address, {gasLimit: 2000000}); console.log("connect messager successed"); diff --git a/helix-contract/deploy/deploy_xtoken_logic.js b/helix-contract/deploy/deploy_xtoken_logic.js index 92308bd..2969f59 100644 --- a/helix-contract/deploy/deploy_xtoken_logic.js +++ b/helix-contract/deploy/deploy_xtoken_logic.js @@ -1,27 +1,12 @@ const ethUtil = require('ethereumjs-util'); const abi = require('ethereumjs-abi'); const secp256k1 = require('secp256k1'); +const fs = require("fs"); var Create2 = require("./create2.js"); const privateKey = process.env.PRIKEY -const crabNetwork = { - url: "https://crab-rpc.darwinia.network", - deployer: "0xbe6b2860d3c17a719be0A4911EA0EE689e8357f3", -}; - -const sepoliaNetwork = { - url: "https://rpc-sepolia.rockx.com", - deployer: "0xbe6b2860d3c17a719be0A4911EA0EE689e8357f3", -} - -function wallet(url) { - const provider = new ethers.providers.JsonRpcProvider(url); - const wallet = new ethers.Wallet(privateKey, provider); - return wallet; -} - async function deployxTokenBacking(wallet, deployerAddress, salt) { const bridgeContract = await ethers.getContractFactory("xTokenBacking", wallet); const bytecode = Create2.getDeployedBytecode(bridgeContract, [], []); @@ -38,15 +23,23 @@ async function deployxTokenIssuing(wallet, deployerAddress, salt) { return address; } +function wallet(configure, network) { + const provider = new ethers.providers.JsonRpcProvider(network.url); + const wallet = new ethers.Wallet(privateKey, provider); + return wallet; +} + // 2. deploy mapping token factory async function main() { - // deploy backing on crab - const walletCrab = wallet(crabNetwork.url); - const backingLogic = await deployxTokenBacking(walletCrab, crabNetwork.deployer, "xTokenBacking-logic-v1.0.3"); - - // deploy issuing on sepolia - const walletSpeolia = wallet(sepoliaNetwork.url); - const issuingLogic = await deployxTokenIssuing(walletSpeolia, sepoliaNetwork.deployer, "xTokenIssuing-logic-v1.0.3"); + const pathConfig = "./address/ln-dev.json"; + const configure = JSON.parse( + fs.readFileSync(pathConfig, "utf8") + ); + const network = configure.chains['pangolin']; + const w = wallet(configure, network); + + //const backingLogic = await deployxTokenBacking(w, network.deployer, "xTokenBacking-logic-v1.0.0"); + const issuingLogic = await deployxTokenIssuing(w, network.deployer, "xTokenIssuing-logic-v1.0.0"); } main() diff --git a/helix-contract/deploy/deploy_xtoken_proxy.js b/helix-contract/deploy/deploy_xtoken_proxy.js index fadbe60..7aeb5b2 100644 --- a/helix-contract/deploy/deploy_xtoken_proxy.js +++ b/helix-contract/deploy/deploy_xtoken_proxy.js @@ -7,24 +7,8 @@ var ProxyDeployer = require("./proxy.js"); const privateKey = process.env.PRIKEY -const crabNetwork = { - name: "crab", - url: "https://crab-rpc.darwinia.network", - dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", - proxyAdmin: "0xE3979fFa68BBa1F53c6F502c8F5788B370d28730", - deployer: "0xbe6b2860d3c17a719be0A4911EA0EE689e8357f3", -}; - -const sepoliaNetwork = { - name: "sepolia", - url: "https://rpc-sepolia.rockx.com", - dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", - proxyAdmin: "0xE3979fFa68BBa1F53c6F502c8F5788B370d28730", - deployer: "0xbe6b2860d3c17a719be0A4911EA0EE689e8357f3", -}; - -function wallet(url) { - const provider = new ethers.providers.JsonRpcProvider(url); +function wallet(configure, network) { + const provider = new ethers.providers.JsonRpcProvider(network.url); const wallet = new ethers.Wallet(privateKey, provider); return wallet; } @@ -38,19 +22,30 @@ async function deployxTokenProxy(wallet, salt, dao, proxyAdminAddress, logicAddr bridgeContract, logicAddress, [dao, salt], - wallet); + wallet, + 5000000 + ); console.log("finish to deploy xtoken bridge proxy, address:", proxy); return proxy; } async function deploy() { - const walletCrab = wallet(crabNetwork.url); - const backingLogic = "0x22E50D0511538B78D4E3b94d4D51AFDa924286D0"; - await deployxTokenProxy(walletCrab, "xtoken-backing-1.0.4", crabNetwork.dao, crabNetwork.proxyAdmin, backingLogic, crabNetwork.deployer); - - const walletSepolia = wallet(sepoliaNetwork.url); - const issuingLogic = "0xCD1c1C799f3914ECFC5e3653D3Cc846355d3dFC9"; - await deployxTokenProxy(walletSepolia, "xtoken-issuing-1.0.4", sepoliaNetwork.dao, sepoliaNetwork.proxyAdmin, issuingLogic, sepoliaNetwork.deployer); + const pathConfig = "./address/ln-dev.json"; + const configure = JSON.parse( + fs.readFileSync(pathConfig, "utf8") + ); + const network = configure.chains['sepolia']; + const w = wallet(configure, network); + + const xTokenConfigPath = "./address/xtoken-dev.json"; + const xTokenConfig = JSON.parse( + fs.readFileSync(xTokenConfigPath, "utf8") + ); + + //const backingLogic = xTokenConfig.backingLogic['pangolin']; + //await deployxTokenProxy(w, "xtoken-backing-1.0.0", network.dao, configure.ProxyAdmin.others, backingLogic, network.deployer); + const issuingLogic = xTokenConfig.issuingLogic['sepolia']; + await deployxTokenProxy(w, "xtoken-issuing-1.0.0", network.dao, configure.ProxyAdmin.others, issuingLogic, network.deployer); } async function main() { diff --git a/helix-contract/deploy/deploy_xtoken_test.js b/helix-contract/deploy/deploy_xtoken_test.js index b2a9a15..9247f24 100644 --- a/helix-contract/deploy/deploy_xtoken_test.js +++ b/helix-contract/deploy/deploy_xtoken_test.js @@ -7,19 +7,19 @@ var ProxyDeployer = require("./proxy.js"); const privateKey = process.env.PRIKEY -const crabNetwork = { - name: "crab", - url: "https://crab-rpc.darwinia.network", +const pangolinNetwork = { + name: "pangolin", + url: "https://pangolin-rpc.darwinia.network", dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", - backing: "0xbdC7bbF408931C5d666b4F0520E0D9E9A0B04e99", - chainid: 44 + backing: "0x94eAb0CB67AB7edaf9A280aCa097F70e4BD780ac", + chainid: 43 }; const sepoliaNetwork = { name: "sepolia", - url: "https://rpc-sepolia.rockx.com", + url: "https://rpc.sepolia.org", dao: "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", - issuing: "0xf22D0bb66b39745Ae6e3fEa3E5859d7f0b367Fd1", + issuing: "0x371019523b25Ff4F26d977724f976566b08bf741", chainid: 11155111 }; @@ -36,11 +36,11 @@ async function registerIssuing() { const issuing = await ethers.getContractAt("xTokenIssuing", issuingNetwork.issuing, walletIssuing); await issuing.registerxToken( - 44, + 43, "0x0000000000000000000000000000000000000000", - "crab", - "crab native token", - "CRAB", + "pangolin", + "pangolin native token", + "PRING", 18, "0x56bc75e2d63100000", { gasLimit: 1000000 } @@ -48,11 +48,11 @@ async function registerIssuing() { } async function registerBacking() { - const backingNetwork = crabNetwork; - const walletBacking = wallet(crabNetwork.url); + const backingNetwork = pangolinNetwork; + const walletBacking = wallet(pangolinNetwork.url); const backing = await ethers.getContractAt("xTokenBacking", backingNetwork.backing, walletBacking); - const xToken = "0x9Da7E18441f26515CC713290BE846E726d41781d"; + const xToken = "0xBC43cb6175FcC8E577a0846256eA699b87eFcEE5"; await backing.registerOriginalToken( 11155111, @@ -63,8 +63,8 @@ async function registerBacking() { } async function lockAndRemoteIssuing() { - const backingNetwork = crabNetwork; - const walletBacking = wallet(crabNetwork.url); + const backingNetwork = pangolinNetwork; + const walletBacking = wallet(pangolinNetwork.url); const backing = await ethers.getContractAt("xTokenBacking", backingNetwork.backing, walletBacking); @@ -73,10 +73,10 @@ async function lockAndRemoteIssuing() { 11155111, "0x0000000000000000000000000000000000000000", walletBacking.address, - ethers.utils.parseEther("10"), - 1703247763002, + ethers.utils.parseEther("10000"), + 1703247763006, "0x000000000000000000000000000000000000000000000000000000000005f02200000000000000000000000088a39b052d477cfde47600a7c9950a441ce61cb400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", - { value: ethers.utils.parseEther("15.4") } + { value: ethers.utils.parseEther("10005") } ); } @@ -86,7 +86,7 @@ async function burnAndRemoteUnlock() { const issuing = await ethers.getContractAt("xTokenIssuing", issuingNetwork.issuing, walletIssuing); - const xTokenAddress = "0x9Da7E18441f26515CC713290BE846E726d41781d"; + const xTokenAddress = "0xBC43cb6175FcC8E577a0846256eA699b87eFcEE5"; const xToken = await ethers.getContractAt("xTokenErc20", xTokenAddress, walletIssuing); await xToken.approve(issuing.address, ethers.utils.parseEther("10000000"), {gasLimit: 500000}); await issuing.burnAndRemoteUnlock( @@ -109,12 +109,12 @@ async function requestRemoteUnlockForIssuingFailure() { const issuing = await ethers.getContractAt("xTokenIssuing", issuingNetwork.issuing, walletIssuing); await issuing.requestRemoteUnlockForIssuingFailure( - 44, + 43, "0x0000000000000000000000000000000000000000", walletIssuing.address, walletIssuing.address, - ethers.utils.parseEther("91"), - 1703247763001, + ethers.utils.parseEther("12000"), + 1703247763005, "0x000000000000000000000000000000000000000000000000000000000006493c00000000000000000000000088a39b052d477cfde47600a7c9950a441ce61cb400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000", { value: ethers.utils.parseEther("0.0000007"), @@ -124,8 +124,8 @@ async function requestRemoteUnlockForIssuingFailure() { } async function requestRemoteIssuingForUnlockFailure() { - const backingNetwork = crabNetwork; - const walletBacking = wallet(crabNetwork.url); + const backingNetwork = pangolinNetwork; + const walletBacking = wallet(pangolinNetwork.url); const backing = await ethers.getContractAt("xTokenBacking", backingNetwork.backing, walletBacking); @@ -146,8 +146,8 @@ async function main() { //await registerBacking(); //await lockAndRemoteIssuing(); //await burnAndRemoteUnlock(); - //await requestRemoteUnlockForIssuingFailure(); - await requestRemoteIssuingForUnlockFailure(); + await requestRemoteUnlockForIssuingFailure(); + //await requestRemoteIssuingForUnlockFailure(); } main() diff --git a/helix-contract/deploy/flatten-xtoken.sh b/helix-contract/deploy/flatten-xtoken.sh index bd09b6a..6f92f0a 100644 --- a/helix-contract/deploy/flatten-xtoken.sh +++ b/helix-contract/deploy/flatten-xtoken.sh @@ -4,4 +4,4 @@ yarn flat contracts/mapping-token/v3/base/xTokenBacking.sol --output $path/xToke yarn flat contracts/mapping-token/v3/base/xTokenIssuing.sol --output $path/xTokenIssuing.sol yarn flat contracts/mapping-token/v3/base/xTokenErc20.sol --output $path/xTokenErc20.sol yarn flat contracts/mapping-token/v3/GuardV3.sol --output $path/GuardV3.sol -yarn flat contracts/messagers/MsglineMessager.sol --output $path/MsglineMessager.sol +yarn flat contracts/messagers/MsgportMessager.sol --output $path/MsgportMessager.sol diff --git a/helix-contract/deploy/proxy.js b/helix-contract/deploy/proxy.js index 8c7b210..a690b4d 100644 --- a/helix-contract/deploy/proxy.js +++ b/helix-contract/deploy/proxy.js @@ -34,9 +34,8 @@ var ProxyDeployer = { proxyContract, ["address", "address", "bytes"], [logicAddress, proxyAdminAdder, calldata], - { gasLimit: gasLimit } ); - return await Create2.deploy(deployerAddress, wallet, deployedBytecode, salt); + return await Create2.deploy(deployerAddress, wallet, deployedBytecode, salt, gasLimit); } } diff --git a/helix-contract/flatten/xtoken-v3/GuardV3.sol b/helix-contract/flatten/xtoken-v3/GuardV3.sol index 497e258..5d4a873 100644 --- a/helix-contract/flatten/xtoken-v3/GuardV3.sol +++ b/helix-contract/flatten/xtoken-v3/GuardV3.sol @@ -14,7 +14,7 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 12/26/2023 + * 2/6/2024 **/ pragma solidity ^0.8.17; @@ -617,89 +617,6 @@ interface IWToken { function withdraw(uint wad) external; } -// File @zeppelin-solidity/contracts/token/ERC20/IERC20.sol@v4.7.3 -// License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) external returns (bool); -} - // File @zeppelin-solidity/contracts/utils/Context.sol@v4.7.3 // License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) @@ -829,6 +746,89 @@ abstract contract Pausable is Context { } } +// File @zeppelin-solidity/contracts/token/ERC20/IERC20.sol@v4.7.3 +// License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) + + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); + + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `to`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address to, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `from` to `to` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom( + address from, + address to, + uint256 amount + ) external returns (bool); +} + // File @zeppelin-solidity/contracts/utils/math/SafeMath.sol@v4.7.3 // License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol) @@ -1142,6 +1142,7 @@ contract GuardV3 is GuardRegistryV3, Pausable { ) internal { require(hash(abi.encodePacked(from, timestamp, token, recipient, amount)) == deposits[id], "Guard: Invalid id to claim"); require(amount > 0, "Guard: Invalid amount to claim"); + delete deposits[id]; if (isNative) { require(IERC20(token).transferFrom(from, address(this), amount), "Guard: claim native token failed"); uint256 balanceBefore = address(this).balance; @@ -1151,7 +1152,6 @@ contract GuardV3 is GuardRegistryV3, Pausable { } else { require(IERC20(token).transferFrom(from, recipient, amount), "Guard: claim token failed"); } - delete deposits[id]; emit TokenClaimed(id); } diff --git a/helix-contract/flatten/xtoken-v3/MsgportMessager.sol b/helix-contract/flatten/xtoken-v3/MsgportMessager.sol new file mode 100644 index 0000000..e026e48 --- /dev/null +++ b/helix-contract/flatten/xtoken-v3/MsgportMessager.sol @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: MIT + +/** + * .----------------. .----------------. .----------------. .----------------. .----------------. + * | .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | + * | | ____ ____ | || | _________ | || | _____ | || | _____ | || | ____ ____ | | + * | | |_ || _| | || | |_ ___ | | || | |_ _| | || | |_ _| | || | |_ _||_ _| | | + * | | | |__| | | || | | |_ \_| | || | | | | || | | | | || | \ \ / / | | + * | | | __ | | || | | _| _ | || | | | _ | || | | | | || | > `' < | | + * | | _| | | |_ | || | _| |___/ | | || | _| |__/ | | || | _| |_ | || | _/ /'`\ \_ | | + * | | |____||____| | || | |_________| | || | |________| | || | |_____| | || | |____||____| | | + * | | | || | | || | | || | | || | | | + * | '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | + * '----------------' '----------------' '----------------' '----------------' '----------------' ' + * + * + * 2/6/2024 + **/ + +pragma solidity ^0.8.17; + +// File contracts/utils/AccessController.sol +// License-Identifier: MIT + +/// @title AccessController +/// @notice AccessController is a contract to control the access permission +/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract +contract AccessController { + address public dao; + address public operator; + address public pendingDao; + + modifier onlyDao() { + require(msg.sender == dao, "!dao"); + _; + } + + modifier onlyOperator() { + require(msg.sender == operator, "!operator"); + _; + } + + function _initialize(address _dao) internal { + dao = _dao; + operator = _dao; + } + + function setOperator(address _operator) onlyDao external { + operator = _operator; + } + + function transferOwnership(address _dao) onlyDao external { + pendingDao = _dao; + } + + function acceptOwnership() external { + address newDao = msg.sender; + require(pendingDao == newDao, "!pendingDao"); + delete pendingDao; + dao = newDao; + } +} + +// File contracts/interfaces/IMessageLine.sol +// License-Identifier: MIT + +interface IMessageLine { + function send(uint256 toChainId, address toDapp, bytes calldata message, bytes calldata params) external payable; + function fee(uint256 toChainId, address toDapp, bytes calldata message, bytes calldata params) external view returns (uint256); +} + +abstract contract Application { + function _msgSender() internal view returns (address payable _line) { + _line = payable(msg.sender); + } + + function _fromChainId() internal pure returns (uint256 _msgDataFromChainId) { + require(msg.data.length >= 52, "!fromChainId"); + assembly { + _msgDataFromChainId := calldataload(sub(calldatasize(), 52)) + } + } + + function _xmsgSender() internal pure returns (address payable _from) { + require(msg.data.length >= 20, "!line"); + assembly { + _from := shr(96, calldataload(sub(calldatasize(), 20))) + } + } +} + +// File contracts/messagers/MsgportMessager.sol +// License-Identifier: MIT + + +contract MsgportMessager is Application, AccessController { + IMessageLine public msgport; + + struct RemoteMessager { + uint256 msgportRemoteChainId; + address messager; + } + + mapping(address=>bool) public whiteList; + // app remoteChainId => msgport remote messager + mapping(uint256=>RemoteMessager) public remoteMessagers; + + // token bridge pair + // hash(msgportRemoteChainId, localAppAddress) => remoteAppAddress + mapping(bytes32=>address) public remoteAppReceivers; + mapping(bytes32=>address) public remoteAppSenders; + + event CallerUnMatched(uint256 srcAppChainId, address srcAppAddress); + event CallResult(uint256 srcAppChainId, bool result); + + modifier onlyWhiteList() { + require(whiteList[msg.sender], "msg.sender not in whitelist"); + _; + } + + modifier onlyMsgline() { + require(msg.sender == address(msgport), "invalid caller"); + _; + } + + constructor(address _dao, address _msgport) { + _initialize(_dao); + msgport = IMessageLine(_msgport); + } + + function setMsgline(address _msgport) onlyDao external { + msgport = IMessageLine(_msgport); + } + + function setRemoteMessager(uint256 _appRemoteChainId, uint256 _msgportRemoteChainId, address _remoteMessager) onlyDao external { + remoteMessagers[_appRemoteChainId] = RemoteMessager(_msgportRemoteChainId, _remoteMessager); + } + + function setWhiteList(address _caller, bool _enable) external onlyDao { + whiteList[_caller] = _enable; + } + + function registerRemoteReceiver(uint256 _remoteChainId, address _remoteBridge) onlyWhiteList external { + RemoteMessager memory remoteMessager = remoteMessagers[_remoteChainId]; + require(remoteMessager.messager != address(0), "remote not configured"); + bytes32 key = keccak256(abi.encodePacked(remoteMessager.msgportRemoteChainId, msg.sender)); + remoteAppReceivers[key] = _remoteBridge; + } + + function registerRemoteSender(uint256 _remoteChainId, address _remoteBridge) onlyWhiteList external { + RemoteMessager memory remoteMessager = remoteMessagers[_remoteChainId]; + require(remoteMessager.messager != address(0), "remote not configured"); + bytes32 key = keccak256(abi.encodePacked(remoteMessager.msgportRemoteChainId, msg.sender)); + remoteAppSenders[key] = _remoteBridge; + } + + function sendMessage(uint256 _remoteChainId, bytes memory _message, bytes memory _params) onlyWhiteList external payable { + RemoteMessager memory remoteMessager = remoteMessagers[_remoteChainId]; + require(remoteMessager.messager != address(0), "remote not configured"); + bytes32 key = keccak256(abi.encodePacked(remoteMessager.msgportRemoteChainId, msg.sender)); + address remoteAppAddress = remoteAppReceivers[key]; + require(remoteAppAddress != address(0), "app pair not registered"); + bytes memory msgportPayload = messagePayload(msg.sender, remoteAppAddress, _message); + msgport.send{ value: msg.value }( + remoteMessager.msgportRemoteChainId, + remoteMessager.messager, + msgportPayload, + _params + ); + } + + function receiveMessage(uint256 _srcAppChainId, address _remoteAppAddress, address _localAppAddress, bytes memory _message) onlyMsgline external { + uint256 srcChainId = _fromChainId(); + RemoteMessager memory remoteMessager = remoteMessagers[_srcAppChainId]; + require(srcChainId == remoteMessager.msgportRemoteChainId, "invalid remote chainid"); + require(remoteMessager.messager == _xmsgSender(), "invalid remote messager"); + bytes32 key = keccak256(abi.encodePacked(srcChainId, _localAppAddress)); + + // check remote appSender + if (_remoteAppAddress != remoteAppSenders[key]) { + emit CallerUnMatched(_srcAppChainId, _remoteAppAddress); + return; + } + (bool success,) = _localAppAddress.call(_message); + // don't revert to prevent message block + emit CallResult(_srcAppChainId, success); + } + + function messagePayload(address _from, address _to, bytes memory _message) public view returns(bytes memory) { + return abi.encodeWithSelector( + MsgportMessager.receiveMessage.selector, + block.chainid, + _from, + _to, + _message + ); + } +} \ No newline at end of file diff --git a/helix-contract/flatten/xtoken-v3/xTokenBacking.sol b/helix-contract/flatten/xtoken-v3/xTokenBacking.sol index 851ce08..07f19e0 100644 --- a/helix-contract/flatten/xtoken-v3/xTokenBacking.sol +++ b/helix-contract/flatten/xtoken-v3/xTokenBacking.sol @@ -14,7 +14,7 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 12/26/2023 + * 2/6/2024 **/ pragma solidity ^0.8.17; @@ -160,29 +160,6 @@ interface IWToken { function withdraw(uint wad) external; } -// File contracts/mapping-token/v3/interfaces/IxTokenIssuing.sol -// License-Identifier: MIT - -interface IxTokenIssuing { - function handleIssuingForUnlockFailureFromRemote( - uint256 originalChainId, - address originalToken, - address originalSender, - address recipient, - uint256 amount, - uint256 nonce - ) external; - - function issuexToken( - uint256 remoteChainId, - address originalToken, - address originalSender, - address recipient, - uint256 amount, - uint256 nonce - ) external; -} - // File contracts/interfaces/IMessager.sol // License-Identifier: MIT @@ -974,6 +951,29 @@ contract xTokenBridgeBase is Initializable, Pausable, AccessController, DailyLim } } +// File contracts/mapping-token/v3/interfaces/IxTokenIssuing.sol +// License-Identifier: MIT + +interface IxTokenIssuing { + function handleIssuingForUnlockFailureFromRemote( + uint256 originalChainId, + address originalToken, + address originalSender, + address recipient, + uint256 amount, + uint256 nonce + ) external; + + function issuexToken( + uint256 remoteChainId, + address originalToken, + address originalSender, + address recipient, + uint256 amount, + uint256 nonce + ) external; +} + // File contracts/mapping-token/v3/base/xTokenBacking.sol // License-Identifier: MIT diff --git a/helix-contract/flatten/xtoken-v3/xTokenErc20.sol b/helix-contract/flatten/xtoken-v3/xTokenErc20.sol index ae6d4a3..fb1625f 100644 --- a/helix-contract/flatten/xtoken-v3/xTokenErc20.sol +++ b/helix-contract/flatten/xtoken-v3/xTokenErc20.sol @@ -14,7 +14,7 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 12/26/2023 + * 2/6/2024 **/ pragma solidity ^0.8.17; diff --git a/helix-contract/flatten/xtoken-v3/xTokenIssuing.sol b/helix-contract/flatten/xtoken-v3/xTokenIssuing.sol index 4487af7..38790eb 100644 --- a/helix-contract/flatten/xtoken-v3/xTokenIssuing.sol +++ b/helix-contract/flatten/xtoken-v3/xTokenIssuing.sol @@ -14,7 +14,7 @@ * '----------------' '----------------' '----------------' '----------------' '----------------' ' * * - * 12/26/2023 + * 2/6/2024 **/ pragma solidity ^0.8.17; @@ -151,17 +151,46 @@ interface IGuard { function deposit(uint256 id, address token, address recipient, uint256 amount) external; } -// File contracts/interfaces/IMessager.sol +// File contracts/utils/AccessController.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; -} +/// @title AccessController +/// @notice AccessController is a contract to control the access permission +/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract +contract AccessController { + address public dao; + address public operator; + address public pendingDao; -interface ILowLevelMessageReceiver { - function registerRemoteSender(uint256 remoteChainId, address remoteBridge) external; - function recvMessage(address remoteSender, address localReceiver, bytes memory payload) external; + modifier onlyDao() { + require(msg.sender == dao, "!dao"); + _; + } + + modifier onlyOperator() { + require(msg.sender == operator, "!operator"); + _; + } + + function _initialize(address _dao) internal { + dao = _dao; + operator = _dao; + } + + function setOperator(address _operator) onlyDao external { + operator = _operator; + } + + function transferOwnership(address _dao) onlyDao external { + pendingDao = _dao; + } + + function acceptOwnership() external { + address newDao = msg.sender; + require(pendingDao == newDao, "!pendingDao"); + delete pendingDao; + dao = newDao; + } } // File contracts/utils/DailyLimit.sol @@ -247,46 +276,17 @@ contract DailyLimit { } } -// File contracts/utils/AccessController.sol +// File contracts/interfaces/IMessager.sol // License-Identifier: MIT -/// @title AccessController -/// @notice AccessController is a contract to control the access permission -/// @dev See https://github.com/helix-bridge/contracts/tree/master/helix-contract -contract AccessController { - address public dao; - address public operator; - address public pendingDao; - - modifier onlyDao() { - require(msg.sender == dao, "!dao"); - _; - } - - modifier onlyOperator() { - require(msg.sender == operator, "!operator"); - _; - } - - function _initialize(address _dao) internal { - dao = _dao; - operator = _dao; - } - - function setOperator(address _operator) onlyDao external { - operator = _operator; - } - - function transferOwnership(address _dao) onlyDao external { - pendingDao = _dao; - } +interface ILowLevelMessageSender { + function registerRemoteReceiver(uint256 remoteChainId, address remoteBridge) external; + function sendMessage(uint256 remoteChainId, bytes memory message, bytes memory params) external payable; +} - function acceptOwnership() external { - address newDao = msg.sender; - require(pendingDao == newDao, "!pendingDao"); - delete pendingDao; - dao = newDao; - } +interface ILowLevelMessageReceiver { + function registerRemoteSender(uint256 remoteChainId, address remoteBridge) external; + function recvMessage(address remoteSender, address localReceiver, bytes memory payload) external; } // File @zeppelin-solidity/contracts/utils/Address.sol@v4.7.3 From fab321ee8af549074936c319afd959c9b64ba459 Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Wed, 7 Feb 2024 17:34:43 +0800 Subject: [PATCH 3/4] rename msgline->msgport --- helix-contract/address/ln-product.json | 11 ++++++++++- .../{IMessageLine.sol => IMessagePort.sol} | 8 ++++---- .../contracts/messagers/MsgportMessager.sol | 14 +++++++------- ...line_messager.js => deploy_msgport_messager.js} | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) rename helix-contract/contracts/interfaces/{IMessageLine.sol => IMessagePort.sol} (87%) rename helix-contract/deploy/{deploy_msgline_messager.js => deploy_msgport_messager.js} (96%) diff --git a/helix-contract/address/ln-product.json b/helix-contract/address/ln-product.json index a7e1854..6404321 100644 --- a/helix-contract/address/ln-product.json +++ b/helix-contract/address/ln-product.json @@ -80,6 +80,14 @@ "lzChainId": 214, "lzEndpoint": "0xb6319cC6c8c27A8F5dAF0dD3DF91EA35C4720dd7", "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3" + }, + "darwinia-dvm": { + "name": "darwinia-dvm", + "url": "https://rpc.darwinia.network", + "dao": "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + "chainId": 46, + "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3", + "ormpPort": "0x0000000005d961F950adA391C1511c92bbc64D9F" } }, "messagers": { @@ -105,7 +113,8 @@ }, "darwinia": { "DarwiniaMsglineMessager": "0x6035Eb7783d7Aab8d0a57a7b154f5DD5D5477Ff2", - "DarwiniaSub2SubMessager": "0x9dF64c435F02fb46bd8eB3757D3dF42dDA912bDe" + "DarwiniaSub2SubMessager": "0x9dF64c435F02fb46bd8eB3757D3dF42dDA912bDe", + "MsgportMessager": "0x65Be094765731F394bc6d9DF53bDF3376F1Fc8B0" }, "crab": { "DarwiniaSub2SubMessager": "0x9dF64c435F02fb46bd8eB3757D3dF42dDA912bDe" diff --git a/helix-contract/contracts/interfaces/IMessageLine.sol b/helix-contract/contracts/interfaces/IMessagePort.sol similarity index 87% rename from helix-contract/contracts/interfaces/IMessageLine.sol rename to helix-contract/contracts/interfaces/IMessagePort.sol index d56739a..5ad035b 100644 --- a/helix-contract/contracts/interfaces/IMessageLine.sol +++ b/helix-contract/contracts/interfaces/IMessagePort.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.17; -interface IMessageLine { +interface IMessagePort { function send(uint256 toChainId, address toDapp, bytes calldata message, bytes calldata params) external payable; function fee(uint256 toChainId, address toDapp, bytes calldata message, bytes calldata params) external view returns (uint256); } abstract contract Application { - function _msgSender() internal view returns (address payable _line) { - _line = payable(msg.sender); + function _msgSender() internal view returns (address payable _port) { + _port = payable(msg.sender); } function _fromChainId() internal pure returns (uint256 _msgDataFromChainId) { @@ -19,7 +19,7 @@ abstract contract Application { } function _xmsgSender() internal pure returns (address payable _from) { - require(msg.data.length >= 20, "!line"); + require(msg.data.length >= 20, "!port"); assembly { _from := shr(96, calldataload(sub(calldatasize(), 20))) } diff --git a/helix-contract/contracts/messagers/MsgportMessager.sol b/helix-contract/contracts/messagers/MsgportMessager.sol index 931840c..a9bf728 100644 --- a/helix-contract/contracts/messagers/MsgportMessager.sol +++ b/helix-contract/contracts/messagers/MsgportMessager.sol @@ -2,10 +2,10 @@ pragma solidity ^0.8.17; import "../utils/AccessController.sol"; -import "../interfaces/IMessageLine.sol"; +import "../interfaces/IMessagePort.sol"; contract MsgportMessager is Application, AccessController { - IMessageLine public msgport; + IMessagePort public msgport; struct RemoteMessager { uint256 msgportRemoteChainId; @@ -29,18 +29,18 @@ contract MsgportMessager is Application, AccessController { _; } - modifier onlyMsgline() { + modifier onlyMsgPort() { require(msg.sender == address(msgport), "invalid caller"); _; } constructor(address _dao, address _msgport) { _initialize(_dao); - msgport = IMessageLine(_msgport); + msgport = IMessagePort(_msgport); } - function setMsgline(address _msgport) onlyDao external { - msgport = IMessageLine(_msgport); + function setMsgPort(address _msgport) onlyDao external { + msgport = IMessagePort(_msgport); } function setRemoteMessager(uint256 _appRemoteChainId, uint256 _msgportRemoteChainId, address _remoteMessager) onlyDao external { @@ -80,7 +80,7 @@ contract MsgportMessager is Application, AccessController { ); } - function receiveMessage(uint256 _srcAppChainId, address _remoteAppAddress, address _localAppAddress, bytes memory _message) onlyMsgline external { + function receiveMessage(uint256 _srcAppChainId, address _remoteAppAddress, address _localAppAddress, bytes memory _message) onlyMsgPort external { uint256 srcChainId = _fromChainId(); RemoteMessager memory remoteMessager = remoteMessagers[_srcAppChainId]; require(srcChainId == remoteMessager.msgportRemoteChainId, "invalid remote chainid"); diff --git a/helix-contract/deploy/deploy_msgline_messager.js b/helix-contract/deploy/deploy_msgport_messager.js similarity index 96% rename from helix-contract/deploy/deploy_msgline_messager.js rename to helix-contract/deploy/deploy_msgport_messager.js index 06cef16..834d07b 100644 --- a/helix-contract/deploy/deploy_msgline_messager.js +++ b/helix-contract/deploy/deploy_msgport_messager.js @@ -31,7 +31,7 @@ async function main() { const configure = JSON.parse( fs.readFileSync(pathConfig, "utf8") ); - const network = configure.chains['pangolin']; + const network = configure.chains['sepolia']; const w = wallet(configure, network); await deployMessager(w, network.dao, network.ormpPort, network.deployer, "msgport-messager-v1.0.0"); } From 0c0a881634ed519eaffe857263d9b54e1c454eba Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Tue, 20 Feb 2024 10:11:25 +0800 Subject: [PATCH 4/4] update address --- helix-contract/address/ln-product.json | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/helix-contract/address/ln-product.json b/helix-contract/address/ln-product.json index 6404321..e48eca7 100644 --- a/helix-contract/address/ln-product.json +++ b/helix-contract/address/ln-product.json @@ -88,6 +88,23 @@ "chainId": 46, "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3", "ormpPort": "0x0000000005d961F950adA391C1511c92bbc64D9F" + }, + "polygon-zkevm": { + "name": "polygon-zkevm", + "url": "https://zkevm-rpc.com", + "dao": "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + "chainId": 1101, + "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3", + "lzChainId": 158, + "lzEndpoint": "0x9740FF91F1985D8d2B71494aE1A2f723bb3Ed9E4" + }, + "crab-dvm": { + "name": "crab-dvm", + "url": "https://crab-rpc.darwinia.network", + "dao": "0x88a39B052d477CfdE47600a7C9950a441Ce61cb4", + "chainId": 44, + "deployer": "0x80D4c766C5142D1313D531Afe7384D0D5E108Db3", + "ormpPort": "0x0000000005d961F950adA391C1511c92bbc64D9F" } }, "messagers": { @@ -97,7 +114,8 @@ "arbitrum": { "Eth2ArbReceiveService": "0xc95D939Da72ECe8Bd794d42EaEd28974CDb0ADa2", "LayerZeroMessager": "0x509354A4ebf98aCC7a65d2264694A65a2938cac9", - "DarwiniaMsglineMessager": "0x3d33856dcf74f110690f5a2647c7dfb9bb5ff2d0" + "DarwiniaMsglineMessager": "0x3d33856dcf74f110690f5a2647c7dfb9bb5ff2d0", + "MsgportMessager": "0x65Be094765731F394bc6d9DF53bDF3376F1Fc8B0" }, "polygon": { "LayerZeroMessager": "0x463D1730a8527CA58d48EF70C7460B9920346567"