From bbc0cffc23646a475c4e0c98ec6bf7bf8902642e Mon Sep 17 00:00:00 2001 From: gongtao245 Date: Tue, 12 Mar 2024 22:46:01 +0800 Subject: [PATCH 1/5] move request func to utils --- .../celerBridge/scripts/1-poolBasedTransfer.js | 14 +------------- .../scripts/2-queryPoolBasedTrasnferStatus.js | 14 +------------- .../scripts/4.1-queryCanonicalTrasnferStatus.js | 15 +-------------- .../4.2-queryCanonicalTrasnferStatus_ForRefund.js | 14 +------------- .../scripts/5-canonicalTrasnferRefund.js | 14 +------------- .../celerBridge/utils/index.js | 15 +++++++++++++++ 6 files changed, 20 insertions(+), 66 deletions(-) diff --git a/basic/80-crossChainTransfer/celerBridge/scripts/1-poolBasedTransfer.js b/basic/80-crossChainTransfer/celerBridge/scripts/1-poolBasedTransfer.js index 7b0057488..c3084af60 100644 --- a/basic/80-crossChainTransfer/celerBridge/scripts/1-poolBasedTransfer.js +++ b/basic/80-crossChainTransfer/celerBridge/scripts/1-poolBasedTransfer.js @@ -5,24 +5,12 @@ // will compile your contracts, add the Hardhat Runtime Environment's members to the // global scope, and execute the script. const {ethers} = require("hardhat"); -const fetch = require("node-fetch"); const { saveRedpacketDeployment, + request, } = require("../utils"); -const request = (url, params = {}, method = "GET") => { - let options = { - method, - }; - if ("GET" === method) { - url += "?" + new URLSearchParams(params).toString(); - } else { - options.body = JSON.stringify(params); - } - - return fetch(url, options).then((response) => response.json()); -}; async function getTransferConfigs(){ diff --git a/basic/80-crossChainTransfer/celerBridge/scripts/2-queryPoolBasedTrasnferStatus.js b/basic/80-crossChainTransfer/celerBridge/scripts/2-queryPoolBasedTrasnferStatus.js index ab5e1d8df..0b739fd44 100644 --- a/basic/80-crossChainTransfer/celerBridge/scripts/2-queryPoolBasedTrasnferStatus.js +++ b/basic/80-crossChainTransfer/celerBridge/scripts/2-queryPoolBasedTrasnferStatus.js @@ -5,24 +5,12 @@ // will compile your contracts, add the Hardhat Runtime Environment's members to the // global scope, and execute the script. const hre = require("hardhat"); -const fetch = require("node-fetch"); const { readRedpacketDeployment, + request, } = require("../utils"); -const request = (url, params = {}, method = "GET") => { - let options = { - method, - }; - if ("GET" === method) { - url += "?" + new URLSearchParams(params).toString(); - } else { - options.body = JSON.stringify(params); - } - - return fetch(url, options).then((response) => response.json()); -}; async function getTransferStatus(transferID){ diff --git a/basic/80-crossChainTransfer/celerBridge/scripts/4.1-queryCanonicalTrasnferStatus.js b/basic/80-crossChainTransfer/celerBridge/scripts/4.1-queryCanonicalTrasnferStatus.js index 496705b70..2dbb2850d 100644 --- a/basic/80-crossChainTransfer/celerBridge/scripts/4.1-queryCanonicalTrasnferStatus.js +++ b/basic/80-crossChainTransfer/celerBridge/scripts/4.1-queryCanonicalTrasnferStatus.js @@ -5,25 +5,12 @@ // will compile your contracts, add the Hardhat Runtime Environment's members to the // global scope, and execute the script. const {ethers} = require("hardhat"); -const fetch = require("node-fetch"); const { readRedpacketDeployment, + request, } = require("../utils"); -const request = (url, params = {}, method = "GET") => { - let options = { - method, - }; - if ("GET" === method) { - url += "?" + new URLSearchParams(params).toString(); - } else { - options.body = JSON.stringify(params); - } - - return fetch(url, options).then((response) => response.json()); -}; - async function getTransferStatus(transferID){ const fetchPostRes = await request( diff --git a/basic/80-crossChainTransfer/celerBridge/scripts/4.2-queryCanonicalTrasnferStatus_ForRefund.js b/basic/80-crossChainTransfer/celerBridge/scripts/4.2-queryCanonicalTrasnferStatus_ForRefund.js index 496705b70..351fb1008 100644 --- a/basic/80-crossChainTransfer/celerBridge/scripts/4.2-queryCanonicalTrasnferStatus_ForRefund.js +++ b/basic/80-crossChainTransfer/celerBridge/scripts/4.2-queryCanonicalTrasnferStatus_ForRefund.js @@ -5,24 +5,12 @@ // will compile your contracts, add the Hardhat Runtime Environment's members to the // global scope, and execute the script. const {ethers} = require("hardhat"); -const fetch = require("node-fetch"); const { readRedpacketDeployment, + request, } = require("../utils"); -const request = (url, params = {}, method = "GET") => { - let options = { - method, - }; - if ("GET" === method) { - url += "?" + new URLSearchParams(params).toString(); - } else { - options.body = JSON.stringify(params); - } - - return fetch(url, options).then((response) => response.json()); -}; async function getTransferStatus(transferID){ diff --git a/basic/80-crossChainTransfer/celerBridge/scripts/5-canonicalTrasnferRefund.js b/basic/80-crossChainTransfer/celerBridge/scripts/5-canonicalTrasnferRefund.js index 8a700f3da..e40b13cfc 100644 --- a/basic/80-crossChainTransfer/celerBridge/scripts/5-canonicalTrasnferRefund.js +++ b/basic/80-crossChainTransfer/celerBridge/scripts/5-canonicalTrasnferRefund.js @@ -5,24 +5,12 @@ // will compile your contracts, add the Hardhat Runtime Environment's members to the // global scope, and execute the script. const {ethers} = require("hardhat"); -const fetch = require("node-fetch"); const { readRedpacketDeployment, + request, } = require("../utils"); -const request = (url, params = {}, method = "GET") => { - let options = { - method, - }; - if ("GET" === method) { - url += "?" + new URLSearchParams(params).toString(); - } else { - options.body = JSON.stringify(params); - } - - return fetch(url, options).then((response) => response.json()); -}; async function getTransferStatus(transferID){ diff --git a/basic/80-crossChainTransfer/celerBridge/utils/index.js b/basic/80-crossChainTransfer/celerBridge/utils/index.js index 0b07c130d..b27c41e4a 100644 --- a/basic/80-crossChainTransfer/celerBridge/utils/index.js +++ b/basic/80-crossChainTransfer/celerBridge/utils/index.js @@ -2,6 +2,7 @@ const path = require("path"); const fs = require("fs"); const hre = require("hardhat"); +const fetch = require("node-fetch"); const currentNamework = hre.network.name; const DEPLOYMENGT_DIR = path.join( @@ -19,6 +20,19 @@ async function deployContract(name, params, deployer = undefined) { return contract; } +const request = (url, params = {}, method = "GET") => { + let options = { + method, + }; + if ("GET" === method) { + url += "?" + new URLSearchParams(params).toString(); + } else { + options.body = JSON.stringify(params); + } + + return fetch(url, options).then((response) => response.json()); +}; + /* * deployment: * redPacketAddress @@ -110,4 +124,5 @@ module.exports = { readRedpacketDeployment, saveRedpacketDeployment, hashToken, + request, }; From 7ce19b56f642c67f038a2c7de49de3259804af50 Mon Sep 17 00:00:00 2001 From: gongtao245 Date: Tue, 12 Mar 2024 22:49:03 +0800 Subject: [PATCH 2/5] add request func --- .../layerZero/hardhat.config.js | 4 ++++ .../80-crossChainTransfer/layerZero/package.json | 3 ++- .../sendMessage/1-deployOmniCounterOnSepolia.js | 1 + .../layerZero/utils/index.js | 15 +++++++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/basic/80-crossChainTransfer/layerZero/hardhat.config.js b/basic/80-crossChainTransfer/layerZero/hardhat.config.js index 65dc50a74..c326fa407 100644 --- a/basic/80-crossChainTransfer/layerZero/hardhat.config.js +++ b/basic/80-crossChainTransfer/layerZero/hardhat.config.js @@ -78,6 +78,10 @@ module.exports = { url: "https://optimism-sepolia.infura.io/v3/" + process.env.INFURA_ID, accounts: mnemonic() }, + mantaPacific: { + url: "https://pacific-rpc.manta.network/http", + accounts: mnemonic(), + }, }, mocha: { diff --git a/basic/80-crossChainTransfer/layerZero/package.json b/basic/80-crossChainTransfer/layerZero/package.json index af6045555..c04674fee 100644 --- a/basic/80-crossChainTransfer/layerZero/package.json +++ b/basic/80-crossChainTransfer/layerZero/package.json @@ -12,7 +12,8 @@ "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^4.0.0", "dotenv": "^16.4.5", - "hardhat": "^2.21.0" + "hardhat": "^2.21.0", + "node-fetch": "^2.7.0" }, "dependencies": { "@layerzerolabs/scan-client": "^0.0.8", diff --git a/basic/80-crossChainTransfer/layerZero/scripts/sendMessage/1-deployOmniCounterOnSepolia.js b/basic/80-crossChainTransfer/layerZero/scripts/sendMessage/1-deployOmniCounterOnSepolia.js index 8df3062ff..870485a27 100644 --- a/basic/80-crossChainTransfer/layerZero/scripts/sendMessage/1-deployOmniCounterOnSepolia.js +++ b/basic/80-crossChainTransfer/layerZero/scripts/sendMessage/1-deployOmniCounterOnSepolia.js @@ -11,6 +11,7 @@ const { } = require("../../utils"); async function main() { + const [deployer] = await ethers.getSigners(); // for sepolia, endpoint address is fixed, refer to : https://layerzero.gitbook.io/docs/technical-reference/testnet/testnet-addresses diff --git a/basic/80-crossChainTransfer/layerZero/utils/index.js b/basic/80-crossChainTransfer/layerZero/utils/index.js index 0b07c130d..b27c41e4a 100644 --- a/basic/80-crossChainTransfer/layerZero/utils/index.js +++ b/basic/80-crossChainTransfer/layerZero/utils/index.js @@ -2,6 +2,7 @@ const path = require("path"); const fs = require("fs"); const hre = require("hardhat"); +const fetch = require("node-fetch"); const currentNamework = hre.network.name; const DEPLOYMENGT_DIR = path.join( @@ -19,6 +20,19 @@ async function deployContract(name, params, deployer = undefined) { return contract; } +const request = (url, params = {}, method = "GET") => { + let options = { + method, + }; + if ("GET" === method) { + url += "?" + new URLSearchParams(params).toString(); + } else { + options.body = JSON.stringify(params); + } + + return fetch(url, options).then((response) => response.json()); +}; + /* * deployment: * redPacketAddress @@ -110,4 +124,5 @@ module.exports = { readRedpacketDeployment, saveRedpacketDeployment, hashToken, + request, }; From c49397de7e423359fd4169d4c06e0525c0adc3ca Mon Sep 17 00:00:00 2001 From: gongtao245 Date: Wed, 13 Mar 2024 14:20:39 +0800 Subject: [PATCH 3/5] add LI.FI --- .../80-crossChainTransfer/LI.FI/.env.example | 2 + basic/80-crossChainTransfer/LI.FI/.gitignore | 16 ++ basic/80-crossChainTransfer/LI.FI/README.md | 42 +++++ .../LI.FI/contracts/IERC20.sol | 79 +++++++++ .../LI.FI/hardhat.config.js | 89 ++++++++++ .../80-crossChainTransfer/LI.FI/package.json | 9 + .../scripts/1-crossChainTokenTransfer.js | 70 ++++++++ .../scripts/2-checkTokenTransferStatus.js | 65 +++++++ .../LI.FI/utils/index.js | 162 ++++++++++++++++++ 9 files changed, 534 insertions(+) create mode 100644 basic/80-crossChainTransfer/LI.FI/.env.example create mode 100644 basic/80-crossChainTransfer/LI.FI/.gitignore create mode 100644 basic/80-crossChainTransfer/LI.FI/README.md create mode 100644 basic/80-crossChainTransfer/LI.FI/contracts/IERC20.sol create mode 100644 basic/80-crossChainTransfer/LI.FI/hardhat.config.js create mode 100644 basic/80-crossChainTransfer/LI.FI/package.json create mode 100644 basic/80-crossChainTransfer/LI.FI/scripts/1-crossChainTokenTransfer.js create mode 100644 basic/80-crossChainTransfer/LI.FI/scripts/2-checkTokenTransferStatus.js create mode 100644 basic/80-crossChainTransfer/LI.FI/utils/index.js diff --git a/basic/80-crossChainTransfer/LI.FI/.env.example b/basic/80-crossChainTransfer/LI.FI/.env.example new file mode 100644 index 000000000..5effb1d3e --- /dev/null +++ b/basic/80-crossChainTransfer/LI.FI/.env.example @@ -0,0 +1,2 @@ +PRIVATE_KEY=yyyy +INFURA_ID=zzzz \ No newline at end of file diff --git a/basic/80-crossChainTransfer/LI.FI/.gitignore b/basic/80-crossChainTransfer/LI.FI/.gitignore new file mode 100644 index 000000000..7b1c94825 --- /dev/null +++ b/basic/80-crossChainTransfer/LI.FI/.gitignore @@ -0,0 +1,16 @@ +node_modules +.env + +# Hardhat files +/cache +/artifacts + +# TypeChain files +/typechain +/typechain-types + +# solidity-coverage files +/coverage +/coverage.json + +deployment.json \ No newline at end of file diff --git a/basic/80-crossChainTransfer/LI.FI/README.md b/basic/80-crossChainTransfer/LI.FI/README.md new file mode 100644 index 000000000..7ebca7b77 --- /dev/null +++ b/basic/80-crossChainTransfer/LI.FI/README.md @@ -0,0 +1,42 @@ +# LI.FI 介绍 +LI.FI 是一种跨链桥接聚合协议,通过聚合 Bridge, DEX, Solver 来支持 Token 在任意链之间转移,交易。 +应用场景举例如下: +1)Optim 上的 USDT 转移到 Polygon 上 +2)Optim 上的 USDT 转移到 Polygon 上,同时将 USDT swap 为 USDC +3)Optim 上的 USDT 转移到 Polygon 上,同时将 10% USDT 变为 Polygon 上原生的 gas ( Matic ),以便后续的操作。这个特性对 EVM 链和非 EVM 链来说非常便利,但目前只支持 4 个链 + +LI.FI 的操作很简单,用户只需在 origin chain 上发起一笔交易即可完成上述这些场景。 +同时为方便其他 Dapp 集成,LI.FI 提供了对应的 [SDK](https://docs.li.fi/integrate-li.fi-js-sdk/install-li.fi-sdk) 和 相应的前端 [UI components](https://docs.li.fi/integrate-li.fi-widget/li.fi-widget-overview) + +# 跨链测试 +下面我们将使用 ARB 和 OP 这两个 Layer2 演示 USDT 跨链 +- 软件要求 +``` +node 版本需要为 v20.11.0 +``` + +- 安装依赖 +``` +npm install +``` + +- 配置 env 文件 +```shell +cp .env.example .env +## 之后在 .env 文件中配置对应的私钥和infura +``` + +- 发起跨链请求 +``` +npx hardhat run scripts/1-crossChainTokenTransfer.js --network optim +``` + +- 检查跨链结果 +``` +npx hardhat run scripts/2-checkTokenTransferStatus.js --network optim +``` + + +## 参考文档 +- 官方文档: https://docs.li.fi/ +- 合约仓库: https://github.com/lifinance/contracts/blob/main/docs/README.md \ No newline at end of file diff --git a/basic/80-crossChainTransfer/LI.FI/contracts/IERC20.sol b/basic/80-crossChainTransfer/LI.FI/contracts/IERC20.sol new file mode 100644 index 000000000..bcd73a9b1 --- /dev/null +++ b/basic/80-crossChainTransfer/LI.FI/contracts/IERC20.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Interface of the ERC-20 standard as defined in the ERC. + */ +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 value of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the value of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); + + /** + * @dev Moves a `value` amount of tokens from `from` to `to` using the + * allowance mechanism. `value` 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 value) external returns (bool); +} \ No newline at end of file diff --git a/basic/80-crossChainTransfer/LI.FI/hardhat.config.js b/basic/80-crossChainTransfer/LI.FI/hardhat.config.js new file mode 100644 index 000000000..27b52ef9a --- /dev/null +++ b/basic/80-crossChainTransfer/LI.FI/hardhat.config.js @@ -0,0 +1,89 @@ +require("@nomicfoundation/hardhat-toolbox"); +require('dotenv').config(); + +/** @type import('hardhat/config').HardhatUserConfig */ +// module.exports = { +// solidity: "0.8.24", +// }; + + +const settings = { + optimizer: { + enabled: true, + runs: 200, + }, +}; + +function mnemonic() { + return [process.env.PRIVATE_KEY]; +} + +/** + * @type import('hardhat/config').HardhatUserConfig + */ +module.exports = { + solidity: { + compilers: [ + { version: '0.8.4', settings }, + { version: '0.4.21', settings }, + { version: '0.8.24', settings }, + ], + }, + networks: { + localhost: { + url: 'http://localhost:8545', + //gasPrice: 125000000000, // you can adjust gasPrice locally to see how much it will cost on production + /* + notice no mnemonic here? it will just use account 0 of the hardhat node to deploy + (you can put in a mnemonic here to set the deployer locally) + */ + }, + rinkeby: { + url: 'https://rinkeby.infura.io/v3/' + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work) + accounts: mnemonic(), + }, + kovan: { + url: 'https://kovan.infura.io/v3/' + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work) + accounts: mnemonic(), + }, + mainnet: { + url: 'https://mainnet.infura.io/v3/' + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work) + accounts: mnemonic(), + }, + ropsten: { + url: 'https://ropsten.infura.io/v3/' + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work) + accounts: mnemonic(), + }, + matic: { + url: 'https://polygon-mainnet.infura.io/v3/' + process.env.INFURA_ID, + accounts: mnemonic() + }, + optim: { + url: "https://optimism-mainnet.infura.io/v3/" + process.env.INFURA_ID, + accounts: mnemonic() + }, + sepolia: { + url: "https://sepolia.infura.io/v3/" + process.env.INFURA_ID, + accounts: mnemonic() + }, + arbitrum: { + url: "https://arbitrum-mainnet.infura.io/v3/" + process.env.INFURA_ID, + accounts: mnemonic() + }, + scroll: { + url: "https://rpc.scroll.io", + accounts: mnemonic() + }, + optim_sepolia: { + url: "https://optimism-sepolia.infura.io/v3/" + process.env.INFURA_ID, + accounts: mnemonic() + }, + + }, + mocha: { + timeout: 200000 + }, + sourcify: { + enabled: true + }, +}; diff --git a/basic/80-crossChainTransfer/LI.FI/package.json b/basic/80-crossChainTransfer/LI.FI/package.json new file mode 100644 index 000000000..cc03c5919 --- /dev/null +++ b/basic/80-crossChainTransfer/LI.FI/package.json @@ -0,0 +1,9 @@ +{ + "name": "hardhat-project", + "devDependencies": { + "@nomicfoundation/hardhat-toolbox": "^4.0.0", + "dotenv": "^16.4.5", + "hardhat": "^2.21.0", + "node-fetch": "^2.7.0" + } +} diff --git a/basic/80-crossChainTransfer/LI.FI/scripts/1-crossChainTokenTransfer.js b/basic/80-crossChainTransfer/LI.FI/scripts/1-crossChainTokenTransfer.js new file mode 100644 index 000000000..98252ed2a --- /dev/null +++ b/basic/80-crossChainTransfer/LI.FI/scripts/1-crossChainTokenTransfer.js @@ -0,0 +1,70 @@ +// We require the Hardhat Runtime Environment explicitly here. This is optional +// but useful for running the script in a standalone fashion through `node