From 20bf86d33fa2dea5c065a21a62a3b7c196b803e3 Mon Sep 17 00:00:00 2001 From: Andres Aiello Date: Fri, 22 Sep 2023 15:50:29 -0300 Subject: [PATCH 1/4] Improve uniswap scripts --- .../add-liquidity-zeta-uniswap.ts | 43 ++----- .../uniswap/remove-liquidity-zeta-uniswap.ts | 110 +++++++++++++++++ .../scripts/uniswap/sell-token.ts | 111 ++++++++++++++++++ .../scripts/uniswap/sell-zeta.ts | 93 +++++++++++++++ .../scripts/uniswap/uniswap.helpers.ts | 55 +++++++++ 5 files changed, 377 insertions(+), 35 deletions(-) rename packages/zevm-app-contracts/scripts/{zeta-swap => uniswap}/add-liquidity-zeta-uniswap.ts (82%) create mode 100644 packages/zevm-app-contracts/scripts/uniswap/remove-liquidity-zeta-uniswap.ts create mode 100644 packages/zevm-app-contracts/scripts/uniswap/sell-token.ts create mode 100644 packages/zevm-app-contracts/scripts/uniswap/sell-zeta.ts create mode 100644 packages/zevm-app-contracts/scripts/uniswap/uniswap.helpers.ts diff --git a/packages/zevm-app-contracts/scripts/zeta-swap/add-liquidity-zeta-uniswap.ts b/packages/zevm-app-contracts/scripts/uniswap/add-liquidity-zeta-uniswap.ts similarity index 82% rename from packages/zevm-app-contracts/scripts/zeta-swap/add-liquidity-zeta-uniswap.ts rename to packages/zevm-app-contracts/scripts/uniswap/add-liquidity-zeta-uniswap.ts index 787f8d69..32731630 100644 --- a/packages/zevm-app-contracts/scripts/zeta-swap/add-liquidity-zeta-uniswap.ts +++ b/packages/zevm-app-contracts/scripts/uniswap/add-liquidity-zeta-uniswap.ts @@ -17,33 +17,17 @@ import { SystemContract__factory, UniswapV2Router02__factory } from "../../typechain-types"; +import { getNow, printReserves, sortPair } from "./uniswap.helpers"; const SYSTEM_CONTRACT = getSystemContractAddress(); const BTC_TO_ADD = parseUnits("0", 8); -const ETH_TO_ADD = parseUnits("1500"); -const MATIC_TO_ADD = parseUnits("1500"); -const BNB_TO_ADD = parseUnits("100"); +const ETH_TO_ADD = parseUnits("0"); +const MATIC_TO_ADD = parseUnits("0"); +const BNB_TO_ADD = parseUnits("0"); const ZETA_TO_ADD = parseUnits("0"); -interface Pair { - TokenA: string; - TokenB: string; -} - -export const getNow = async () => { - const block = await ethers.provider.getBlock("latest"); - return block.timestamp; -}; - -export const sortPair = (token1: string, token2: string): Pair => { - if (token1 < token2) { - return { TokenA: token1, TokenB: token2 }; - } - return { TokenA: token2, TokenB: token1 }; -}; - const addTokenEthLiquidity = async ( tokenContract: ERC20, tokenAmountToAdd: BigNumber, @@ -54,6 +38,8 @@ const addTokenEthLiquidity = async ( const tx1 = await tokenContract.approve(uniswapRouter.address, MaxUint256); await tx1.wait(); + console.log("Uniswap approved to consume token..."); + const tx2 = await uniswapRouter.addLiquidityETH( tokenContract.address, tokenAmountToAdd, @@ -89,13 +75,6 @@ const estimateZetaForToken = async ( const ZETAValue = reservesZETA.mul(tokenAmountToAdd).div(reservesToken); - const tokenDecimals = await tokenContract.decimals(); - console.log( - `Zeta/${getGasSymbolByNetwork(network)} reserves ${formatUnits(reservesZETA)}/${formatUnits( - reservesToken, - tokenDecimals - )}` - ); return ZETAValue; }; @@ -116,7 +95,6 @@ async function addLiquidity( const tokenAddress = await systemContract.gasCoinZRC20ByChainId(getChainId(network)); const tokenContract = ERC20__factory.connect(tokenAddress, deployer); - const tokenDecimals = await tokenContract.decimals(); const zetaToAdd = initLiquidityPool ? ZETA_TO_ADD @@ -129,14 +107,9 @@ async function addLiquidity( deployer ); - console.log( - `Zeta/${getGasSymbolByNetwork(network)} to add ${formatUnits(zetaToAdd)}/${formatUnits( - tokenAmountToAdd, - tokenDecimals - )}` - ); - + await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); // await addTokenEthLiquidity(tokenContract, tokenAmountToAdd, zetaToAdd, uniswapRouter, deployer); + await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); } async function main() { const WZETA_ADDRESS = getAddress({ diff --git a/packages/zevm-app-contracts/scripts/uniswap/remove-liquidity-zeta-uniswap.ts b/packages/zevm-app-contracts/scripts/uniswap/remove-liquidity-zeta-uniswap.ts new file mode 100644 index 00000000..896f0293 --- /dev/null +++ b/packages/zevm-app-contracts/scripts/uniswap/remove-liquidity-zeta-uniswap.ts @@ -0,0 +1,110 @@ +import { MaxUint256 } from "@ethersproject/constants"; +import { formatUnits } from "@ethersproject/units"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { getChainId } from "@zetachain/addresses"; +import { NetworkName } from "@zetachain/addresses"; +import { getAddress } from "@zetachain/addresses"; +import { getSystemContractAddress } from "@zetachain/addresses-tools"; +import { BigNumber } from "ethers"; +import { ethers } from "hardhat"; + +import { + ERC20, + ERC20__factory, + IUniswapV2Factory__factory, + IUniswapV2Pair, + IUniswapV2Pair__factory, + IUniswapV2Router02, + SystemContract__factory, + UniswapV2Router02__factory +} from "../../typechain-types"; +import { getNow, printReserves, sortPair } from "./uniswap.helpers"; + +const SYSTEM_CONTRACT = getSystemContractAddress(); + +const removeTokenEthLiquidity = async ( + tokenContract: ERC20, + LPContract: IUniswapV2Pair, + LPAmountToRemove: BigNumber, + uniswapRouter: IUniswapV2Router02, + deployer: SignerWithAddress +) => { + const tx1 = await LPContract.approve(uniswapRouter.address, MaxUint256); + await tx1.wait(); + + console.log("Uniswap approved to consume LP..."); + + const tx2 = await uniswapRouter.removeLiquidityETH( + tokenContract.address, + LPAmountToRemove, + 0, + 0, + deployer.address, + (await getNow()) + 360, + { gasLimit: 10_000_000 } + ); + await tx2.wait(); +}; + +async function removeLiquidity( + network: NetworkName, + WZETAAddress: string, + uniswapFactoryAddress: string, + uniswapRouterAddress: string +) { + console.log(`Removing liquidity for: ${network}`); + + const [deployer] = await ethers.getSigners(); + + const systemContract = await SystemContract__factory.connect(SYSTEM_CONTRACT, deployer); + const uniswapV2Factory = IUniswapV2Factory__factory.connect(uniswapFactoryAddress, deployer); + const uniswapRouter = await UniswapV2Router02__factory.connect(uniswapRouterAddress, deployer); + + const tokenAddress = await systemContract.gasCoinZRC20ByChainId(getChainId(network)); + const tokenContract = ERC20__factory.connect(tokenAddress, deployer); + + const pair = sortPair(tokenAddress, WZETAAddress); + + const poolAddress = await uniswapV2Factory.getPair(pair.TokenA, pair.TokenB); + + const pool = IUniswapV2Pair__factory.connect(poolAddress, deployer); + + const LPBalance = await pool.balanceOf(deployer.address); + + console.log(`LP Balance: ${formatUnits(LPBalance, 18)} for ${poolAddress}`); + + await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); + // await removeTokenEthLiquidity(tokenContract, pool, LPBalance, uniswapRouter, deployer); + await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); +} +async function main() { + const WZETA_ADDRESS = getAddress({ + address: "weth9", + networkName: "athens", + zetaNetwork: "athens" + }); + + const UNISWAP_FACTORY_ADDRESS = getAddress({ + address: "uniswapV2Factory", + networkName: "athens", + zetaNetwork: "athens" + }); + + const UNISWAP_ROUTER_ADDRESS = getAddress({ + address: "uniswapV2Router02", + networkName: "athens", + zetaNetwork: "athens" + }); + + await removeLiquidity("goerli", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + await removeLiquidity("polygon-mumbai", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + await removeLiquidity("bsc-testnet", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + await removeLiquidity("bitcoin-test", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); diff --git a/packages/zevm-app-contracts/scripts/uniswap/sell-token.ts b/packages/zevm-app-contracts/scripts/uniswap/sell-token.ts new file mode 100644 index 00000000..6d8ed6ea --- /dev/null +++ b/packages/zevm-app-contracts/scripts/uniswap/sell-token.ts @@ -0,0 +1,111 @@ +import { MaxUint256 } from "@ethersproject/constants"; +import { formatUnits, parseUnits } from "@ethersproject/units"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { getChainId } from "@zetachain/addresses"; +import { NetworkName } from "@zetachain/addresses"; +import { getAddress } from "@zetachain/addresses"; +import { getSystemContractAddress } from "@zetachain/addresses-tools"; +import { BigNumber } from "ethers"; +import { ethers } from "hardhat"; + +import { + ERC20, + ERC20__factory, + IUniswapV2Router02, + SystemContract__factory, + UniswapV2Router02__factory +} from "../../typechain-types"; +import { getNow, printReserves } from "./uniswap.helpers"; + +const SYSTEM_CONTRACT = getSystemContractAddress(); + +const BTC_TO_SELL = parseUnits("0", 8); +const ETH_TO_SELL = parseUnits("0"); +const MATIC_TO_SELL = parseUnits("0"); +const BNB_TO_SELL = parseUnits("0"); + +const swapZeta = async ( + tokenContract: ERC20, + WZETAAddress: string, + amountIn: BigNumber, + uniswapRouter: IUniswapV2Router02, + deployer: SignerWithAddress +) => { + const tx1 = await tokenContract.approve(uniswapRouter.address, MaxUint256); + await tx1.wait(); + + console.log("Uniswap approved to consume token..."); + + const tx2 = await uniswapRouter.swapExactTokensForETH( + amountIn, + 0, + [tokenContract.address, WZETAAddress], + deployer.address, + (await getNow()) + 360, + { gasLimit: 10_000_000 } + ); + await tx2.wait(); + + console.log(`Tx hash: ${tx2.hash}`); +}; + +async function sellToken( + network: NetworkName, + tokenAmountToSell: BigNumber, + WZETAAddress: string, + uniswapFactoryAddress: string, + uniswapRouterAddress: string +) { + console.log(`Selling token on: ${network}`); + + const [deployer] = await ethers.getSigners(); + + const systemContract = await SystemContract__factory.connect(SYSTEM_CONTRACT, deployer); + const uniswapRouter = await UniswapV2Router02__factory.connect(uniswapRouterAddress, deployer); + + const tokenAddress = await systemContract.gasCoinZRC20ByChainId(getChainId(network)); + const tokenContract = ERC20__factory.connect(tokenAddress, deployer); + + await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); + // await swapZeta(tokenContract, WZETAAddress, tokenAmountToSell, uniswapRouter, deployer); + await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); +} +async function main() { + const WZETA_ADDRESS = getAddress({ + address: "weth9", + networkName: "athens", + zetaNetwork: "athens" + }); + + const UNISWAP_FACTORY_ADDRESS = getAddress({ + address: "uniswapV2Factory", + networkName: "athens", + zetaNetwork: "athens" + }); + + const UNISWAP_ROUTER_ADDRESS = getAddress({ + address: "uniswapV2Router02", + networkName: "athens", + zetaNetwork: "athens" + }); + + if (!ETH_TO_SELL.isZero()) { + await sellToken("goerli", ETH_TO_SELL, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + } + if (!MATIC_TO_SELL.isZero()) { + await sellToken("polygon-mumbai", MATIC_TO_SELL, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + } + if (!BNB_TO_SELL.isZero()) { + await sellToken("bsc-testnet", BNB_TO_SELL, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + } + if (!BTC_TO_SELL.isZero()) { + await sellToken("bitcoin-test", BTC_TO_SELL, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + } +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); diff --git a/packages/zevm-app-contracts/scripts/uniswap/sell-zeta.ts b/packages/zevm-app-contracts/scripts/uniswap/sell-zeta.ts new file mode 100644 index 00000000..f990c074 --- /dev/null +++ b/packages/zevm-app-contracts/scripts/uniswap/sell-zeta.ts @@ -0,0 +1,93 @@ +import { MaxUint256 } from "@ethersproject/constants"; +import { formatUnits, parseUnits } from "@ethersproject/units"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { getChainId } from "@zetachain/addresses"; +import { NetworkName } from "@zetachain/addresses"; +import { getAddress } from "@zetachain/addresses"; +import { getSystemContractAddress } from "@zetachain/addresses-tools"; +import { BigNumber } from "ethers"; +import { ethers } from "hardhat"; + +import { + ERC20, + ERC20__factory, + IUniswapV2Router02, + SystemContract__factory, + UniswapV2Router02__factory +} from "../../typechain-types"; +import { getNow, printReserves } from "./uniswap.helpers"; + +const SYSTEM_CONTRACT = getSystemContractAddress(); + +const ZETA_TO_SELL = parseUnits("0.001"); + +const swapZeta = async ( + tokenContract: ERC20, + WZETAAddress: string, + ZETAAmountToSell: BigNumber, + uniswapRouter: IUniswapV2Router02, + deployer: SignerWithAddress +) => { + const tx = await uniswapRouter.swapExactETHForTokens( + 0, + [WZETAAddress, tokenContract.address], + deployer.address, + (await getNow()) + 360, + { gasLimit: 10_000_000, value: ZETAAmountToSell } + ); + await tx.wait(); + + console.log(`Sell tx hash: ${tx.hash}`); +}; + +async function sellZeta( + network: NetworkName, + WZETAAddress: string, + uniswapFactoryAddress: string, + uniswapRouterAddress: string +) { + console.log(`Sell ZETA on: ${network}`); + + const [deployer] = await ethers.getSigners(); + + const systemContract = await SystemContract__factory.connect(SYSTEM_CONTRACT, deployer); + const uniswapRouter = await UniswapV2Router02__factory.connect(uniswapRouterAddress, deployer); + + const tokenAddress = await systemContract.gasCoinZRC20ByChainId(getChainId(network)); + const tokenContract = ERC20__factory.connect(tokenAddress, deployer); + + await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); + // await swapZeta(tokenContract, WZETAAddress, ZETA_TO_SELL, uniswapRouter, deployer); + await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); +} +async function main() { + const WZETA_ADDRESS = getAddress({ + address: "weth9", + networkName: "athens", + zetaNetwork: "athens" + }); + + const UNISWAP_FACTORY_ADDRESS = getAddress({ + address: "uniswapV2Factory", + networkName: "athens", + zetaNetwork: "athens" + }); + + const UNISWAP_ROUTER_ADDRESS = getAddress({ + address: "uniswapV2Router02", + networkName: "athens", + zetaNetwork: "athens" + }); + + await sellZeta("goerli", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + await sellZeta("polygon-mumbai", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + await sellZeta("bsc-testnet", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + await sellZeta("bitcoin-test", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); diff --git a/packages/zevm-app-contracts/scripts/uniswap/uniswap.helpers.ts b/packages/zevm-app-contracts/scripts/uniswap/uniswap.helpers.ts new file mode 100644 index 00000000..9fcfd3b2 --- /dev/null +++ b/packages/zevm-app-contracts/scripts/uniswap/uniswap.helpers.ts @@ -0,0 +1,55 @@ +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { formatUnits, parseUnits } from "ethers/lib/utils"; +import { ethers } from "hardhat"; + +import { IUniswapV2Factory__factory } from "../../../zevm-example-contracts/typechain-types"; +import { ERC20, IUniswapV2Pair__factory } from "../../typechain-types"; + +export interface Pair { + TokenA: string; + TokenB: string; +} + +export const getNow = async () => { + const block = await ethers.provider.getBlock("latest"); + return block.timestamp; +}; + +export const sortPair = (token1: string, token2: string): Pair => { + if (token1 < token2) { + return { TokenA: token1, TokenB: token2 }; + } + return { TokenA: token2, TokenB: token1 }; +}; + +export const printReserves = async ( + tokenContract: ERC20, + WZETAAddress: string, + uniswapFactoryAddress: string, + deployer: SignerWithAddress +) => { + const uniswapV2Factory = IUniswapV2Factory__factory.connect(uniswapFactoryAddress, deployer); + + const pair = sortPair(tokenContract.address, WZETAAddress); + + const poolAddress = await uniswapV2Factory.getPair(pair.TokenA, pair.TokenB); + + const pool = IUniswapV2Pair__factory.connect(poolAddress, deployer); + + const reserves = await pool.getReserves(); + + const reservesZETA = WZETAAddress < tokenContract.address ? reserves.reserve0 : reserves.reserve1; + const reservesToken = WZETAAddress > tokenContract.address ? reserves.reserve0 : reserves.reserve1; + + const tokenDecimals = await tokenContract.decimals(); + const reservesToken18Decimals = + 18 === tokenDecimals ? reservesToken : reservesToken.mul(parseUnits("1", 18 - tokenDecimals)); + + const ratio = reservesToken18Decimals.mul(parseUnits("1")).div(reservesZETA); + + console.log( + `Reserves ZETA: ${formatUnits(reservesZETA)} / TOKEN: ${formatUnits(reservesToken18Decimals)} / Ratio ${formatUnits( + ratio + )}` + ); +}; From b0129aee660782cbd93a75b81c50d89f0daf8a85 Mon Sep 17 00:00:00 2001 From: Andres Aiello Date: Mon, 25 Sep 2023 15:26:07 -0300 Subject: [PATCH 2/4] deploy disperse to athens --- packages/addresses/src/addresses.athens.json | 5 ++++ packages/addresses/src/addresses.helpers.ts | 2 ++ .../contracts/disperse/Disperse.sol | 24 +++++++++++++++++++ .../scripts/disperse/deploy.ts | 23 ++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 packages/zevm-app-contracts/contracts/disperse/Disperse.sol create mode 100644 packages/zevm-app-contracts/scripts/disperse/deploy.ts diff --git a/packages/addresses/src/addresses.athens.json b/packages/addresses/src/addresses.athens.json index 413e3a2d..1a408b1d 100644 --- a/packages/addresses/src/addresses.athens.json +++ b/packages/addresses/src/addresses.athens.json @@ -4,6 +4,7 @@ "crossChainCounter": "", "crossChainNft": "", "dai": "", + "disperse": "", "immutableCreate2Factory": "0x095a03c6a68137fE9a566bBc3e552F299d8b886d", "multiChainSwap": "0x8BD7144Ddb59c9Fa3Dcf809998521E9cAD946fa1", "multiChainSwapZetaConnector": "", @@ -30,6 +31,7 @@ "crossChainCounter": "", "crossChainNft": "", "dai": "", + "disperse": "", "immutableCreate2Factory": "0x095a03c6a68137fE9a566bBc3e552F299d8b886d", "multiChainSwap": "0x323745f16C93e56a98012970c28788498d8B3a14", "multiChainSwapZetaConnector": "", @@ -82,6 +84,7 @@ "crossChainCounter": "", "crossChainNft": "", "dai": "", + "disperse": "", "immutableCreate2Factory": "", "multiChainSwap": "", "multiChainValue": "", @@ -107,6 +110,7 @@ "crossChainCounter": "", "crossChainNft": "", "dai": "", + "disperse": "0x1E0F767F48Fb10FcF820703f116E9B0F87319d63", "immutableCreate2Factory": "", "multiChainSwap": "", "multiChainSwapZetaConnector": "", @@ -133,6 +137,7 @@ "crossChainCounter": "", "crossChainNft": "", "dai": "", + "disperse": "", "immutableCreate2Factory": "", "multiChainSwap": "", "multiChainSwapZetaConnector": "", diff --git a/packages/addresses/src/addresses.helpers.ts b/packages/addresses/src/addresses.helpers.ts index e3a21f84..330bd00f 100644 --- a/packages/addresses/src/addresses.helpers.ts +++ b/packages/addresses/src/addresses.helpers.ts @@ -7,6 +7,7 @@ export type ZetaAddress = | "crossChainCounter" | "crossChainNft" | "dai" + | "disperse" | "immutableCreate2Factory" | "multiChainSwap" | "multiChainSwapZetaConnector" @@ -34,6 +35,7 @@ const zetaAddresses: Record = { crossChainCounter: true, crossChainNft: true, dai: true, + disperse: true, immutableCreate2Factory: true, multiChainSwap: true, multiChainSwapZetaConnector: true, diff --git a/packages/zevm-app-contracts/contracts/disperse/Disperse.sol b/packages/zevm-app-contracts/contracts/disperse/Disperse.sol new file mode 100644 index 00000000..9adc5cec --- /dev/null +++ b/packages/zevm-app-contracts/contracts/disperse/Disperse.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.7; + +import "@openzeppelin/contracts/interfaces/IERC20.sol"; + +contract Disperse { + function disperseEther(address[] calldata recipients, uint256[] calldata values) external payable { + for (uint256 i = 0; i < recipients.length; i++) payable(recipients[i]).transfer(values[i]); + uint256 balance = address(this).balance; + if (balance > 0) payable(msg.sender).transfer(balance); + } + + function disperseToken(IERC20 token, address[] calldata recipients, uint256[] calldata values) external { + uint256 total = 0; + for (uint256 i = 0; i < recipients.length; i++) total += values[i]; + require(token.transferFrom(msg.sender, address(this), total)); + for (uint256 i = 0; i < recipients.length; i++) require(token.transfer(recipients[i], values[i])); + } + + function disperseTokenSimple(IERC20 token, address[] calldata recipients, uint256[] calldata values) external { + for (uint256 i = 0; i < recipients.length; i++) + require(token.transferFrom(msg.sender, recipients[i], values[i])); + } +} diff --git a/packages/zevm-app-contracts/scripts/disperse/deploy.ts b/packages/zevm-app-contracts/scripts/disperse/deploy.ts new file mode 100644 index 00000000..8b8a28b7 --- /dev/null +++ b/packages/zevm-app-contracts/scripts/disperse/deploy.ts @@ -0,0 +1,23 @@ +import { isNetworkName } from "@zetachain/addresses"; +import { saveAddress } from "@zetachain/addresses-tools"; +import { ethers, network } from "hardhat"; + +import { Disperse__factory } from "../../typechain-types"; + +const networkName = network.name; + +async function main() { + if (!isNetworkName(networkName)) throw new Error("Invalid network name"); + + const DisperseFactory = (await ethers.getContractFactory("Disperse")) as Disperse__factory; + + const disperseFactory = await DisperseFactory.deploy(); + await disperseFactory.deployed(); + console.log("Disperse deployed to:", disperseFactory.address); + saveAddress("disperse", disperseFactory.address); +} + +main().catch(error => { + console.error(error); + process.exit(1); +}); From 61fd69bc2b749a20f747a8bc2b8ed9e835fd78df Mon Sep 17 00:00:00 2001 From: Andres Aiello Date: Mon, 25 Sep 2023 15:30:33 -0300 Subject: [PATCH 3/4] remove uniswap scripts --- .../uniswap/add-liquidity-zeta-uniswap.ts | 152 ------------------ .../uniswap/remove-liquidity-zeta-uniswap.ts | 110 ------------- .../scripts/uniswap/sell-token.ts | 111 ------------- .../scripts/uniswap/sell-zeta.ts | 93 ----------- .../scripts/uniswap/uniswap.helpers.ts | 55 ------- 5 files changed, 521 deletions(-) delete mode 100644 packages/zevm-app-contracts/scripts/uniswap/add-liquidity-zeta-uniswap.ts delete mode 100644 packages/zevm-app-contracts/scripts/uniswap/remove-liquidity-zeta-uniswap.ts delete mode 100644 packages/zevm-app-contracts/scripts/uniswap/sell-token.ts delete mode 100644 packages/zevm-app-contracts/scripts/uniswap/sell-zeta.ts delete mode 100644 packages/zevm-app-contracts/scripts/uniswap/uniswap.helpers.ts diff --git a/packages/zevm-app-contracts/scripts/uniswap/add-liquidity-zeta-uniswap.ts b/packages/zevm-app-contracts/scripts/uniswap/add-liquidity-zeta-uniswap.ts deleted file mode 100644 index 32731630..00000000 --- a/packages/zevm-app-contracts/scripts/uniswap/add-liquidity-zeta-uniswap.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { MaxUint256 } from "@ethersproject/constants"; -import { formatUnits, parseUnits } from "@ethersproject/units"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { getChainId } from "@zetachain/addresses"; -import { NetworkName } from "@zetachain/addresses"; -import { getAddress } from "@zetachain/addresses"; -import { getGasSymbolByNetwork, getSystemContractAddress } from "@zetachain/addresses-tools"; -import { BigNumber } from "ethers"; -import { ethers } from "hardhat"; - -import { - ERC20, - ERC20__factory, - IUniswapV2Factory__factory, - IUniswapV2Pair__factory, - IUniswapV2Router02, - SystemContract__factory, - UniswapV2Router02__factory -} from "../../typechain-types"; -import { getNow, printReserves, sortPair } from "./uniswap.helpers"; - -const SYSTEM_CONTRACT = getSystemContractAddress(); - -const BTC_TO_ADD = parseUnits("0", 8); -const ETH_TO_ADD = parseUnits("0"); -const MATIC_TO_ADD = parseUnits("0"); -const BNB_TO_ADD = parseUnits("0"); - -const ZETA_TO_ADD = parseUnits("0"); - -const addTokenEthLiquidity = async ( - tokenContract: ERC20, - tokenAmountToAdd: BigNumber, - ETHToAdd: BigNumber, - uniswapRouter: IUniswapV2Router02, - deployer: SignerWithAddress -) => { - const tx1 = await tokenContract.approve(uniswapRouter.address, MaxUint256); - await tx1.wait(); - - console.log("Uniswap approved to consume token..."); - - const tx2 = await uniswapRouter.addLiquidityETH( - tokenContract.address, - tokenAmountToAdd, - 0, - 0, - deployer.address, - (await getNow()) + 360, - { gasLimit: 10_000_000, value: ETHToAdd } - ); - await tx2.wait(); -}; - -const estimateZetaForToken = async ( - network: NetworkName, - WZETAAddress: string, - uniswapFactoryAddress: string, - tokenContract: ERC20, - tokenAmountToAdd: BigNumber, - deployer: SignerWithAddress -) => { - const uniswapV2Factory = IUniswapV2Factory__factory.connect(uniswapFactoryAddress, deployer); - - const pair = sortPair(tokenContract.address, WZETAAddress); - - const poolAddress = await uniswapV2Factory.getPair(pair.TokenA, pair.TokenB); - - const pool = IUniswapV2Pair__factory.connect(poolAddress, deployer); - - const reserves = await pool.getReserves(); - - const reservesZETA = WZETAAddress < tokenContract.address ? reserves.reserve0 : reserves.reserve1; - const reservesToken = WZETAAddress > tokenContract.address ? reserves.reserve0 : reserves.reserve1; - - const ZETAValue = reservesZETA.mul(tokenAmountToAdd).div(reservesToken); - - return ZETAValue; -}; - -async function addLiquidity( - network: NetworkName, - tokenAmountToAdd: BigNumber, - WZETAAddress: string, - uniswapFactoryAddress: string, - uniswapRouterAddress: string -) { - console.log(`Adding liquidity for: ${network}`); - const initLiquidityPool = !ZETA_TO_ADD.isZero(); - - const [deployer] = await ethers.getSigners(); - - const systemContract = await SystemContract__factory.connect(SYSTEM_CONTRACT, deployer); - const uniswapRouter = await UniswapV2Router02__factory.connect(uniswapRouterAddress, deployer); - - const tokenAddress = await systemContract.gasCoinZRC20ByChainId(getChainId(network)); - const tokenContract = ERC20__factory.connect(tokenAddress, deployer); - - const zetaToAdd = initLiquidityPool - ? ZETA_TO_ADD - : await estimateZetaForToken( - network, - WZETAAddress, - uniswapFactoryAddress, - tokenContract, - tokenAmountToAdd, - deployer - ); - - await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); - // await addTokenEthLiquidity(tokenContract, tokenAmountToAdd, zetaToAdd, uniswapRouter, deployer); - await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); -} -async function main() { - const WZETA_ADDRESS = getAddress({ - address: "weth9", - networkName: "athens", - zetaNetwork: "athens" - }); - - const UNISWAP_FACTORY_ADDRESS = getAddress({ - address: "uniswapV2Factory", - networkName: "athens", - zetaNetwork: "athens" - }); - - const UNISWAP_ROUTER_ADDRESS = getAddress({ - address: "uniswapV2Router02", - networkName: "athens", - zetaNetwork: "athens" - }); - - if (!ETH_TO_ADD.isZero()) { - await addLiquidity("goerli", ETH_TO_ADD, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - } - if (!MATIC_TO_ADD.isZero()) { - await addLiquidity("polygon-mumbai", MATIC_TO_ADD, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - } - if (!BNB_TO_ADD.isZero()) { - await addLiquidity("bsc-testnet", BNB_TO_ADD, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - } - if (!BTC_TO_ADD.isZero()) { - await addLiquidity("bitcoin-test", BTC_TO_ADD, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - } -} - -main() - .then(() => process.exit(0)) - .catch(error => { - console.error(error); - process.exit(1); - }); diff --git a/packages/zevm-app-contracts/scripts/uniswap/remove-liquidity-zeta-uniswap.ts b/packages/zevm-app-contracts/scripts/uniswap/remove-liquidity-zeta-uniswap.ts deleted file mode 100644 index 896f0293..00000000 --- a/packages/zevm-app-contracts/scripts/uniswap/remove-liquidity-zeta-uniswap.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { MaxUint256 } from "@ethersproject/constants"; -import { formatUnits } from "@ethersproject/units"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { getChainId } from "@zetachain/addresses"; -import { NetworkName } from "@zetachain/addresses"; -import { getAddress } from "@zetachain/addresses"; -import { getSystemContractAddress } from "@zetachain/addresses-tools"; -import { BigNumber } from "ethers"; -import { ethers } from "hardhat"; - -import { - ERC20, - ERC20__factory, - IUniswapV2Factory__factory, - IUniswapV2Pair, - IUniswapV2Pair__factory, - IUniswapV2Router02, - SystemContract__factory, - UniswapV2Router02__factory -} from "../../typechain-types"; -import { getNow, printReserves, sortPair } from "./uniswap.helpers"; - -const SYSTEM_CONTRACT = getSystemContractAddress(); - -const removeTokenEthLiquidity = async ( - tokenContract: ERC20, - LPContract: IUniswapV2Pair, - LPAmountToRemove: BigNumber, - uniswapRouter: IUniswapV2Router02, - deployer: SignerWithAddress -) => { - const tx1 = await LPContract.approve(uniswapRouter.address, MaxUint256); - await tx1.wait(); - - console.log("Uniswap approved to consume LP..."); - - const tx2 = await uniswapRouter.removeLiquidityETH( - tokenContract.address, - LPAmountToRemove, - 0, - 0, - deployer.address, - (await getNow()) + 360, - { gasLimit: 10_000_000 } - ); - await tx2.wait(); -}; - -async function removeLiquidity( - network: NetworkName, - WZETAAddress: string, - uniswapFactoryAddress: string, - uniswapRouterAddress: string -) { - console.log(`Removing liquidity for: ${network}`); - - const [deployer] = await ethers.getSigners(); - - const systemContract = await SystemContract__factory.connect(SYSTEM_CONTRACT, deployer); - const uniswapV2Factory = IUniswapV2Factory__factory.connect(uniswapFactoryAddress, deployer); - const uniswapRouter = await UniswapV2Router02__factory.connect(uniswapRouterAddress, deployer); - - const tokenAddress = await systemContract.gasCoinZRC20ByChainId(getChainId(network)); - const tokenContract = ERC20__factory.connect(tokenAddress, deployer); - - const pair = sortPair(tokenAddress, WZETAAddress); - - const poolAddress = await uniswapV2Factory.getPair(pair.TokenA, pair.TokenB); - - const pool = IUniswapV2Pair__factory.connect(poolAddress, deployer); - - const LPBalance = await pool.balanceOf(deployer.address); - - console.log(`LP Balance: ${formatUnits(LPBalance, 18)} for ${poolAddress}`); - - await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); - // await removeTokenEthLiquidity(tokenContract, pool, LPBalance, uniswapRouter, deployer); - await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); -} -async function main() { - const WZETA_ADDRESS = getAddress({ - address: "weth9", - networkName: "athens", - zetaNetwork: "athens" - }); - - const UNISWAP_FACTORY_ADDRESS = getAddress({ - address: "uniswapV2Factory", - networkName: "athens", - zetaNetwork: "athens" - }); - - const UNISWAP_ROUTER_ADDRESS = getAddress({ - address: "uniswapV2Router02", - networkName: "athens", - zetaNetwork: "athens" - }); - - await removeLiquidity("goerli", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - await removeLiquidity("polygon-mumbai", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - await removeLiquidity("bsc-testnet", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - await removeLiquidity("bitcoin-test", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); -} - -main() - .then(() => process.exit(0)) - .catch(error => { - console.error(error); - process.exit(1); - }); diff --git a/packages/zevm-app-contracts/scripts/uniswap/sell-token.ts b/packages/zevm-app-contracts/scripts/uniswap/sell-token.ts deleted file mode 100644 index 6d8ed6ea..00000000 --- a/packages/zevm-app-contracts/scripts/uniswap/sell-token.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { MaxUint256 } from "@ethersproject/constants"; -import { formatUnits, parseUnits } from "@ethersproject/units"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { getChainId } from "@zetachain/addresses"; -import { NetworkName } from "@zetachain/addresses"; -import { getAddress } from "@zetachain/addresses"; -import { getSystemContractAddress } from "@zetachain/addresses-tools"; -import { BigNumber } from "ethers"; -import { ethers } from "hardhat"; - -import { - ERC20, - ERC20__factory, - IUniswapV2Router02, - SystemContract__factory, - UniswapV2Router02__factory -} from "../../typechain-types"; -import { getNow, printReserves } from "./uniswap.helpers"; - -const SYSTEM_CONTRACT = getSystemContractAddress(); - -const BTC_TO_SELL = parseUnits("0", 8); -const ETH_TO_SELL = parseUnits("0"); -const MATIC_TO_SELL = parseUnits("0"); -const BNB_TO_SELL = parseUnits("0"); - -const swapZeta = async ( - tokenContract: ERC20, - WZETAAddress: string, - amountIn: BigNumber, - uniswapRouter: IUniswapV2Router02, - deployer: SignerWithAddress -) => { - const tx1 = await tokenContract.approve(uniswapRouter.address, MaxUint256); - await tx1.wait(); - - console.log("Uniswap approved to consume token..."); - - const tx2 = await uniswapRouter.swapExactTokensForETH( - amountIn, - 0, - [tokenContract.address, WZETAAddress], - deployer.address, - (await getNow()) + 360, - { gasLimit: 10_000_000 } - ); - await tx2.wait(); - - console.log(`Tx hash: ${tx2.hash}`); -}; - -async function sellToken( - network: NetworkName, - tokenAmountToSell: BigNumber, - WZETAAddress: string, - uniswapFactoryAddress: string, - uniswapRouterAddress: string -) { - console.log(`Selling token on: ${network}`); - - const [deployer] = await ethers.getSigners(); - - const systemContract = await SystemContract__factory.connect(SYSTEM_CONTRACT, deployer); - const uniswapRouter = await UniswapV2Router02__factory.connect(uniswapRouterAddress, deployer); - - const tokenAddress = await systemContract.gasCoinZRC20ByChainId(getChainId(network)); - const tokenContract = ERC20__factory.connect(tokenAddress, deployer); - - await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); - // await swapZeta(tokenContract, WZETAAddress, tokenAmountToSell, uniswapRouter, deployer); - await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); -} -async function main() { - const WZETA_ADDRESS = getAddress({ - address: "weth9", - networkName: "athens", - zetaNetwork: "athens" - }); - - const UNISWAP_FACTORY_ADDRESS = getAddress({ - address: "uniswapV2Factory", - networkName: "athens", - zetaNetwork: "athens" - }); - - const UNISWAP_ROUTER_ADDRESS = getAddress({ - address: "uniswapV2Router02", - networkName: "athens", - zetaNetwork: "athens" - }); - - if (!ETH_TO_SELL.isZero()) { - await sellToken("goerli", ETH_TO_SELL, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - } - if (!MATIC_TO_SELL.isZero()) { - await sellToken("polygon-mumbai", MATIC_TO_SELL, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - } - if (!BNB_TO_SELL.isZero()) { - await sellToken("bsc-testnet", BNB_TO_SELL, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - } - if (!BTC_TO_SELL.isZero()) { - await sellToken("bitcoin-test", BTC_TO_SELL, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - } -} - -main() - .then(() => process.exit(0)) - .catch(error => { - console.error(error); - process.exit(1); - }); diff --git a/packages/zevm-app-contracts/scripts/uniswap/sell-zeta.ts b/packages/zevm-app-contracts/scripts/uniswap/sell-zeta.ts deleted file mode 100644 index f990c074..00000000 --- a/packages/zevm-app-contracts/scripts/uniswap/sell-zeta.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { MaxUint256 } from "@ethersproject/constants"; -import { formatUnits, parseUnits } from "@ethersproject/units"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { getChainId } from "@zetachain/addresses"; -import { NetworkName } from "@zetachain/addresses"; -import { getAddress } from "@zetachain/addresses"; -import { getSystemContractAddress } from "@zetachain/addresses-tools"; -import { BigNumber } from "ethers"; -import { ethers } from "hardhat"; - -import { - ERC20, - ERC20__factory, - IUniswapV2Router02, - SystemContract__factory, - UniswapV2Router02__factory -} from "../../typechain-types"; -import { getNow, printReserves } from "./uniswap.helpers"; - -const SYSTEM_CONTRACT = getSystemContractAddress(); - -const ZETA_TO_SELL = parseUnits("0.001"); - -const swapZeta = async ( - tokenContract: ERC20, - WZETAAddress: string, - ZETAAmountToSell: BigNumber, - uniswapRouter: IUniswapV2Router02, - deployer: SignerWithAddress -) => { - const tx = await uniswapRouter.swapExactETHForTokens( - 0, - [WZETAAddress, tokenContract.address], - deployer.address, - (await getNow()) + 360, - { gasLimit: 10_000_000, value: ZETAAmountToSell } - ); - await tx.wait(); - - console.log(`Sell tx hash: ${tx.hash}`); -}; - -async function sellZeta( - network: NetworkName, - WZETAAddress: string, - uniswapFactoryAddress: string, - uniswapRouterAddress: string -) { - console.log(`Sell ZETA on: ${network}`); - - const [deployer] = await ethers.getSigners(); - - const systemContract = await SystemContract__factory.connect(SYSTEM_CONTRACT, deployer); - const uniswapRouter = await UniswapV2Router02__factory.connect(uniswapRouterAddress, deployer); - - const tokenAddress = await systemContract.gasCoinZRC20ByChainId(getChainId(network)); - const tokenContract = ERC20__factory.connect(tokenAddress, deployer); - - await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); - // await swapZeta(tokenContract, WZETAAddress, ZETA_TO_SELL, uniswapRouter, deployer); - await printReserves(tokenContract, WZETAAddress, uniswapFactoryAddress, deployer); -} -async function main() { - const WZETA_ADDRESS = getAddress({ - address: "weth9", - networkName: "athens", - zetaNetwork: "athens" - }); - - const UNISWAP_FACTORY_ADDRESS = getAddress({ - address: "uniswapV2Factory", - networkName: "athens", - zetaNetwork: "athens" - }); - - const UNISWAP_ROUTER_ADDRESS = getAddress({ - address: "uniswapV2Router02", - networkName: "athens", - zetaNetwork: "athens" - }); - - await sellZeta("goerli", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - await sellZeta("polygon-mumbai", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - await sellZeta("bsc-testnet", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); - await sellZeta("bitcoin-test", WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); -} - -main() - .then(() => process.exit(0)) - .catch(error => { - console.error(error); - process.exit(1); - }); diff --git a/packages/zevm-app-contracts/scripts/uniswap/uniswap.helpers.ts b/packages/zevm-app-contracts/scripts/uniswap/uniswap.helpers.ts deleted file mode 100644 index 9fcfd3b2..00000000 --- a/packages/zevm-app-contracts/scripts/uniswap/uniswap.helpers.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { formatUnits, parseUnits } from "ethers/lib/utils"; -import { ethers } from "hardhat"; - -import { IUniswapV2Factory__factory } from "../../../zevm-example-contracts/typechain-types"; -import { ERC20, IUniswapV2Pair__factory } from "../../typechain-types"; - -export interface Pair { - TokenA: string; - TokenB: string; -} - -export const getNow = async () => { - const block = await ethers.provider.getBlock("latest"); - return block.timestamp; -}; - -export const sortPair = (token1: string, token2: string): Pair => { - if (token1 < token2) { - return { TokenA: token1, TokenB: token2 }; - } - return { TokenA: token2, TokenB: token1 }; -}; - -export const printReserves = async ( - tokenContract: ERC20, - WZETAAddress: string, - uniswapFactoryAddress: string, - deployer: SignerWithAddress -) => { - const uniswapV2Factory = IUniswapV2Factory__factory.connect(uniswapFactoryAddress, deployer); - - const pair = sortPair(tokenContract.address, WZETAAddress); - - const poolAddress = await uniswapV2Factory.getPair(pair.TokenA, pair.TokenB); - - const pool = IUniswapV2Pair__factory.connect(poolAddress, deployer); - - const reserves = await pool.getReserves(); - - const reservesZETA = WZETAAddress < tokenContract.address ? reserves.reserve0 : reserves.reserve1; - const reservesToken = WZETAAddress > tokenContract.address ? reserves.reserve0 : reserves.reserve1; - - const tokenDecimals = await tokenContract.decimals(); - const reservesToken18Decimals = - 18 === tokenDecimals ? reservesToken : reservesToken.mul(parseUnits("1", 18 - tokenDecimals)); - - const ratio = reservesToken18Decimals.mul(parseUnits("1")).div(reservesZETA); - - console.log( - `Reserves ZETA: ${formatUnits(reservesZETA)} / TOKEN: ${formatUnits(reservesToken18Decimals)} / Ratio ${formatUnits( - ratio - )}` - ); -}; From 5c10e65410211581c37348852e00db202df77e5b Mon Sep 17 00:00:00 2001 From: Andres Aiello Date: Mon, 25 Sep 2023 15:31:10 -0300 Subject: [PATCH 4/4] restore script --- .../zeta-swap/add-liquidity-zeta-uniswap.ts | 179 ++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 packages/zevm-app-contracts/scripts/zeta-swap/add-liquidity-zeta-uniswap.ts diff --git a/packages/zevm-app-contracts/scripts/zeta-swap/add-liquidity-zeta-uniswap.ts b/packages/zevm-app-contracts/scripts/zeta-swap/add-liquidity-zeta-uniswap.ts new file mode 100644 index 00000000..787f8d69 --- /dev/null +++ b/packages/zevm-app-contracts/scripts/zeta-swap/add-liquidity-zeta-uniswap.ts @@ -0,0 +1,179 @@ +import { MaxUint256 } from "@ethersproject/constants"; +import { formatUnits, parseUnits } from "@ethersproject/units"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { getChainId } from "@zetachain/addresses"; +import { NetworkName } from "@zetachain/addresses"; +import { getAddress } from "@zetachain/addresses"; +import { getGasSymbolByNetwork, getSystemContractAddress } from "@zetachain/addresses-tools"; +import { BigNumber } from "ethers"; +import { ethers } from "hardhat"; + +import { + ERC20, + ERC20__factory, + IUniswapV2Factory__factory, + IUniswapV2Pair__factory, + IUniswapV2Router02, + SystemContract__factory, + UniswapV2Router02__factory +} from "../../typechain-types"; + +const SYSTEM_CONTRACT = getSystemContractAddress(); + +const BTC_TO_ADD = parseUnits("0", 8); +const ETH_TO_ADD = parseUnits("1500"); +const MATIC_TO_ADD = parseUnits("1500"); +const BNB_TO_ADD = parseUnits("100"); + +const ZETA_TO_ADD = parseUnits("0"); + +interface Pair { + TokenA: string; + TokenB: string; +} + +export const getNow = async () => { + const block = await ethers.provider.getBlock("latest"); + return block.timestamp; +}; + +export const sortPair = (token1: string, token2: string): Pair => { + if (token1 < token2) { + return { TokenA: token1, TokenB: token2 }; + } + return { TokenA: token2, TokenB: token1 }; +}; + +const addTokenEthLiquidity = async ( + tokenContract: ERC20, + tokenAmountToAdd: BigNumber, + ETHToAdd: BigNumber, + uniswapRouter: IUniswapV2Router02, + deployer: SignerWithAddress +) => { + const tx1 = await tokenContract.approve(uniswapRouter.address, MaxUint256); + await tx1.wait(); + + const tx2 = await uniswapRouter.addLiquidityETH( + tokenContract.address, + tokenAmountToAdd, + 0, + 0, + deployer.address, + (await getNow()) + 360, + { gasLimit: 10_000_000, value: ETHToAdd } + ); + await tx2.wait(); +}; + +const estimateZetaForToken = async ( + network: NetworkName, + WZETAAddress: string, + uniswapFactoryAddress: string, + tokenContract: ERC20, + tokenAmountToAdd: BigNumber, + deployer: SignerWithAddress +) => { + const uniswapV2Factory = IUniswapV2Factory__factory.connect(uniswapFactoryAddress, deployer); + + const pair = sortPair(tokenContract.address, WZETAAddress); + + const poolAddress = await uniswapV2Factory.getPair(pair.TokenA, pair.TokenB); + + const pool = IUniswapV2Pair__factory.connect(poolAddress, deployer); + + const reserves = await pool.getReserves(); + + const reservesZETA = WZETAAddress < tokenContract.address ? reserves.reserve0 : reserves.reserve1; + const reservesToken = WZETAAddress > tokenContract.address ? reserves.reserve0 : reserves.reserve1; + + const ZETAValue = reservesZETA.mul(tokenAmountToAdd).div(reservesToken); + + const tokenDecimals = await tokenContract.decimals(); + console.log( + `Zeta/${getGasSymbolByNetwork(network)} reserves ${formatUnits(reservesZETA)}/${formatUnits( + reservesToken, + tokenDecimals + )}` + ); + return ZETAValue; +}; + +async function addLiquidity( + network: NetworkName, + tokenAmountToAdd: BigNumber, + WZETAAddress: string, + uniswapFactoryAddress: string, + uniswapRouterAddress: string +) { + console.log(`Adding liquidity for: ${network}`); + const initLiquidityPool = !ZETA_TO_ADD.isZero(); + + const [deployer] = await ethers.getSigners(); + + const systemContract = await SystemContract__factory.connect(SYSTEM_CONTRACT, deployer); + const uniswapRouter = await UniswapV2Router02__factory.connect(uniswapRouterAddress, deployer); + + const tokenAddress = await systemContract.gasCoinZRC20ByChainId(getChainId(network)); + const tokenContract = ERC20__factory.connect(tokenAddress, deployer); + const tokenDecimals = await tokenContract.decimals(); + + const zetaToAdd = initLiquidityPool + ? ZETA_TO_ADD + : await estimateZetaForToken( + network, + WZETAAddress, + uniswapFactoryAddress, + tokenContract, + tokenAmountToAdd, + deployer + ); + + console.log( + `Zeta/${getGasSymbolByNetwork(network)} to add ${formatUnits(zetaToAdd)}/${formatUnits( + tokenAmountToAdd, + tokenDecimals + )}` + ); + + // await addTokenEthLiquidity(tokenContract, tokenAmountToAdd, zetaToAdd, uniswapRouter, deployer); +} +async function main() { + const WZETA_ADDRESS = getAddress({ + address: "weth9", + networkName: "athens", + zetaNetwork: "athens" + }); + + const UNISWAP_FACTORY_ADDRESS = getAddress({ + address: "uniswapV2Factory", + networkName: "athens", + zetaNetwork: "athens" + }); + + const UNISWAP_ROUTER_ADDRESS = getAddress({ + address: "uniswapV2Router02", + networkName: "athens", + zetaNetwork: "athens" + }); + + if (!ETH_TO_ADD.isZero()) { + await addLiquidity("goerli", ETH_TO_ADD, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + } + if (!MATIC_TO_ADD.isZero()) { + await addLiquidity("polygon-mumbai", MATIC_TO_ADD, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + } + if (!BNB_TO_ADD.isZero()) { + await addLiquidity("bsc-testnet", BNB_TO_ADD, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + } + if (!BTC_TO_ADD.isZero()) { + await addLiquidity("bitcoin-test", BTC_TO_ADD, WZETA_ADDRESS, UNISWAP_FACTORY_ADDRESS, UNISWAP_ROUTER_ADDRESS); + } +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + });