├── .solhintignore ├── .prettierrc ├── .eslintignore ├── .prettierignore ├── .vscode └── settings.json ├── .npmignore ├── contracts ├── test │ ├── imports.sol │ ├── SampleContract.sol │ ├── ERC20Token.sol │ ├── LiquidityProvidersTest.sol │ ├── TokenMintingReentrancy.sol │ ├── LiquidityProvidersMaliciousReentrant.sol │ ├── BatchHelper.sol │ └── CCMPGatewayMock.sol ├── hyphen │ ├── interfaces │ │ ├── IWETH.sol │ │ ├── IERC20WithDecimals.sol │ │ ├── ISwapAdaptor.sol │ │ ├── ICCMPGateway.sol │ │ ├── IExecutorManager.sol │ │ ├── ISvgHelper.sol │ │ ├── IUniswapV3SwapCallback.sol │ │ ├── ILiquidityPool.sol │ │ ├── ITokenManager.sol │ │ ├── IWhiteListPeriodManager.sol │ │ ├── ILiquidityProviders.sol │ │ ├── IERC20.sol │ │ ├── ILPToken.sol │ │ ├── ISwapRouter.sol │ │ └── IHyphenLiquidityFarmingV2.sol │ ├── structures │ │ ├── LpTokenMetadata.sol │ │ ├── SwapRequest.sol │ │ ├── TokenConfig.sol │ │ └── DepositAndCall.sol │ ├── mock │ │ ├── MockSwapRouter_Fail.sol │ │ ├── MockSwapRouter.sol │ │ ├── MockAdaptorFail.sol │ │ └── MockAdaptor.sol │ ├── metatx │ │ ├── ERC2771Context.sol │ │ └── ERC2771ContextUpgradeable.sol │ ├── proxy │ │ └── LiquidityPoolProxy.sol │ ├── lib │ │ ├── TransferHelper.sol │ │ └── Fee.sol │ └── ExecutorManager.sol ├── interfaces │ └── IERC20Permit.sol └── security │ └── Pausable.sol ├── test ├── utils │ └── index.ts └── ExecutorManager.tests.ts ├── .solhint.json ├── tsconfig.json ├── .solcover.js ├── Dockerfile ├── .dockerignore ├── scripts ├── misc │ └── audit-data-gen.sh ├── prod-replica-helpers │ ├── entrypoint.sh │ ├── token-address-to-funding-account.ts │ ├── utils.ts │ ├── fund-account.ts │ ├── upgrade-force-import.ts │ ├── abi │ │ └── ProxyAdmin.ts │ └── transfer-ownership.ts ├── upgrades │ ├── upgrade-all │ │ ├── local.ts │ │ ├── prod.ts │ │ ├── staging.ts │ │ ├── integration.ts │ │ └── upgrade-all.ts │ ├── upgrade-liquidity-pool.ts │ ├── upgrade-token-manager.ts │ ├── upgrade-liquidity-farming.ts │ ├── upgrade-liquidity-providers.ts │ ├── upgrade-whitelist-period-manager.ts │ └── upgrade.ts ├── deploy │ ├── deploy-batch-helper.ts │ ├── mainnet │ │ ├── deploy-avalanche.ts │ │ ├── deploy-fantom.ts │ │ └── deploy-arbitrum.ts │ └── testnet │ │ ├── deploy-fuji.ts │ │ ├── deploy-bsc-testnet.ts │ │ ├── deploy-mumbai.ts │ │ └── deploy-goerli.ts ├── transferOverhead.ts ├── token-deposit-config │ ├── set-fuji.ts │ ├── set-avax.ts │ ├── set-goerli.ts │ ├── set-mumbai.ts │ ├── set-ethereum.ts │ ├── set-polygon.ts │ └── set.ts ├── backend-api-script │ ├── utils.ts │ ├── get-implementation-addresses.ts │ ├── set-all-token-config.ts │ ├── set-deposit-config.ts │ ├── add-supported-token.ts │ ├── mainnet │ │ ├── deposit-config-optimism.ts │ │ ├── deposit-config-fantom.ts │ │ ├── deposit-config-arbitrum.ts │ │ ├── token-config-fantom.ts │ │ └── token-config-optimism.ts │ ├── testnet │ │ ├── deposit-config-arbiTestnet.ts │ │ └── token-config-arbitestnet.ts │ └── ethereum_config.ts ├── transferOverhead.js ├── types.ts └── token-manager │ ├── deploy-fuji.ts │ ├── deploy-avalanche.ts │ ├── deploy-mumbai.ts │ ├── deploy-goerli.ts │ ├── helper.ts │ ├── deploy-polygon.ts │ └── deploy-ethereum.ts ├── .eslintrc.js ├── LICENSE ├── .env.example ├── README.md ├── package.json ├── .gitignore └── .github └── PULL_REQUEST_TEMPLATE.md /.solhintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120 3 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage* 5 | gasReporterOutput.json 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "solidity.compileUsingRemoteVersion": "v0.8.0+commit.c7dfd78e" 3 | } -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | hardhat.config.ts 2 | scripts 3 | test 4 | .env* 5 | artifacts 6 | .openzeppelin 7 | .vscode 8 | cache 9 | typechain 10 | -------------------------------------------------------------------------------- /contracts/test/imports.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2; 3 | 4 | import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; -------------------------------------------------------------------------------- /test/utils/index.ts: -------------------------------------------------------------------------------- 1 | function getLocaleString(amount: number) { 2 | return amount.toLocaleString("fullwide", { useGrouping: false }); 3 | } 4 | 5 | export { getLocaleString }; 6 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/IWETH.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.0; 2 | 3 | import "./IERC20.sol"; 4 | 5 | /// @title Interface for WETH9 6 | interface IWETH is IERC20 { 7 | 8 | function withdraw(uint256 _amount) external; 9 | } -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "rules": { 4 | "compiler-version": ["error", "^0.8.0"], 5 | "func-visibility": ["warn", { "ignoreConstructors": true }], 6 | "quotes": "off" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /contracts/hyphen/structures/LpTokenMetadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | struct LpTokenMetadata { 5 | address token; 6 | uint256 suppliedLiquidity; 7 | uint256 shares; 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "outDir": "dist", 8 | "declaration": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | skipFiles: [ 3 | "hyphen/interfaces", 4 | "hyphen/mock", 5 | "hyphen/token/svg-helpers", 6 | "hyphen/metatx", 7 | "hyphen/proxy", 8 | "interfaces", 9 | "test", 10 | ], 11 | configureYulOptimizer: true, 12 | }; 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16 AS deps 2 | RUN apt-get update 3 | RUN apt-get upgrade --yes 4 | COPY ./package.json /app/ 5 | COPY ./yarn.lock /app/ 6 | WORKDIR /app 7 | RUN yarn 8 | 9 | FROM deps 10 | COPY . /app/ 11 | RUN npx hardhat compile 12 | RUN chmod a+x scripts/prod-replica-helpers/entrypoint.sh 13 | WORKDIR /app -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/IERC20WithDecimals.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; 5 | 6 | interface IERC20WithDecimals is IERC20Upgradeable { 7 | function decimals() external view returns (uint8); 8 | } 9 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # ignore all logs 2 | *.log 3 | 4 | node_modules/ 5 | dist/ 6 | 7 | *.cert 8 | *.key 9 | LICENSE 10 | README.md 11 | undefined 12 | .env 13 | 14 | # Ignore Mac DS_Store files 15 | .DS_Store 16 | **/.DS_Store 17 | 18 | # VSCode project files 19 | .vscode 20 | .openzeppelin 21 | .vscode 22 | cache 23 | artifacts -------------------------------------------------------------------------------- /contracts/hyphen/structures/SwapRequest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | enum SwapOperation {ExactOutput, ExactInput} 5 | 6 | struct SwapRequest { 7 | address tokenAddress; 8 | uint256 percentage; 9 | uint256 amount; 10 | SwapOperation operation; 11 | bytes path; 12 | } 13 | -------------------------------------------------------------------------------- /scripts/misc/audit-data-gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | contracts=$(find $CONTRACTS_DIR -name "*.sol") 4 | let contractsCount=0 5 | printf "%-8s %-100s %-4s\n" "No." "Contract" "SLoC"; 6 | for i in $contracts 7 | do 8 | contractsCount=$((contractsCount+1)) 9 | sloc=$(cat $i | sed '/^\s*$/d' | wc -l | xargs) 10 | printf "%-8d %-100s %-4d\n" $contractsCount $i $sloc; 11 | done -------------------------------------------------------------------------------- /contracts/hyphen/structures/TokenConfig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | struct TokenInfo { 5 | uint256 transferOverhead; 6 | bool supportedToken; 7 | uint256 equilibriumFee; // Percentage fee Represented in basis points 8 | uint256 maxFee; // Percentage fee Represented in basis points 9 | TokenConfig tokenConfig; 10 | } 11 | 12 | struct TokenConfig { 13 | uint256 min; 14 | uint256 max; 15 | } 16 | -------------------------------------------------------------------------------- /scripts/prod-replica-helpers/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_PATH=$(dirname "$0") 3 | 4 | setup () { 5 | npx hardhat run $SCRIPT_PATH/transfer-ownership.ts --network $1 6 | npx hardhat run $SCRIPT_PATH/upgrade-force-import.ts --network $1 7 | PRIVATE_KEY=$NEW_OWNER_PRIVATE_KEY npx hardhat run $SCRIPT_PATH/../upgrades/upgrade-all/prod.ts --network $1 8 | npx hardhat run $SCRIPT_PATH/fund-account.ts --network $1 9 | } 10 | 11 | setup mainnet & 12 | setup polygon & 13 | wait -------------------------------------------------------------------------------- /scripts/upgrades/upgrade-all/local.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { upgradeAllContracts, getContractAddressesByChain } from "./upgrade-all"; 3 | 4 | (async () => { 5 | const chainId = (await ethers.provider.getNetwork()).chainId; 6 | console.log(`Upgrading contracts on chain ${chainId}`); 7 | const contracts = await getContractAddressesByChain(process.env.LOCAL_API_URL as string, chainId); 8 | console.log(`Contracts: ${JSON.stringify(contracts, null, 2)}`); 9 | await upgradeAllContracts(contracts); 10 | })(); 11 | -------------------------------------------------------------------------------- /scripts/upgrades/upgrade-all/prod.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { upgradeAllContracts, getContractAddressesByChain } from "./upgrade-all"; 3 | 4 | (async () => { 5 | const chainId = (await ethers.provider.getNetwork()).chainId; 6 | console.log(`Upgrading contracts on chain ${chainId}`); 7 | const contracts = await getContractAddressesByChain(process.env.PROD_API_URL as string, chainId); 8 | console.log(`Contracts: ${JSON.stringify(contracts, null, 2)}`); 9 | await upgradeAllContracts(contracts); 10 | })(); 11 | -------------------------------------------------------------------------------- /scripts/upgrades/upgrade-all/staging.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { upgradeAllContracts, getContractAddressesByChain } from "./upgrade-all"; 3 | 4 | (async () => { 5 | const chainId = (await ethers.provider.getNetwork()).chainId; 6 | console.log(`Upgrading contracts on chain ${chainId}`); 7 | const contracts = await getContractAddressesByChain(process.env.STAGING_API_URL as string, chainId); 8 | console.log(`Contracts: ${JSON.stringify(contracts, null, 2)}`); 9 | await upgradeAllContracts(contracts); 10 | })(); 11 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: false, 4 | es2021: true, 5 | mocha: true, 6 | node: true, 7 | }, 8 | plugins: ["@typescript-eslint"], 9 | extends: [ 10 | "plugin:node/recommended", 11 | ], 12 | parser: "@typescript-eslint/parser", 13 | parserOptions: { 14 | ecmaVersion: 12, 15 | }, 16 | rules: { 17 | "node/no-unsupported-features/es-syntax": [ 18 | "error", 19 | { ignores: ["modules"] }, 20 | ], 21 | }, "engines": { 22 | "node": ">=10.0.0" 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /scripts/upgrades/upgrade-all/integration.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { upgradeAllContracts, getContractAddressesByChain } from "./upgrade-all"; 3 | 4 | (async () => { 5 | const chainId = (await ethers.provider.getNetwork()).chainId; 6 | console.log(`Upgrading contracts on chain ${chainId}`); 7 | const contracts = await getContractAddressesByChain(process.env.INTEGRATION_API_URL as string, chainId); 8 | console.log(`Contracts: ${JSON.stringify(contracts, null, 2)}`); 9 | await upgradeAllContracts(contracts); 10 | })(); 11 | -------------------------------------------------------------------------------- /scripts/deploy/deploy-batch-helper.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { verifyContract } from "./deploy-utils"; 3 | 4 | (async () => { 5 | const [deployer] = await ethers.getSigners(); 6 | console.log("Deploying contracts with the account:", deployer.address); 7 | 8 | const BatchHelper = await ethers.getContractFactory("BatchHelper"); 9 | const batchHelper = await BatchHelper.deploy(); 10 | await batchHelper.deployed(); 11 | 12 | console.log("Batch Helper address:", batchHelper.address); 13 | 14 | await verifyContract(batchHelper.address, []); 15 | })(); 16 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/ISwapAdaptor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | import "../structures/SwapRequest.sol"; 4 | 5 | interface ISwapAdaptor { 6 | function swap( 7 | address inputTokenAddress, 8 | uint256 amountInMaximum, 9 | address receiver, 10 | SwapRequest[] calldata swapRequests 11 | ) external returns (uint256 amountIn); 12 | 13 | function swapNative( 14 | uint256 amountInMaximum, 15 | address receiver, 16 | SwapRequest[] calldata swapRequests 17 | ) external returns (uint256 amountOut); 18 | } -------------------------------------------------------------------------------- /contracts/test/SampleContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "@biconomy/ccmp-contracts/contracts/receiver/CCMPReceiver.sol"; 5 | 6 | contract SampleContract is CCMPReceiver { 7 | event Message(string message, address sender, uint256 chainId); 8 | 9 | constructor(address _ccmpExecutor, ILiquidityPool _liquidityPool) CCMPReceiver(_ccmpExecutor, _liquidityPool) {} 10 | 11 | function emitEvent(string calldata message) external { 12 | (address sender, uint256 chainId) = _hyphenMsgOrigin(); 13 | emit Message(message, sender, chainId); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /scripts/upgrades/upgrade-liquidity-pool.ts: -------------------------------------------------------------------------------- 1 | import { upgradeLiquidityPool } from "./upgrade"; 2 | import { verifyImplementation } from "../deploy/deploy-utils"; 3 | import { ethers } from "hardhat"; 4 | 5 | (async () => { 6 | const proxy = process.env.PROXY || "0x8033Bd14c4C114C14C910fe05Ff13DB4C481a85D"; 7 | const [signer] = await ethers.getSigners(); 8 | 9 | console.log("Proxy: ", proxy, " Deployer: ", signer.address); 10 | console.log("Upgrading Proxy..."); 11 | await upgradeLiquidityPool(proxy); 12 | await new Promise((resolve) => setTimeout(resolve, 5000)); 13 | await verifyImplementation(proxy); 14 | })(); 15 | -------------------------------------------------------------------------------- /scripts/upgrades/upgrade-token-manager.ts: -------------------------------------------------------------------------------- 1 | import { upgradeTokenManager } from "./upgrade"; 2 | import { verifyImplementation } from "../deploy/deploy-utils"; 3 | import { ethers } from "hardhat"; 4 | 5 | (async () => { 6 | const proxy = process.env.PROXY || "0x8033Bd14c4C114C14C910fe05Ff13DB4C481a85D"; 7 | const [signer] = await ethers.getSigners(); 8 | 9 | console.log("Proxy: ", proxy, " Deployer: ", signer.address); 10 | console.log("Upgrading Proxy..."); 11 | await upgradeTokenManager(proxy); 12 | await new Promise((resolve) => setTimeout(resolve, 5000)); 13 | await verifyImplementation(proxy); 14 | })(); 15 | -------------------------------------------------------------------------------- /scripts/upgrades/upgrade-liquidity-farming.ts: -------------------------------------------------------------------------------- 1 | import { upgradeLiquidityFarming } from "./upgrade"; 2 | import { verifyImplementation } from "../deploy/deploy-utils"; 3 | import { ethers } from "hardhat"; 4 | 5 | (async () => { 6 | const proxy = process.env.PROXY || "0x62A0521d3F3B75b70fA39926A0c63CBf819870a6"; 7 | const [signer] = await ethers.getSigners(); 8 | console.log("Proxy: ", proxy, " Deployer: ", signer.address); 9 | console.log("Upgrading Proxy..."); 10 | await upgradeLiquidityFarming(proxy); 11 | await new Promise((resolve) => setTimeout(resolve, 5000)); 12 | await verifyImplementation(proxy); 13 | })(); 14 | -------------------------------------------------------------------------------- /scripts/upgrades/upgrade-liquidity-providers.ts: -------------------------------------------------------------------------------- 1 | import { upgradeLiquidityProviders } from "./upgrade"; 2 | import { verifyImplementation } from "../deploy/deploy-utils"; 3 | import { ethers } from "hardhat"; 4 | 5 | (async () => { 6 | const proxy = process.env.PROXY || "0x17D42A784928a8168a871fA627bb1e4023D25C2A"; 7 | const [signer] = await ethers.getSigners(); 8 | console.log("Proxy: ", proxy, " Deployer: ", signer.address); 9 | console.log("Upgrading Proxy..."); 10 | await upgradeLiquidityProviders(proxy); 11 | await new Promise((resolve) => setTimeout(resolve, 5000)); 12 | await verifyImplementation(proxy); 13 | })(); 14 | -------------------------------------------------------------------------------- /scripts/upgrades/upgrade-whitelist-period-manager.ts: -------------------------------------------------------------------------------- 1 | import { upgradeWhiteListPeriodManager } from "./upgrade"; 2 | import { verifyImplementation } from "../deploy/deploy-utils"; 3 | import { ethers } from "hardhat"; 4 | 5 | (async () => { 6 | const proxy = process.env.PROXY || "0x62A0521d3F3B75b70fA39926A0c63CBf819870a6"; 7 | const [signer] = await ethers.getSigners(); 8 | console.log("Proxy: ", proxy, " Deployer: ", signer.address); 9 | console.log("Upgrading Proxy..."); 10 | await new Promise((resolve) => setTimeout(resolve, 5000)); 11 | await upgradeWhiteListPeriodManager(proxy); 12 | await verifyImplementation(proxy); 13 | })(); 14 | -------------------------------------------------------------------------------- /scripts/transferOverhead.ts: -------------------------------------------------------------------------------- 1 | let { BigNumber, ethers } = require("ethers"); 2 | 3 | let sentAmount = ethers.utils.parseUnits("2.000174338223706993", "18"); 4 | let receivedAmount = ethers.utils.parseUnits("1.999255842125327365", "18"); 5 | let gasFeeDeductedOnChain = ethers.utils.parseUnits("0.000000160412259956", "18"); 6 | let actualGasFeeByExecutor = ethers.utils.parseUnits("0.000000256803745", "18"); 7 | let gasUnaccountedFor = BigNumber.from(actualGasFeeByExecutor).sub(gasFeeDeductedOnChain); 8 | 9 | let gasPrice = ethers.utils.parseUnits(".000000000001358666","18"); 10 | 11 | let transferOverhead = gasUnaccountedFor.div(gasPrice); 12 | 13 | console.log(transferOverhead.toString()); -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/ICCMPGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | interface ICCMPGateway { 5 | struct CCMPMessagePayload { 6 | address to; 7 | bytes _calldata; 8 | } 9 | 10 | struct GasFeePaymentArgs { 11 | address feeTokenAddress; 12 | uint256 feeAmount; 13 | address relayer; 14 | } 15 | 16 | function sendMessage( 17 | uint256 _destinationChainId, 18 | string calldata _adaptorName, 19 | CCMPMessagePayload[] calldata _payloads, 20 | GasFeePaymentArgs calldata _gasFeePaymentArgs, 21 | bytes calldata _routerArgs 22 | ) external payable returns (bool sent); 23 | } 24 | -------------------------------------------------------------------------------- /contracts/test/ERC20Token.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; 5 | 6 | contract ERC20Token is ERC20Upgradeable { 7 | uint8 private __decimals; 8 | 9 | function initialize( 10 | string memory _name, 11 | string memory _symbol, 12 | uint8 _decimals 13 | ) public initializer { 14 | __ERC20_init(_name, _symbol); 15 | __decimals = _decimals; 16 | } 17 | 18 | function mint(address _to, uint256 _amount) external { 19 | _mint(_to, _amount); 20 | } 21 | 22 | function decimals() public view override returns (uint8) { 23 | return __decimals; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/hyphen/structures/DepositAndCall.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "../interfaces/ICCMPGateway.sol"; 5 | 6 | struct DepositAndCallArgs { 7 | uint256 toChainId; 8 | address tokenAddress; // Can be Native 9 | address receiver; 10 | uint256 amount; 11 | string tag; 12 | ICCMPGateway.CCMPMessagePayload[] payloads; 13 | ICCMPGateway.GasFeePaymentArgs gasFeePaymentArgs; 14 | string adaptorName; 15 | bytes routerArgs; 16 | bytes[] hyphenArgs; 17 | } 18 | 19 | struct SendFundsToUserFromCCMPArgs { 20 | uint256 tokenSymbol; 21 | uint256 sourceChainAmount; 22 | uint256 sourceChainDecimals; 23 | address payable receiver; 24 | bytes[] hyphenArgs; 25 | } 26 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/IExecutorManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.0; 4 | 5 | interface IExecutorManager { 6 | function getExecutorStatus(address executor) external view returns (bool status); 7 | 8 | function getAllExecutors() external view returns (address[] memory); 9 | 10 | //Register new Executors 11 | function addExecutors(address[] calldata executorArray) external; 12 | 13 | // Register single executor 14 | function addExecutor(address executorAddress) external; 15 | 16 | //Remove registered Executors 17 | function removeExecutors(address[] calldata executorArray) external; 18 | 19 | // Remove Register single executor 20 | function removeExecutor(address executorAddress) external; 21 | } 22 | -------------------------------------------------------------------------------- /scripts/token-deposit-config/set-fuji.ts: -------------------------------------------------------------------------------- 1 | 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { setTokenDepositConfiguration } from "./set"; 4 | import type { ITokenAddConfiguration } from "./set"; 5 | 6 | const TokenManager = "0xf972dAf3273B84Ab862a73a75dca1204E4a357cf"; 7 | 8 | const configurations: ITokenAddConfiguration[] = [ 9 | { 10 | chainId: 97, 11 | tokenAddress: "0xB4E0F6FEF81BdFea0856bB846789985c9CFf7e85", 12 | minCap: parseUnits("100", 18), 13 | maxCap: parseUnits("1000", 18), 14 | }, 15 | { 16 | chainId: 97, 17 | tokenAddress: "0x7fCDc2C1EF3e4A0bCC8155a558bB20a7218f2b05", 18 | minCap: parseUnits("0.01", 18), 19 | maxCap: parseUnits("100", 18), 20 | }, 21 | ]; 22 | 23 | setTokenDepositConfiguration(TokenManager, configurations); -------------------------------------------------------------------------------- /scripts/prod-replica-helpers/token-address-to-funding-account.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | // Ethereum 3 | "0xdac17f958d2ee523a2206206994597c13d831ec7": "0xf977814e90da44bfa03b6295a0616a897441acec", 4 | "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48": "0x0a59649758aa4d66e25f08dd01271e891fe52199", 5 | "0xf17e65822b568b3903685a7c9f496cf7656cc6c2": "0x48d601d601ed4cde44dd688573e2235aea333ba2", 6 | 7 | // Polygon 8 | "0xc2132d05d31c914a87c6611c10748aeb04b58e8f": "0xe7804c37c13166ff0b37f5ae0bb07a3aebb6e245", 9 | "0x2791bca1f2de4661ed88a30c99a7a9449aa84174": "0xf977814e90da44bfa03b6295a0616a897441acec", 10 | "0x91c89a94567980f0e9723b487b0bed586ee96aa7": "0x9769410db87fb19914cdcbf5ff714e8b987656b9", 11 | "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619": "0x28424507fefb6f7f8e9d3860f56504e4e5f5f390" 12 | }; 13 | -------------------------------------------------------------------------------- /scripts/token-deposit-config/set-avax.ts: -------------------------------------------------------------------------------- 1 | import { parseUnits } from "ethers/lib/utils"; 2 | import { setTokenDepositConfiguration } from "./set"; 3 | import type { ITokenAddConfiguration } from "./set"; 4 | 5 | const TokenManager = "0xd8Ce41FDF0fE96ea4F457d2A22faAF1d128C0954"; 6 | 7 | const configurations: ITokenAddConfiguration[] = [ 8 | // USDC 9 | { 10 | chainId: 56, 11 | tokenAddress: "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664", 12 | minCap: parseUnits("10", 6), 13 | maxCap: parseUnits("200000", 6), 14 | }, 15 | // ETH 16 | { 17 | chainId: 56, 18 | tokenAddress: "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB", 19 | minCap: parseUnits("0.0039", 18), 20 | maxCap: parseUnits("100", 18), 21 | }, 22 | ]; 23 | 24 | setTokenDepositConfiguration(TokenManager, configurations); 25 | -------------------------------------------------------------------------------- /contracts/test/LiquidityProvidersTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | import "../hyphen/LiquidityProviders.sol"; 5 | import "hardhat/console.sol"; 6 | 7 | contract LiquidityProvidersTest is LiquidityProviders { 8 | using SafeERC20Upgradeable for IERC20Upgradeable; 9 | 10 | function addLpFeeTesting(address _token, uint256 _amount) external payable { 11 | totalReserve[_token] += _amount; 12 | totalLPFees[_token] += _amount; 13 | 14 | if (_token == NATIVE) { 15 | (bool success, ) = address(liquidityPool).call{value: msg.value}(""); 16 | require(success, "ERR__NATIVE_TRANSFER_FAILED"); 17 | } else { 18 | IERC20Upgradeable(_token).safeTransferFrom(msg.sender, address(liquidityPool), _amount); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /scripts/backend-api-script/utils.ts: -------------------------------------------------------------------------------- 1 | import type { IBackendConfig } from "../types"; 2 | 3 | export const getBackendConfig = (env: "staging" | "integration" | "prod" | "local"): IBackendConfig => { 4 | 5 | const config = { 6 | apiKey: process.env[`${env.toUpperCase()}_API_KEY`] as string, 7 | apiUsername: process.env[`${env.toUpperCase()}_API_USERNAME`] as string, 8 | apiPassword: process.env[`${env.toUpperCase()}_API_PASSWORD`] as string, 9 | baseUrl: process.env[`${env.toUpperCase()}_API_URL`] as string, 10 | }; 11 | if (!config.apiKey || !config.apiUsername || !config.apiPassword || !config.baseUrl) { 12 | throw new Error( 13 | `Missing ${env.toUpperCase()}_API_KEY, ${env.toUpperCase()}_API_USERNAME, ${env.toUpperCase()}_API_PASSWORD, ${env.toUpperCase()}_API_URL` 14 | ); 15 | } 16 | return config; 17 | }; 18 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC20Permit.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | pragma solidity 0.8.0; 3 | 4 | import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; 5 | 6 | interface IERC20Detailed is IERC20Upgradeable { 7 | function name() external view returns(string memory); 8 | function decimals() external view returns(uint256); 9 | } 10 | 11 | interface IERC20Nonces is IERC20Detailed { 12 | function nonces(address holder) external view returns(uint); 13 | } 14 | 15 | interface IERC20Permit is IERC20Nonces { 16 | function permit(address holder, address spender, uint256 nonce, uint256 expiry, 17 | bool allowed, uint8 v, bytes32 r, bytes32 s) external; 18 | 19 | function permit(address holder, address spender, uint256 value, uint256 expiry, 20 | uint8 v, bytes32 r, bytes32 s) external; 21 | } -------------------------------------------------------------------------------- /contracts/hyphen/mock/MockSwapRouter_Fail.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | import "../interfaces/ISwapAdaptor.sol"; 3 | import "../interfaces/ISwapRouter.sol"; 4 | import "../lib/TransferHelper.sol"; 5 | 6 | contract MockSwapRouterFail { 7 | struct ExactOutputParams { 8 | bytes path; 9 | address recipient; 10 | uint256 amountOut; 11 | uint256 amountInMaximum; 12 | } 13 | 14 | struct ExactInputParams { 15 | bytes path; 16 | address recipient; 17 | uint256 amountIn; 18 | uint256 amountOutMinimum; 19 | } 20 | 21 | function exactOutputSingle(ExactOutputParams calldata params) external payable returns (uint256 amountIn){ 22 | revert(); 23 | } 24 | 25 | function exactInputSingle(ExactInputParams calldata params) external payable returns (uint256 amountOut){ 26 | revert(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/hyphen/mock/MockSwapRouter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | import "../interfaces/ISwapAdaptor.sol"; 3 | import "../interfaces/ISwapRouter.sol"; 4 | import "../lib/TransferHelper.sol"; 5 | 6 | contract MockSwapRouter { 7 | struct ExactOutputParams { 8 | bytes path; 9 | address recipient; 10 | uint256 amountOut; 11 | uint256 amountInMaximum; 12 | } 13 | 14 | struct ExactInputParams { 15 | bytes path; 16 | address recipient; 17 | uint256 amountIn; 18 | uint256 amountOutMinimum; 19 | } 20 | 21 | function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn){ 22 | return params.amountOut; 23 | } 24 | 25 | function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut){ 26 | return params.amountIn; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scripts/token-deposit-config/set-goerli.ts: -------------------------------------------------------------------------------- 1 | 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { setTokenDepositConfiguration } from "./set"; 4 | import type { ITokenAddConfiguration } from "./set"; 5 | 6 | const TokenManager = "0x49B5e3Dc6E9f11031E355c272b0Ed11afB90177e"; 7 | 8 | const configurations: ITokenAddConfiguration[] = [ 9 | { 10 | chainId: 97, 11 | tokenAddress: "0x64ef393b6846114bad71e2cb2ccc3e10736b5716", 12 | minCap: parseUnits("100", 18), 13 | maxCap: parseUnits("1000", 18), 14 | }, 15 | { 16 | chainId: 97, 17 | tokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", 18 | minCap: parseUnits("0.01", 18), 19 | maxCap: parseUnits("100", 18), 20 | }, 21 | { 22 | chainId: 97, 23 | tokenAddress: "0xb5B640E6414b6DeF4FC9B3C1EeF373925effeCcF", 24 | minCap: parseUnits("100", 6), 25 | maxCap: parseUnits("1000", 6), 26 | }, 27 | ]; 28 | 29 | setTokenDepositConfiguration(TokenManager, configurations); -------------------------------------------------------------------------------- /scripts/token-deposit-config/set-mumbai.ts: -------------------------------------------------------------------------------- 1 | import { parseUnits } from "ethers/lib/utils"; 2 | import { setTokenDepositConfiguration } from "./set"; 3 | import type { ITokenAddConfiguration } from "./set"; 4 | 5 | const TokenManager = "0xc23F4c4886f1D48d980dd33a712c7B71c3d31032"; 6 | 7 | const configurations: ITokenAddConfiguration[] = [ 8 | { 9 | chainId: 97, 10 | tokenAddress: "0xeabc4b91d9375796aa4f69cc764a4ab509080a58", 11 | minCap: parseUnits("100", 18), 12 | maxCap: parseUnits("1000", 18), 13 | }, 14 | { 15 | chainId: 97, 16 | tokenAddress: "0xa6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa", 17 | minCap: parseUnits("0.01", 18), 18 | maxCap: parseUnits("100", 18), 19 | }, 20 | { 21 | chainId: 97, 22 | tokenAddress: "0xdA5289fCAAF71d52a80A254da614a192b693e977", 23 | minCap: parseUnits("100", 6), 24 | maxCap: parseUnits("1000", 6), 25 | }, 26 | ]; 27 | 28 | setTokenDepositConfiguration(TokenManager, configurations); 29 | -------------------------------------------------------------------------------- /contracts/test/TokenMintingReentrancy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.0; 3 | import "../hyphen/LiquidityProviders.sol"; 4 | import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol"; 5 | 6 | contract TokenMintingReentrancy is IERC721ReceiverUpgradeable { 7 | LiquidityProviders public liquidityproviders; 8 | 9 | constructor(address _lproviders) { 10 | liquidityproviders = LiquidityProviders(payable(_lproviders)); 11 | } 12 | 13 | function onERC721Received( 14 | address, 15 | address, 16 | uint256 tokenId, 17 | bytes calldata 18 | ) external override returns (bytes4) { 19 | if (tokenId < 10) { 20 | liquidityproviders.addNativeLiquidity{value: 1e12}(); 21 | } 22 | return IERC721ReceiverUpgradeable.onERC721Received.selector; 23 | } 24 | 25 | receive() external payable {} 26 | 27 | function attack() external payable { 28 | liquidityproviders.addNativeLiquidity{value: msg.value}(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/ISvgHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | interface ISvgHelper { 5 | function backgroundUrl() external view returns (string memory); 6 | 7 | function getTokenSvg( 8 | uint256 _tokenId, 9 | uint256 _suppliedLiquidity, 10 | uint256 _totalSuppliedLiquidity 11 | ) external view returns (string memory); 12 | 13 | function getAttributes(uint256 _suppliedLiquidity, uint256 _totalSuppliedLiquidity) 14 | external 15 | view 16 | returns (string memory); 17 | 18 | function getDescription(uint256 _suppliedLiquidity, uint256 _totalSuppliedLiquidity) 19 | external 20 | view 21 | returns (string memory); 22 | 23 | function getChainName() external view returns (string memory); 24 | 25 | function owner() external view returns (address); 26 | 27 | function renounceOwnership() external; 28 | 29 | function setBackgroundPngUrl(string memory _backgroundPngUrl) external; 30 | 31 | function transferOwnership(address newOwner) external; 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Biconomy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /scripts/token-deposit-config/set-ethereum.ts: -------------------------------------------------------------------------------- 1 | import { parseUnits } from "ethers/lib/utils"; 2 | import { setTokenDepositConfiguration } from "./set"; 3 | import type { ITokenAddConfiguration } from "./set"; 4 | 5 | const TokenManager = "0xd8Ce41FDF0fE96ea4F457d2A22faAF1d128C0954"; 6 | 7 | const configurations: ITokenAddConfiguration[] = [ 8 | // USDT 9 | { 10 | chainId: 56, 11 | tokenAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7", 12 | minCap: parseUnits("100", 6), 13 | maxCap: parseUnits("50000", 6), 14 | }, 15 | // USDC 16 | { 17 | chainId: 56, 18 | tokenAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", 19 | minCap: parseUnits("10", 6), 20 | maxCap: parseUnits("200000", 6), 21 | }, 22 | // BICO 23 | { 24 | chainId: 56, 25 | tokenAddress: "0xf17e65822b568b3903685a7c9f496cf7656cc6c2", 26 | minCap: parseUnits("100", 18), 27 | maxCap: parseUnits("100000", 18), 28 | }, 29 | // ETH 30 | { 31 | chainId: 56, 32 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 33 | minCap: parseUnits("0.0039", 18), 34 | maxCap: parseUnits("100", 18), 35 | }, 36 | ]; 37 | 38 | setTokenDepositConfiguration(TokenManager, configurations); 39 | -------------------------------------------------------------------------------- /scripts/token-deposit-config/set-polygon.ts: -------------------------------------------------------------------------------- 1 | import { parseUnits } from "ethers/lib/utils"; 2 | import { setTokenDepositConfiguration } from "./set"; 3 | import type { ITokenAddConfiguration } from "./set"; 4 | 5 | const TokenManager = "0xd8Ce41FDF0fE96ea4F457d2A22faAF1d128C0954"; 6 | 7 | const configurations: ITokenAddConfiguration[] = [ 8 | // USDT 9 | { 10 | chainId: 56, 11 | tokenAddress: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", 12 | minCap: parseUnits("100", 6), 13 | maxCap: parseUnits("50000", 6), 14 | }, 15 | // USDC 16 | { 17 | chainId: 56, 18 | tokenAddress: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", 19 | minCap: parseUnits("10", 6), 20 | maxCap: parseUnits("200000", 6), 21 | }, 22 | // BICO 23 | { 24 | chainId: 56, 25 | tokenAddress: "0x91c89A94567980f0e9723b487b0beD586eE96aa7", 26 | minCap: parseUnits("100", 18), 27 | maxCap: parseUnits("100000", 18), 28 | }, 29 | // ETH 30 | { 31 | chainId: 56, 32 | tokenAddress: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", 33 | minCap: parseUnits("0.0039", 18), 34 | maxCap: parseUnits("100", 18), 35 | }, 36 | ]; 37 | 38 | setTokenDepositConfiguration(TokenManager, configurations); 39 | -------------------------------------------------------------------------------- /contracts/test/LiquidityProvidersMaliciousReentrant.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.0; 3 | import "../hyphen/LiquidityPool.sol"; 4 | 5 | contract LiquidityProvidersMaliciousReentrant { 6 | LiquidityPool public lpool; 7 | address private constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; 8 | address private owner; 9 | modifier onlyOwner() { 10 | require(owner == msg.sender, "Unauthorized"); 11 | _; 12 | } 13 | 14 | constructor(address _lpaddress) { 15 | owner = msg.sender; 16 | lpool = LiquidityPool(payable(_lpaddress)); 17 | } 18 | 19 | fallback() external payable { 20 | if (address(lpool).balance >= 1 ether) { 21 | lpool.transfer(NATIVE, address(this), 1 ether); 22 | } 23 | } 24 | 25 | receive() external payable { 26 | if (address(lpool).balance >= 1 ether) { 27 | lpool.transfer(NATIVE, address(this), 1 ether); 28 | } 29 | } 30 | 31 | function getBalance(address target) public view returns (uint256) { 32 | return target.balance; 33 | } 34 | 35 | function destruct() external onlyOwner { 36 | selfdestruct(payable(owner)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /contracts/test/BatchHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "../hyphen/interfaces/ILPToken.sol"; 6 | import "../hyphen/interfaces/ILiquidityProviders.sol"; 7 | import "../hyphen/interfaces/IHyphenLiquidityFarmingV2.sol"; 8 | 9 | contract BatchHelper { 10 | function execute( 11 | IERC20 token, 12 | ILPToken lpToken, 13 | ILiquidityProviders liquidityProviders, 14 | IHyphenLiquidityFarmingV2 farming, 15 | address receiver 16 | ) external { 17 | uint256 balance = token.balanceOf(address(this)); 18 | token.approve(address(liquidityProviders), balance); 19 | liquidityProviders.addTokenLiquidity(address(token), balance); 20 | uint256[] memory tokensOwned = lpToken.getAllNftIdsByUser(address(this)); 21 | lpToken.approve(address(farming), tokensOwned[0]); 22 | farming.deposit(tokensOwned[0], receiver); 23 | } 24 | 25 | function onERC721Received( 26 | address, 27 | address, 28 | uint256, 29 | bytes calldata 30 | ) external pure returns (bytes4) { 31 | return this.onERC721Received.selector; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /scripts/backend-api-script/get-implementation-addresses.ts: -------------------------------------------------------------------------------- 1 | import { getImplementationAddress } from "../deploy/deploy-utils"; 2 | import { getContractAddresses } from "../upgrades/upgrade-all/upgrade-all"; 3 | import { getProviderMapByChain } from "../deploy/deploy-utils"; 4 | 5 | (async () => { 6 | const contracts = await getContractAddresses(process.env.PROD_API_URL!); 7 | const provider = await getProviderMapByChain(); 8 | const result = ( 9 | await Promise.all( 10 | Object.entries(contracts).map( 11 | async ([chainId, addresses]) => 12 | await Promise.all( 13 | Object.entries(addresses).map( 14 | async ([contractName, address]) => 15 | address && [ 16 | chainId, 17 | contractName, 18 | address, 19 | await getImplementationAddress(address, provider[parseInt(chainId)]), 20 | ] 21 | ) 22 | ) 23 | ) 24 | ) 25 | ) 26 | .reduce((a, b) => [...a, ...b]) 27 | .filter(([, , , address]) => address && address != "0x00") 28 | .map(([chainId, contractName, address, implementationAddress]) => ({ 29 | chainId, 30 | contractName, 31 | address, 32 | implementationAddress, 33 | })); 34 | console.table(result); 35 | })(); 36 | -------------------------------------------------------------------------------- /contracts/hyphen/metatx/ERC2771Context.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.0; 4 | 5 | import "@openzeppelin/contracts/utils/Context.sol"; 6 | 7 | /** 8 | * @dev Context variant with ERC2771 support. 9 | */ 10 | abstract contract ERC2771Context is Context { 11 | address internal _trustedForwarder; 12 | 13 | constructor(address trustedForwarder) { 14 | _trustedForwarder = trustedForwarder; 15 | } 16 | 17 | function isTrustedForwarder(address forwarder) public view virtual returns (bool) { 18 | return forwarder == _trustedForwarder; 19 | } 20 | 21 | function _msgSender() internal view virtual override returns (address sender) { 22 | if (isTrustedForwarder(msg.sender)) { 23 | // The assembly code is more direct than the Solidity version using `abi.decode`. 24 | assembly { 25 | sender := shr(96, calldataload(sub(calldatasize(), 20))) 26 | } 27 | } else { 28 | return super._msgSender(); 29 | } 30 | } 31 | 32 | function _msgData() internal view virtual override returns (bytes calldata) { 33 | if (isTrustedForwarder(msg.sender)) { 34 | return msg.data[:msg.data.length - 20]; 35 | } else { 36 | return super._msgData(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /scripts/token-deposit-config/set.ts: -------------------------------------------------------------------------------- 1 | import { BigNumberish } from "ethers"; 2 | import { ethers } from "hardhat"; 3 | import { TokenManager__factory } from "../../typechain"; 4 | 5 | interface ITokenAddConfiguration { 6 | chainId: number; 7 | minCap: BigNumberish; 8 | maxCap: BigNumberish; 9 | tokenAddress: string; 10 | } 11 | 12 | const setTokenDepositConfiguration = async (tokenManagerAddress: string, configs: ITokenAddConfiguration[]) => { 13 | const [signer] = await ethers.getSigners(); 14 | console.log(`signer: ${signer.address}`); 15 | 16 | const tokenManager = TokenManager__factory.connect(tokenManagerAddress, signer); 17 | 18 | const toChainIds = configs.map((config) => config.chainId); 19 | const tokenAddresses = configs.map((config) => config.tokenAddress); 20 | const tokenConfigs = configs.map((config) => ({ min: config.minCap, max: config.maxCap })); 21 | 22 | console.log(`Adding tokens to TokenManager on chainId: ${(await ethers.provider.getNetwork()).chainId}`); 23 | const { wait, hash } = await tokenManager.setDepositConfig(toChainIds, tokenAddresses, tokenConfigs); 24 | console.log(`Waiting for transaction ${hash} to be confirmed...`); 25 | await wait(); 26 | console.log(`Transaction ${hash} confirmed!`); 27 | }; 28 | 29 | export { setTokenDepositConfiguration }; 30 | export type { ITokenAddConfiguration }; 31 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/IUniswapV3SwapCallback.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity 0.8.0; 3 | 4 | /// @title Callback for IUniswapV3PoolActions#swap 5 | /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface 6 | interface IUniswapV3SwapCallback { 7 | /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. 8 | /// @dev In the implementation you must pay the pool tokens owed for the swap. 9 | /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. 10 | /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. 11 | /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by 12 | /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. 13 | /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by 14 | /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. 15 | /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call 16 | function uniswapV3SwapCallback( 17 | int256 amount0Delta, 18 | int256 amount1Delta, 19 | bytes calldata data 20 | ) external; 21 | } -------------------------------------------------------------------------------- /scripts/transferOverhead.js: -------------------------------------------------------------------------------- 1 | let { BigNumber, ethers } = require("ethers"); 2 | 3 | // This amount should be get from exit transaction parameters including reward amount 4 | let sentAmountDecimal = "101.319533"; 5 | let receivedAmountDecimal = "101.105734"; 6 | let differenceInAmount = sentAmountDecimal - receivedAmountDecimal; 7 | 8 | // Set the transfer Fee percentrage deducted in this transaction. Can be fetched from db or exit transaction logs on explorer. 9 | let transferFeePerc = 0.045 10 | let transferFee = sentAmountDecimal * transferFeePerc / 100; 11 | 12 | let expectedExecutorFeeInToken = differenceInAmount - transferFee; 13 | 14 | // If token is USDC, then what is the price of native token in USDC? 15 | let nativeTokenPriceInToken = 27.78; 16 | 17 | let expectedExecutorFeeInNative = expectedExecutorFeeInToken / nativeTokenPriceInToken; 18 | let gasFeeDeductedOnChain = ethers.utils.parseUnits(expectedExecutorFeeInNative.toString(), "18"); 19 | 20 | // Set the gas fee used by the executor. Can be fetched from explorer 21 | let actualGasFeeByExecutor = ethers.utils.parseUnits("0.006039", "18"); 22 | let gasUnaccountedFor = BigNumber.from(actualGasFeeByExecutor).sub(gasFeeDeductedOnChain); 23 | 24 | // Final gas price of the trasnaction. Can be fetched from the explorer 25 | let gasPrice = ethers.utils.parseUnits("0.0000000275","18"); 26 | 27 | let transferOverhead = gasUnaccountedFor.div(gasPrice); 28 | 29 | console.log(transferOverhead.toString()); -------------------------------------------------------------------------------- /contracts/hyphen/mock/MockAdaptorFail.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | import "../interfaces/ISwapAdaptor.sol"; 3 | import "../interfaces/ISwapRouter.sol"; 4 | import "../lib/TransferHelper.sol"; 5 | 6 | contract MockAdaptorFail is ISwapAdaptor { 7 | uint24 public constant POOL_FEE = 3000; 8 | address private constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; 9 | 10 | address public immutable NATIVE_WRAP_ADDRESS; 11 | ISwapRouter public immutable swapRouter; 12 | 13 | constructor(ISwapRouter _swapRouter, address nativeWrapAddress) { 14 | NATIVE_WRAP_ADDRESS = nativeWrapAddress; 15 | swapRouter = _swapRouter; // "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45" 16 | } 17 | 18 | function swap( 19 | address inputTokenAddress, 20 | uint256 amountInMaximum, 21 | address receiver, 22 | SwapRequest[] memory swapRequests 23 | ) external override returns (uint256 amountIn) { 24 | revert("Insufitient funds"); 25 | } 26 | 27 | function swapNative( 28 | uint256 amountInMaximum, 29 | address receiver, 30 | SwapRequest[] memory swapRequests 31 | ) external override returns (uint256 amountIn) { 32 | revert("Insufitient funds"); 33 | } 34 | 35 | function unwrap(uint256 amountMinimum, address recipient) internal { 36 | 37 | } 38 | 39 | receive() external payable { 40 | require(msg.sender == NATIVE_WRAP_ADDRESS, 'Not WETH9'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/ILiquidityPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | import "../structures/DepositAndCall.sol"; 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | interface ILiquidityPool { 7 | function depositErc20( 8 | uint256 toChainId, 9 | address tokenAddress, 10 | address receiver, 11 | uint256 amount, 12 | string memory tag 13 | ) external; 14 | 15 | function depositNative( 16 | address receiver, 17 | uint256 toChainId, 18 | string memory tag 19 | ) external payable; 20 | 21 | function gasFeeAccumulated(address, address) external view returns (uint256); 22 | 23 | function gasFeeAccumulatedByToken(address) external view returns (uint256); 24 | 25 | function getCurrentLiquidity(address tokenAddress) external view returns (uint256 currentLiquidity); 26 | 27 | function getRewardAmount(uint256 amount, address tokenAddress) external view returns (uint256 rewardAmount); 28 | 29 | function getTransferFee(address tokenAddress, uint256 amount) external view returns (uint256 fee); 30 | 31 | function incentivePool(address) external view returns (uint256); 32 | 33 | function processedHash(bytes32) external view returns (bool); 34 | 35 | function transfer(address _tokenAddress, address receiver, uint256 _tokenAmount) external; 36 | 37 | function withdrawErc20GasFee(address tokenAddress) external; 38 | 39 | function withdrawNativeGasFee() external; 40 | 41 | function depositAndCall(DepositAndCallArgs calldata args) external payable; 42 | } 43 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/ITokenManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | import "../structures/TokenConfig.sol"; 5 | 6 | interface ITokenManager { 7 | function getEquilibriumFee(address tokenAddress) external view returns (uint256); 8 | 9 | function getMaxFee(address tokenAddress) external view returns (uint256); 10 | 11 | function changeFee( 12 | address tokenAddress, 13 | uint256 _equilibriumFee, 14 | uint256 _maxFee 15 | ) external; 16 | 17 | function tokensInfo(address tokenAddress) 18 | external 19 | view 20 | returns ( 21 | uint256 transferOverhead, 22 | bool supportedToken, 23 | uint256 equilibriumFee, 24 | uint256 maxFee, 25 | TokenConfig memory config 26 | ); 27 | 28 | function excessStateTransferFeePerc(address tokenAddress) external view returns (uint256); 29 | 30 | function getTokensInfo(address tokenAddress) external view returns (TokenInfo memory); 31 | 32 | function getDepositConfig(uint256 toChainId, address tokenAddress) external view returns (TokenConfig memory); 33 | 34 | function getTransferConfig(address tokenAddress) external view returns (TokenConfig memory); 35 | 36 | function changeExcessStateFee(address _tokenAddress, uint256 _excessStateFeePer) external; 37 | 38 | function tokenAddressToSymbol(address tokenAddress) external view returns (uint256); 39 | 40 | function symbolToTokenAddress(uint256 symbol) external view returns (address); 41 | } 42 | -------------------------------------------------------------------------------- /scripts/backend-api-script/set-all-token-config.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { setTokenConfig } from "./add-supported-token"; 3 | import { getBackendConfig } from "./utils"; 4 | 5 | (async () => { 6 | const backendConfig = getBackendConfig("integration"); 7 | const tokenData = (await axios.get(`${backendConfig.baseUrl}/api/v1/configuration/tokens`)).data.message as any; 8 | const promises = []; 9 | for (const token of tokenData) { 10 | const chainWiseData: any[] = []; 11 | for (const [key, value] of Object.entries(token)) { 12 | if (!isNaN(parseInt(key))) { 13 | chainWiseData.push([key, value]); 14 | } 15 | } 16 | for (let i = 0; i < chainWiseData.length; i++) { 17 | for (let j = i + 1; j < chainWiseData.length; j++) { 18 | promises.push( 19 | setTokenConfig( 20 | [ 21 | [ 22 | { 23 | tokenSymbol: token.symbol, 24 | decimal: chainWiseData[i][1].decimal, 25 | chainId: chainWiseData[i][0], 26 | tokenAddress: chainWiseData[i][1].address, 27 | }, 28 | { 29 | tokenSymbol: token.symbol, 30 | decimal: chainWiseData[j][1].decimal, 31 | chainId: chainWiseData[j][0], 32 | tokenAddress: chainWiseData[j][1].address, 33 | }, 34 | ], 35 | ], 36 | backendConfig 37 | ) 38 | ); 39 | } 40 | } 41 | } 42 | await Promise.all(promises); 43 | })(); 44 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | ETHERSCAN_API_KEY=ABC123ABC123ABC123ABC123ABC123ABC1 2 | POLYGONSCAN_API_KEY=ABACBACACBACACABCABCACACBACACBAC 3 | SNOWTRACE_API_KEY=ABACBACACBACACABCABCACACBACACBAC 4 | BSCSCAN_API_KEY=4C2CZWI4ZY9I5A7FPZM2VYXJ58STRVCGU8 5 | OPTIMISM_ETHERSCAN_API_KEY= 6 | OPTIMISM_KOVAN_ETHERSCAN_API_KEY= 7 | ARBITRUM_ETHERSCAN_API_KEY= 8 | ARBITRUM_RINKEBY_ETHERSCAN_API_KEY= 9 | FTMSCAN_API_KEY= 10 | 11 | BSC_URL=https://bsc-dataseed.binance.org/ 12 | BSC_TESTNET_URL=https://data-seed-prebsc-1-s1.binance.org:8545/ 13 | ROPSTEN_URL=https://eth-ropsten.alchemyapi.io/v2/ 14 | RINKEBY_URL=https://eth-rinkeby.alchemyapi.io/v2/ 15 | GOERLI_URL=https://eth-goerli.alchemyapi.io/v2/ 16 | MUMBAI_URL=https://polygon-mumbai.g.alchemy.com/v2/ 17 | ARBITRUM_URL= 18 | ARBITRUM_RINKEBY_URL= 19 | OPTIMISM_KOVAN_URL= 20 | OPTIMISM_ETHEREUM_URL= 21 | FANTOM_URL= 22 | FANTOM_TESTNET_URL= 23 | 24 | STAGING_API_URL=https://hyphen-v2-staging-api.biconomy.io 25 | STAGING_API_USERNAME= 26 | STAGING_API_PASSWORD= 27 | STAGING_API_KEY= 28 | 29 | INTEGRATION_API_URL=https://hyphen-v2-integration-api.biconomy.io 30 | INTEGRATION_API_USERNAME= 31 | INTEGRATION_API_PASSWORD= 32 | INTEGRATION_API_KEY= 33 | 34 | LOCAL_API_URL=http://localhost:3000 35 | LOCAL_API_USERNAME= 36 | LOCAL_API_PASSWORD= 37 | LOCAL_API_KEY= 38 | 39 | PROD_API_URL=https://hyphen-v2-api.biconomy.io 40 | PROD_API_USERNAME= 41 | PROD_API_PASSWORD= 42 | PROD_API_KEY= 43 | 44 | PRIVATE_KEY=0xabc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc1 45 | INFURA_KEY= 46 | 47 | REPORT_GAS=true 48 | REPORT_SIZE=true -------------------------------------------------------------------------------- /scripts/backend-api-script/set-deposit-config.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import type { IBackendConfig } from "../types"; 3 | import { addSupportedTokenSmartContract } from "./add-supported-token"; 4 | 5 | interface IDeployConfigData { 6 | chainId: number; 7 | depositConfig: IChainConfig; 8 | } 9 | 10 | interface IChainConfig { 11 | toChainIds: number[]; 12 | tokenAddresses: string[]; 13 | tokenConfigs: ITokenConfig[]; 14 | } 15 | 16 | interface ITokenConfig { 17 | max: string; 18 | min: string; 19 | } 20 | 21 | const setConfig = async (configData: IDeployConfigData[], backendConfig: IBackendConfig) => { 22 | let response: any = { message: "Execution Finish", code: 200 }; 23 | for (let i = 0; i < configData.length; i++) { 24 | try { 25 | const depositConfigRes = await axios.post( 26 | `${backendConfig.baseUrl}/api/v1/admin/supported-token/smart-contract/set-deposit-config`, 27 | configData[i], 28 | { 29 | headers: { 30 | username: backendConfig.apiUsername, 31 | password: backendConfig.apiPassword, 32 | key: backendConfig.apiKey, 33 | }, 34 | } 35 | ); 36 | const data = await depositConfigRes.data; 37 | 38 | response[i] = { 39 | message: data.message, 40 | code: data.code, 41 | txHash: data.txHash, 42 | }; 43 | } catch (error) { 44 | console.error( 45 | `Error while adding ${JSON.stringify(configData[i])}: ${JSON.stringify((error as any).response.data)}` 46 | ); 47 | } 48 | } 49 | 50 | console.log(response); 51 | }; 52 | 53 | export { setConfig }; 54 | -------------------------------------------------------------------------------- /scripts/types.ts: -------------------------------------------------------------------------------- 1 | import { 2 | LiquidityPool, 3 | LPToken, 4 | WhitelistPeriodManager, 5 | LiquidityProviders, 6 | TokenManager, 7 | ExecutorManager, 8 | SvgHelperBase, 9 | HyphenLiquidityFarmingV2, 10 | // eslint-disable-next-line node/no-missing-import 11 | } from "../typechain"; 12 | import type { BigNumberish, ContractFactory } from "ethers"; 13 | 14 | export interface IAddTokenParameters { 15 | tokenAddress: string; 16 | minCap: BigNumberish; 17 | maxCap: BigNumberish; 18 | depositConfigs: { chainId: number; minCap: BigNumberish; maxCap: BigNumberish }[]; 19 | equilibriumFee: BigNumberish; 20 | maxFee: BigNumberish; 21 | transferOverhead: BigNumberish; 22 | maxWalletLiquidityCap: BigNumberish; 23 | maxLiquidityCap: BigNumberish; 24 | svgHelper: ContractFactory; 25 | decimals: number; 26 | rewardTokenAddress: string; 27 | rewardRatePerSecond: BigNumberish; 28 | excessStateTransferFeePer: BigNumberish; 29 | } 30 | 31 | export interface IContracts { 32 | liquidityProviders: LiquidityProviders; 33 | lpToken: LPToken; 34 | tokenManager: TokenManager; 35 | liquidityPool: LiquidityPool; 36 | whitelistPeriodManager: WhitelistPeriodManager; 37 | executorManager: ExecutorManager; 38 | liquidityFarming: HyphenLiquidityFarmingV2; 39 | svgHelperMap: Record; 40 | } 41 | 42 | export interface IContractAddresses { 43 | liquidityProviders?: string; 44 | lpToken?: string; 45 | tokenManager?: string; 46 | liquidityPool?: string; 47 | whitelistPeriodManager?: string; 48 | executorManager?: string; 49 | liquidityFarming?: string; 50 | liquidityFarmingV1?: string; 51 | liquidityFarmingV2?: string; 52 | svgHelperMap?: Record; 53 | } 54 | 55 | export interface IDeployConfig { 56 | trustedForwarder: string; 57 | bicoOwner: string; 58 | pauser: string; 59 | tokens: IAddTokenParameters[]; 60 | } 61 | 62 | export interface IBackendConfig { 63 | baseUrl: string; 64 | apiUsername: string; 65 | apiPassword: string; 66 | apiKey: string; 67 | } 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advanced Sample Hardhat Project 2 | 3 | This project demonstrates an advanced Hardhat use case, integrating other tools commonly used alongside Hardhat in the ecosystem. 4 | 5 | The project comes with a sample contract, a test for that contract, a sample script that deploys that contract, and an example of a task implementation, which simply lists the available accounts. It also comes with a variety of other tools, preconfigured to work with the project code. 6 | 7 | Try running some of the following tasks: 8 | 9 | ```shell 10 | npx hardhat accounts 11 | npx hardhat compile 12 | npx hardhat clean 13 | npx hardhat test 14 | npx hardhat node 15 | npx hardhat help 16 | REPORT_GAS=true npx hardhat test 17 | npx hardhat coverage 18 | npx hardhat run scripts/deploy.ts 19 | TS_NODE_FILES=true npx ts-node scripts/deploy.ts 20 | npx eslint '**/*.{js,ts}' 21 | npx eslint '**/*.{js,ts}' --fix 22 | npx prettier '**/*.{json,sol,md}' --check 23 | npx prettier '**/*.{json,sol,md}' --write 24 | npx solhint 'contracts/**/*.sol' 25 | npx solhint 'contracts/**/*.sol' --fix 26 | ``` 27 | 28 | # Etherscan verification 29 | 30 | To try out Etherscan verification, you first need to deploy a contract to an Ethereum network that's supported by Etherscan, such as Ropsten. 31 | 32 | In this project, copy the .env.example file to a file named .env, and then edit it to fill in the details. Enter your Etherscan API key, your Ropsten node URL (eg from Alchemy), and the private key of the account which will send the deployment transaction. With a valid .env file in place, first deploy your contract: 33 | 34 | ```shell 35 | hardhat run --network ropsten scripts/sample-script.ts 36 | ``` 37 | 38 | Then, copy the deployment address and paste it in to replace `DEPLOYED_CONTRACT_ADDRESS` in this command: 39 | 40 | ```shell 41 | npx hardhat verify --network ropsten DEPLOYED_CONTRACT_ADDRESS "Hello, Hardhat!" 42 | ``` 43 | 44 | # Performance optimizations 45 | 46 | For faster runs of your tests and scripts, consider skipping ts-node's type checking by setting the environment variable `TS_NODE_TRANSPILE_ONLY` to `1` in hardhat's environment. For more details see [the documentation](https://hardhat.org/guides/typescript.html#performance-optimizations). 47 | -------------------------------------------------------------------------------- /contracts/hyphen/metatx/ERC2771ContextUpgradeable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.0; 4 | 5 | import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; 6 | import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; 7 | 8 | /** 9 | * @dev Context variant with ERC2771 support. 10 | * Here _trustedForwarder is made internal instead of private 11 | * so it can be changed via Child contracts with a setter method. 12 | */ 13 | abstract contract ERC2771ContextUpgradeable is Initializable, ContextUpgradeable { 14 | event TrustedForwarderChanged(address indexed _tf); 15 | 16 | address internal _trustedForwarder; 17 | 18 | function __ERC2771Context_init(address trustedForwarder) internal initializer { 19 | __Context_init_unchained(); 20 | __ERC2771Context_init_unchained(trustedForwarder); 21 | } 22 | 23 | function __ERC2771Context_init_unchained(address trustedForwarder) internal initializer { 24 | _trustedForwarder = trustedForwarder; 25 | } 26 | 27 | function isTrustedForwarder(address forwarder) public view virtual returns (bool) { 28 | return forwarder == _trustedForwarder; 29 | } 30 | 31 | function _msgSender() internal view virtual override returns (address sender) { 32 | if (isTrustedForwarder(msg.sender)) { 33 | // The assembly code is more direct than the Solidity version using `abi.decode`. 34 | assembly { 35 | sender := shr(96, calldataload(sub(calldatasize(), 20))) 36 | } 37 | } else { 38 | return super._msgSender(); 39 | } 40 | } 41 | 42 | function _msgData() internal view virtual override returns (bytes calldata) { 43 | if (isTrustedForwarder(msg.sender)) { 44 | return msg.data[:msg.data.length - 20]; 45 | } else { 46 | return super._msgData(); 47 | } 48 | } 49 | 50 | function _setTrustedForwarder(address _tf) internal virtual { 51 | require(_tf != address(0), "TrustedForwarder can't be 0"); 52 | _trustedForwarder = _tf; 53 | emit TrustedForwarderChanged(_tf); 54 | } 55 | 56 | uint256[49] private __gap; 57 | } 58 | -------------------------------------------------------------------------------- /contracts/hyphen/proxy/LiquidityPoolProxy.sol: -------------------------------------------------------------------------------- 1 | // contracts/bico-token/bico/BicoToken.sol 2 | 3 | // SPDX-License-Identifier: MIT 4 | pragma solidity 0.8.2; 5 | 6 | import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 7 | 8 | /** 9 | * @dev This contract implements a proxy that is upgradeable by an admin. 10 | * 11 | * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector 12 | * clashing], which can potentially be used in an attack, this contract uses the 13 | * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two 14 | * things that go hand in hand: 15 | * 16 | * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if 17 | * that call matches one of the admin functions exposed by the proxy itself. 18 | * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the 19 | * implementation. If the admin tries to call a function on the implementation it will fail with an error that says 20 | * "admin cannot fallback to proxy target". 21 | * 22 | * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing 23 | * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due 24 | * to sudden errors when trying to call a function from the proxy implementation. 25 | * 26 | * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, 27 | * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. 28 | */ 29 | contract LiquidityPoolProxy is TransparentUpgradeableProxy { 30 | constructor(address _implementation, address _admin) 31 | TransparentUpgradeableProxy(_implementation, _admin, bytes("")) 32 | {} 33 | 34 | function getAdmin() external view returns (address adm) { 35 | adm = _admin(); 36 | } 37 | 38 | function getImplementation() external view returns (address impl) { 39 | impl = _implementation(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@biconomy/hyphen-contracts", 3 | "version": "1.0.5", 4 | "description": "Biconomy Liquidity Protocol Contracts", 5 | "devDependencies": { 6 | "@defi-wonderland/smock": "^2.3.0", 7 | "@nomiclabs/hardhat-ethers": "^2.0.0", 8 | "@nomiclabs/hardhat-waffle": "^2.0.0", 9 | "@openzeppelin/hardhat-upgrades": "^1.12.0", 10 | "@typechain/ethers-v5": "^7.0.1", 11 | "@typechain/hardhat": "^2.3.0", 12 | "@types/chai": "^4.2.21", 13 | "@types/chai-almost": "^1.0.1", 14 | "@types/mocha": "^9.0.0", 15 | "@types/node": "^16.4.13", 16 | "@typescript-eslint/eslint-plugin": "^4.29.1", 17 | "@typescript-eslint/parser": "^4.29.1", 18 | "@uniswap/v2-periphery": "^1.1.0-beta.0", 19 | "chai": "^4.2.0", 20 | "chai-almost": "^1.0.1", 21 | "dotenv": "^10.0.0", 22 | "eslint": "^7.29.0", 23 | "eslint-config-prettier": "^8.3.0", 24 | "eslint-config-standard": "^16.0.3", 25 | "eslint-plugin-import": "^2.23.4", 26 | "eslint-plugin-node": "^11.1.0", 27 | "eslint-plugin-prettier": "^3.4.0", 28 | "eslint-plugin-promise": "^5.1.0", 29 | "ethers": "^5.0.0", 30 | "hardhat": "^2.8.4", 31 | "hardhat-contract-sizer": "^2.4.0", 32 | "hardhat-gas-reporter": "^1.0.4", 33 | "prettier": "^2.3.2", 34 | "prettier-plugin-solidity": "^1.0.0-beta.13", 35 | "solhint": "^3.3.6", 36 | "solidity-coverage": "^0.7.17", 37 | "ts-node": "^10.1.0", 38 | "typechain": "^5.1.2", 39 | "typescript": "^4.3.5" 40 | }, 41 | "dependencies": { 42 | "@biconomy/ccmp-contracts": "^0.0.6", 43 | "@nomiclabs/hardhat-etherscan": "^3.1.0", 44 | "@openzeppelin/contracts": "4.3.0", 45 | "@openzeppelin/contracts-upgradeable": "4.3.0", 46 | "abdk-libraries-solidity": "^3.0.0", 47 | "axios": "^0.27.2", 48 | "base64-sol": "^1.1.0", 49 | "ethereum-waffle": "^3.4.4" 50 | }, 51 | "scripts": { 52 | "build": "hardhat compile", 53 | "compile": "hardhat compile", 54 | "test": "hardhat test", 55 | "coverage": "hardhat coverage", 56 | "deploy:goerli": "hardhat run scripts/deploy-goerli.ts --network goerli", 57 | "deploy:mumbai": "hardhat run scripts/deploy-mumbai.ts --network polygonMumbai", 58 | "deploy:fuji": "hardhat run scripts/deploy-fuji.ts --network fuji" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /scripts/prod-replica-helpers/utils.ts: -------------------------------------------------------------------------------- 1 | import { ethers, network } from "hardhat"; 2 | import { ContractTransaction, ContractReceipt, BigNumberish } from "ethers"; 3 | import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; 4 | 5 | export const sendTransaction = async ( 6 | tx: Promise, 7 | description?: string 8 | ): Promise => { 9 | const { wait, hash, chainId } = await tx; 10 | console.log(`Sent Transaction ${hash} on chain ${chainId} ${description}`); 11 | const receipt = await wait(); 12 | if (receipt.status === 1) { 13 | console.log(`Transaction ${hash} on chain ${chainId} for ${description} confirmed on block ${receipt.blockNumber}`); 14 | } else { 15 | console.log(`Transaction ${hash} on chain ${chainId} for ${description} failed`); 16 | } 17 | return receipt; 18 | }; 19 | 20 | export const impersonateAndExecute = async ( 21 | addressToImpersonate: string, 22 | action: (signer: SignerWithAddress) => Promise 23 | ) => { 24 | console.log(`Impersonating ${addressToImpersonate}...`); 25 | const result = await network.provider.request({ 26 | method: "hardhat_impersonateAccount", 27 | params: [addressToImpersonate], 28 | }); 29 | console.log(`Impersonation Request Result: ${JSON.stringify(result, null, 2)}`); 30 | const signer = await ethers.getSigner(addressToImpersonate); 31 | try { 32 | await action(signer); 33 | } catch (e) { 34 | console.error(`Error executing action with impersonated accoutn: ${e}`); 35 | } 36 | console.log(`Stop Impersonating ${addressToImpersonate}...`); 37 | await network.provider.request({ 38 | method: "hardhat_stopImpersonatingAccount", 39 | params: [addressToImpersonate], 40 | }); 41 | }; 42 | 43 | export const setNativeBalance = async (address: string, balance: BigNumberish) => { 44 | const { chainId } = await ethers.provider.getNetwork(); 45 | console.log(`Setting native balance of ${address} to ${balance} on chain ${chainId}`); 46 | await network.provider.send("hardhat_setBalance", [ 47 | address, 48 | ethers.BigNumber.from(balance).toHexString().replace("0x0", "0x"), 49 | ]); 50 | const updatedBalance = await ethers.provider.getBalance(address); 51 | console.log(`Native balance of ${address} is now ${updatedBalance} on chain ${chainId}`); 52 | }; 53 | -------------------------------------------------------------------------------- /scripts/prod-replica-helpers/fund-account.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { ERC20Token__factory } from "../../typechain"; 3 | import { getSupportedTokenAddresses } from "../upgrades/upgrade-all/upgrade-all"; 4 | import { impersonateAndExecute, sendTransaction, setNativeBalance } from "./utils"; 5 | import tokenAddressToFundingAccount from "./token-address-to-funding-account"; 6 | 7 | const fundErc20FromAccount = async (fundingAccount: string, tokenAddress: string, to: string) => { 8 | await impersonateAndExecute(fundingAccount, async (signer) => { 9 | const { chainId } = await ethers.provider.getNetwork(); 10 | const token = ERC20Token__factory.connect(tokenAddress, signer); 11 | const liquidity = await token.balanceOf(signer.address); 12 | const amount = liquidity.div(2); 13 | console.log(`Funding ${to} with ${amount} ${tokenAddress} from ${fundingAccount} on chain ${chainId}...`); 14 | await sendTransaction(token.transfer(to, amount), "Funding ERC20 Token"); 15 | const finalBalance = await token.balanceOf(to); 16 | console.log(`${to} has ${finalBalance} ${tokenAddress} on chain ${chainId}`); 17 | }); 18 | }; 19 | 20 | (async () => { 21 | await setNativeBalance(process.env.TRANSACTOR_ADDRESS!, ethers.utils.parseEther("1000")); 22 | const { chainId } = await ethers.provider.getNetwork(); 23 | const supportedTokenAddresses = (await getSupportedTokenAddresses(process.env.PROD_API_URL!, chainId)).filter( 24 | (x) => x.toLowerCase() !== "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" 25 | ); 26 | console.log(`Supported ERC20 Tokens on chain ${chainId}: ${JSON.stringify(supportedTokenAddresses, null, 2)}`); 27 | for (const token of supportedTokenAddresses) { 28 | const fundingAccount = 29 | tokenAddressToFundingAccount[token.toLowerCase() as keyof typeof tokenAddressToFundingAccount]; 30 | if (!fundingAccount) { 31 | console.error(`No funding account found for ${token}`); 32 | continue; 33 | } 34 | const fundingAccountNativeBalance = await ethers.provider.getBalance(fundingAccount); 35 | if (fundingAccountNativeBalance.eq(0)) { 36 | await setNativeBalance(fundingAccount, ethers.utils.parseEther("1000")); 37 | } 38 | 39 | await fundErc20FromAccount(fundingAccount, token, process.env.TRANSACTOR_ADDRESS!); 40 | } 41 | })(); 42 | -------------------------------------------------------------------------------- /test/ExecutorManager.tests.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "chai"; 2 | import { ethers, upgrades } from "hardhat"; 3 | import { 4 | ExecutorManager, 5 | // eslint-disable-next-line node/no-missing-import 6 | } from "../typechain"; 7 | import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; 8 | import { BigNumber } from "ethers"; 9 | 10 | describe("ExecutorManagerTests", function () { 11 | let owner: SignerWithAddress, pauser: SignerWithAddress, bob: SignerWithAddress; 12 | let charlie: SignerWithAddress, tf: SignerWithAddress, executor: SignerWithAddress; 13 | let executorManager: ExecutorManager; 14 | 15 | beforeEach(async function () { 16 | [owner, pauser, charlie, bob, tf, executor] = await ethers.getSigners(); 17 | 18 | const executorManagerFactory = await ethers.getContractFactory("ExecutorManager"); 19 | executorManager = await executorManagerFactory.deploy(); 20 | await executorManager.deployed(); 21 | }); 22 | 23 | it("Should register executor", async function () { 24 | await executorManager.addExecutor(executor.address); 25 | expect(await executorManager.getAllExecutors()).to.deep.equal([executor.address]); 26 | expect(await executorManager.getExecutorStatus(executor.address)).to.be.true; 27 | }); 28 | 29 | it("Should return false for non executor", async function () { 30 | expect(await executorManager.getExecutorStatus(executor.address)).to.be.false; 31 | }); 32 | 33 | it("Should be able to add multiple executors", async function () { 34 | await executorManager.addExecutors([executor.address, bob.address]); 35 | expect((await executorManager.getAllExecutors()).length).to.equal(2); 36 | expect(await executorManager.getExecutorStatus(executor.address)).to.be.true; 37 | expect(await executorManager.getExecutorStatus(bob.address)).to.be.true; 38 | }); 39 | 40 | it("Should be able to remove multiple executors", async function () { 41 | await executorManager.addExecutors([executor.address, bob.address]); 42 | await executorManager.removeExecutors([executor.address, bob.address]); 43 | expect((await executorManager.getAllExecutors()).length).to.equal(0); 44 | expect(await executorManager.getExecutorStatus(executor.address)).to.be.false; 45 | expect(await executorManager.getExecutorStatus(bob.address)).to.be.false; 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | node_modules 107 | .env 108 | coverage 109 | coverage.json 110 | typechain 111 | 112 | #Hardhat files 113 | cache 114 | artifacts 115 | .openzeppelin 116 | 117 | .DS_Store -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/IWhiteListPeriodManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | interface IWhiteListPeriodManager { 5 | function areWhiteListRestrictionsEnabled() external view returns (bool); 6 | 7 | function beforeLiquidityAddition( 8 | address _lp, 9 | address _token, 10 | uint256 _amount 11 | ) external; 12 | 13 | function beforeLiquidityRemoval( 14 | address _lp, 15 | address _token, 16 | uint256 _amount 17 | ) external; 18 | 19 | function beforeLiquidityTransfer( 20 | address _from, 21 | address _to, 22 | address _token, 23 | uint256 _amount 24 | ) external; 25 | 26 | function getMaxCommunityLpPositon(address _token) external view returns (uint256); 27 | 28 | function initialize( 29 | address _trustedForwarder, 30 | address _liquidityProviders, 31 | address _tokenManager 32 | ) external; 33 | 34 | function isExcludedAddress(address) external view returns (bool); 35 | 36 | function isTrustedForwarder(address forwarder) external view returns (bool); 37 | 38 | function owner() external view returns (address); 39 | 40 | function paused() external view returns (bool); 41 | 42 | function perTokenTotalCap(address) external view returns (uint256); 43 | 44 | function perTokenWalletCap(address) external view returns (uint256); 45 | 46 | function renounceOwnership() external; 47 | 48 | function setAreWhiteListRestrictionsEnabled(bool _status) external; 49 | 50 | function setCap( 51 | address _token, 52 | uint256 _totalCap, 53 | uint256 _perTokenWalletCap 54 | ) external; 55 | 56 | function setCaps( 57 | address[] memory _tokens, 58 | uint256[] memory _totalCaps, 59 | uint256[] memory _perTokenWalletCaps 60 | ) external; 61 | 62 | function setIsExcludedAddressStatus(address[] memory _addresses, bool[] memory _status) external; 63 | 64 | function setLiquidityProviders(address _liquidityProviders) external; 65 | 66 | function setPerTokenWalletCap(address _token, uint256 _perTokenWalletCap) external; 67 | 68 | function setTokenManager(address _tokenManager) external; 69 | 70 | function setTotalCap(address _token, uint256 _totalCap) external; 71 | 72 | function transferOwnership(address newOwner) external; 73 | } 74 | -------------------------------------------------------------------------------- /scripts/upgrades/upgrade.ts: -------------------------------------------------------------------------------- 1 | import { ethers, upgrades } from "hardhat"; 2 | 3 | export async function upgradeLiquidityPool(proxyAddress: string) { 4 | const feeLibFactory = await ethers.getContractFactory("Fee"); 5 | const Fee = await feeLibFactory.deploy(); 6 | await Fee.deployed(); 7 | 8 | const LiquidityPoolFactory = await ethers.getContractFactory("LiquidityPool", { 9 | libraries: { 10 | Fee: Fee.address, 11 | }, 12 | }); 13 | const contract = await upgrades.upgradeProxy(proxyAddress, LiquidityPoolFactory, { 14 | unsafeAllow: ["external-library-linking"], 15 | }); 16 | await contract.deployed(); 17 | console.log("LiquidityPool Upgraded"); 18 | } 19 | 20 | export async function upgradeLiquidityProviders(proxyAddress: string) { 21 | const contract = await upgrades.upgradeProxy(proxyAddress, await ethers.getContractFactory("LiquidityProviders")); 22 | await contract.deployed(); 23 | console.log("LiquidityProviders Upgraded"); 24 | } 25 | 26 | export async function upgradeLPToken(proxyAddress: string) { 27 | const contract = await upgrades.upgradeProxy(proxyAddress, await ethers.getContractFactory("LPToken")); 28 | await contract.deployed(); 29 | console.log("LpToken Upgraded"); 30 | } 31 | 32 | export async function upgradeWhiteListPeriodManager(proxyAddress: string) { 33 | const contract = await upgrades.upgradeProxy(proxyAddress, await ethers.getContractFactory("WhitelistPeriodManager")); 34 | await contract.deployed(); 35 | console.log("WhitelistPeriodManager Upgraded"); 36 | } 37 | 38 | export async function upgradeLiquidityFarming(proxyAddress: string) { 39 | const contract = await upgrades.upgradeProxy(proxyAddress, await ethers.getContractFactory("HyphenLiquidityFarming")); 40 | await contract.deployed(); 41 | console.log("LiquidityFarming Upgraded"); 42 | } 43 | 44 | export async function upgradeLiquidityFarmingV2(proxyAddress: string) { 45 | const contract = await upgrades.upgradeProxy( 46 | proxyAddress, 47 | await ethers.getContractFactory("HyphenLiquidityFarmingV2") 48 | ); 49 | await contract.deployed(); 50 | console.log("LiquidityFarmingV2 Upgraded"); 51 | } 52 | 53 | export async function upgradeTokenManager(proxyAddress: string) { 54 | const contract = await upgrades.upgradeProxy(proxyAddress, await ethers.getContractFactory("TokenManager")); 55 | await contract.deployed(); 56 | console.log("TokenManager Upgraded"); 57 | } 58 | -------------------------------------------------------------------------------- /scripts/prod-replica-helpers/upgrade-force-import.ts: -------------------------------------------------------------------------------- 1 | import { getContractAddresses, getContractAddressesByChain } from "../upgrades/upgrade-all/upgrade-all"; 2 | import { ethers, upgrades } from "hardhat"; 3 | import { IContractAddresses } from "../types"; 4 | 5 | const forceImportForUpgrade = async (contracts: IContractAddresses) => { 6 | await Promise.all([ 7 | contracts.liquidityPool && 8 | upgrades.forceImport( 9 | contracts.liquidityPool, 10 | await ethers.getContractFactory("LiquidityPool", { 11 | libraries: { 12 | Fee: contracts.liquidityPool, 13 | }, 14 | }), 15 | { 16 | kind: "transparent", 17 | } 18 | ), 19 | contracts.liquidityProviders && 20 | upgrades.forceImport(contracts.liquidityProviders, await ethers.getContractFactory("LiquidityProviders"), { 21 | kind: "transparent", 22 | }), 23 | contracts.lpToken && 24 | upgrades.forceImport(contracts.lpToken, await ethers.getContractFactory("LPToken"), { 25 | kind: "transparent", 26 | }), 27 | contracts.tokenManager && 28 | upgrades.forceImport(contracts.tokenManager, await ethers.getContractFactory("TokenManager"), { 29 | kind: "transparent", 30 | }), 31 | contracts.whitelistPeriodManager && 32 | upgrades.forceImport( 33 | contracts.whitelistPeriodManager, 34 | await ethers.getContractFactory("WhitelistPeriodManager"), 35 | { 36 | kind: "transparent", 37 | } 38 | ), 39 | contracts.liquidityFarmingV1 && 40 | upgrades.forceImport(contracts.liquidityFarmingV1, await ethers.getContractFactory("HyphenLiquidityFarming"), { 41 | kind: "transparent", 42 | }), 43 | contracts.liquidityFarmingV2 && 44 | upgrades.forceImport(contracts.liquidityFarmingV2, await ethers.getContractFactory("HyphenLiquidityFarmingV2"), { 45 | kind: "transparent", 46 | }), 47 | ]); 48 | }; 49 | 50 | (async () => { 51 | const chainId = (await ethers.provider.getNetwork()).chainId; 52 | // const contracts = await getContractAddressesByChain(process.env.PROD_API_URL as string, chainId); 53 | const contracts = { 54 | liquidityPool: "0xb831F0848A055b146a0b13D54cfFa6C1FE201b83", 55 | }; 56 | console.log(`Forcing Import for Contracts on chain ${chainId}: ${JSON.stringify(contracts, null, 2)}`); 57 | await forceImportForUpgrade(contracts); 58 | })(); 59 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | 4 | 5 | - ... 6 | - ... 7 | 8 | ## Type of change 9 | 10 | 11 | 12 | - [ ] Bug fix (non-breaking change which fixes an issue) 13 | - [ ] New feature (non-breaking change which adds functionality) 14 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 15 | - [ ] This change requires a documentation update 16 | 17 | # How Has This Been Tested? 18 | 19 | 20 | 21 | - [ ] Manual Testing 22 | - Sample results/txn hashes/screenshots: 23 | - ... 24 | - ... 25 | - [ ] Automated Testing 26 | - ... 27 | 28 | 29 | ## Test Configuration: 30 | 31 | - ... 32 | 33 | ## Steps to reproduce 34 | 35 | - ... 36 | 37 | ### Using New Sample API 38 | **Endpoint**: `/api/v1/admin/withdraw-gas-fee/erc20` 39 | 40 | **Sample Request**: 41 | ``` 42 | { 43 | "chainId": 80001, 44 | "executorAddress": "0xb214cb91ea1485dadfecd49114c58d5710d135a8", 45 | "tokenAddress": "0xeaBc4b91d9375796AA4F69cC764A4aB509080A58" 46 | } 47 | ``` 48 | 49 | **Sample Response**: 50 | ``` 51 | { 52 | "amountWithdrawn": "5000000000000000000" 53 | "txHash": "0x123... 54 | } 55 | ``` 56 | 57 | ## Automated Tests Added/Updated 58 | 59 | - E2E Tests 60 | - [ ] ... 61 | - Unit Tests 62 | - [ ] ... 63 | 64 | ## Coverage 65 | 66 | 67 | # Checklist: 68 | 69 | - [ ] My code follows the style guidelines of this project 70 | - [ ] I have performed a self-review of my code 71 | - [ ] I have commented my code, particularly in hard-to-understand areas 72 | - [ ] I have made corresponding changes to the documentation 73 | - [ ] My changes generate no new warnings 74 | - [ ] I have added tests that prove my fix is effective or that my feature works 75 | - [ ] New and existing unit tests pass locally with my changes 76 | - [ ] Any dependent changes have been merged and published in downstream modules -------------------------------------------------------------------------------- /scripts/backend-api-script/add-supported-token.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import type { IBackendConfig } from "../types"; 3 | 4 | const addSupportedTokenDb = async (configData: any, backendConfig: IBackendConfig) => { 5 | let response: any = { message: "Execution Finish", code: 200 }; 6 | 7 | for (let i = 0; i < configData.length; i++) { 8 | try { 9 | const tokenConfigRes = await axios.post( 10 | `${backendConfig.baseUrl}/api/v1/admin/supported-token/db/add`, 11 | configData[i], 12 | { 13 | headers: { 14 | username: backendConfig.apiUsername, 15 | password: backendConfig.apiPassword, 16 | key: backendConfig.apiKey, 17 | }, 18 | } 19 | ); 20 | const data = tokenConfigRes.data; 21 | if (!data.pairOne) { 22 | response[i] = { 23 | code: data.code, 24 | message: data.message, 25 | }; 26 | } else { 27 | response[i] = { 28 | pairOne: data.pairOne, 29 | pairTwo: data.pairTwo, 30 | }; 31 | } 32 | } catch (error) { 33 | console.error( 34 | `Error while adding ${JSON.stringify(configData[i])}: ${JSON.stringify((error as any).response.data)}` 35 | ); 36 | } 37 | console.log(response); 38 | } 39 | }; 40 | 41 | const addSupportedTokenSmartContract = async (configData: any, backendConfig: IBackendConfig) => { 42 | let response: any = { message: "Execution Finish", code: 200 }; 43 | 44 | for (let i = 0; i < configData.length; i++) { 45 | try { 46 | const tokenConfigRes = await axios.post( 47 | `${backendConfig.baseUrl}/api/v1/admin/supported-token/smart-contract/add`, 48 | configData[i], 49 | { 50 | headers: { 51 | username: backendConfig.apiUsername, 52 | password: backendConfig.apiPassword, 53 | key: backendConfig.apiKey, 54 | }, 55 | } 56 | ); 57 | const data = tokenConfigRes.data; 58 | if (!data.pairOne) { 59 | response[i] = { 60 | code: data.code, 61 | message: data.message, 62 | }; 63 | } else { 64 | response[i] = { 65 | pairOne: data.pairOne, 66 | pairTwo: data.pairTwo, 67 | }; 68 | } 69 | } catch (error) { 70 | console.error( 71 | `Error while adding ${JSON.stringify(configData[i])}: ${JSON.stringify((error as any).response.data)}` 72 | ); 73 | } 74 | console.log(response); 75 | } 76 | }; 77 | 78 | export { addSupportedTokenDb as setTokenConfig, addSupportedTokenSmartContract }; 79 | -------------------------------------------------------------------------------- /scripts/token-manager/deploy-fuji.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy, IDeployConfig } from "./helper"; 4 | 5 | (async () => { 6 | const config: IDeployConfig = { 7 | trustedForwarder: "0x6271Ca63D30507f2Dcbf99B52787032506D75BBF", 8 | bicoOwner: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 9 | pauser: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 10 | tokens: [ 11 | { 12 | tokenAddress: "0xB4E0F6FEF81BdFea0856bB846789985c9CFf7e85", 13 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 14 | maxCap: ethers.BigNumber.from(10).pow(18 + 4), 15 | depositConfigs: [ 16 | { 17 | chainId: 5, 18 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 19 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 20 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 21 | }, 22 | { 23 | chainId: 80001, 24 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 25 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 26 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 27 | }, 28 | ], 29 | equilibriumFee: 10000000, 30 | maxFee: 200000000, 31 | transferOverhead: 0, 32 | excessStateTransferFeePer: parseUnits("0.045", 8), 33 | }, 34 | { 35 | tokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", 36 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 37 | maxCap: ethers.BigNumber.from(10).pow(18 + 2), 38 | depositConfigs: [ 39 | { 40 | chainId: 80001, 41 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 42 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 43 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 44 | }, 45 | { 46 | chainId: 5, 47 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 48 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 49 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 50 | }, 51 | ], 52 | equilibriumFee: 10000000, 53 | maxFee: 200000000, 54 | transferOverhead: 0, 55 | excessStateTransferFeePer: parseUnits("0.045", 8), 56 | }, 57 | ], 58 | }; 59 | await deploy(config); 60 | })(); 61 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/ILiquidityProviders.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | interface ILiquidityProviders { 5 | function BASE_DIVISOR() external view returns (uint256); 6 | 7 | function initialize(address _trustedForwarder, address _lpToken) external; 8 | 9 | function addLPFee(address _token, uint256 _amount) external; 10 | 11 | function addNativeLiquidity() external; 12 | 13 | function addTokenLiquidity(address _token, uint256 _amount) external; 14 | 15 | function claimFee(uint256 _nftId) external; 16 | 17 | function getFeeAccumulatedOnNft(uint256 _nftId) external view returns (uint256); 18 | 19 | function getSuppliedLiquidityByToken(address tokenAddress) external view returns (uint256); 20 | 21 | function getTokenPriceInLPShares(address _baseToken) external view returns (uint256); 22 | 23 | function getTotalLPFeeByToken(address tokenAddress) external view returns (uint256); 24 | 25 | function getTotalReserveByToken(address tokenAddress) external view returns (uint256); 26 | 27 | function getSuppliedLiquidity(uint256 _nftId) external view returns (uint256); 28 | 29 | function increaseNativeLiquidity(uint256 _nftId) external; 30 | 31 | function increaseTokenLiquidity(uint256 _nftId, uint256 _amount) external; 32 | 33 | function isTrustedForwarder(address forwarder) external view returns (bool); 34 | 35 | function owner() external view returns (address); 36 | 37 | function paused() external view returns (bool); 38 | 39 | function removeLiquidity(uint256 _nftId, uint256 amount) external; 40 | 41 | function renounceOwnership() external; 42 | 43 | function setLiquidityPool(address _liquidityPool) external; 44 | 45 | function setLpToken(address _lpToken) external; 46 | 47 | function setWhiteListPeriodManager(address _whiteListPeriodManager) external; 48 | 49 | function sharesToTokenAmount(uint256 _shares, address _tokenAddress) external view returns (uint256); 50 | 51 | function totalLPFees(address) external view returns (uint256); 52 | 53 | function totalLiquidity(address) external view returns (uint256); 54 | 55 | function totalReserve(address) external view returns (uint256); 56 | 57 | function totalSharesMinted(address) external view returns (uint256); 58 | 59 | function transferOwnership(address newOwner) external; 60 | 61 | function whiteListPeriodManager() external view returns (address); 62 | 63 | function increaseCurrentLiquidity(address tokenAddress, uint256 amount) external; 64 | 65 | function decreaseCurrentLiquidity(address tokenAddress, uint256 amount) external; 66 | 67 | function getCurrentLiquidity(address tokenAddress) external view returns (uint256); 68 | } 69 | -------------------------------------------------------------------------------- /contracts/hyphen/lib/TransferHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity 0.8.0; 3 | pragma abicoder v2; 4 | import "../interfaces/IERC20.sol"; 5 | 6 | library TransferHelper { 7 | /// @notice Transfers tokens from the targeted address to the given destination 8 | /// @notice Errors with 'STF' if transfer fails 9 | /// @param token The contract address of the token to be transferred 10 | /// @param from The originating address from which the tokens will be transferred 11 | /// @param to The destination address of the transfer 12 | /// @param value The amount to be transferred 13 | function safeTransferFrom( 14 | address token, 15 | address from, 16 | address to, 17 | uint256 value 18 | ) internal { 19 | (bool success, bytes memory data) = 20 | token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)); 21 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF'); 22 | } 23 | 24 | /// @notice Transfers tokens from msg.sender to a recipient 25 | /// @dev Errors with ST if transfer fails 26 | /// @param token The contract address of the token which will be transferred 27 | /// @param to The recipient of the transfer 28 | /// @param value The value of the transfer 29 | function safeTransfer( 30 | address token, 31 | address to, 32 | uint256 value 33 | ) internal { 34 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value)); 35 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST'); 36 | } 37 | 38 | /// @notice Approves the stipulated contract to spend the given allowance in the given token 39 | /// @dev Errors with 'SA' if transfer fails 40 | /// @param token The contract address of the token to be approved 41 | /// @param to The target of the approval 42 | /// @param value The amount of the given token the target will be allowed to spend 43 | function safeApprove( 44 | address token, 45 | address to, 46 | uint256 value 47 | ) internal { 48 | (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value)); 49 | require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA'); 50 | } 51 | 52 | /// @notice Transfers ETH to the recipient address 53 | /// @dev Fails with `STE` 54 | /// @param to The destination of the transfer 55 | /// @param value The value to be transferred 56 | function safeTransferETH(address to, uint256 value) internal { 57 | (bool success, ) = to.call{value: value}(new bytes(0)); 58 | require(success, 'STE'); 59 | } 60 | } -------------------------------------------------------------------------------- /contracts/test/CCMPGatewayMock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | import "../hyphen/interfaces/ICCMPGateway.sol"; 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | 7 | contract CCMPGatewayMock is ICCMPGateway { 8 | address private constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; 9 | 10 | struct sendMessageArgs { 11 | uint256 destinationChainId; 12 | string adaptorName; 13 | ICCMPGateway.CCMPMessagePayload[] payloads; 14 | ICCMPGateway.GasFeePaymentArgs gasFeePaymentArgs; 15 | bytes routerArgs; 16 | } 17 | 18 | sendMessageArgs public lastCallArgs; 19 | 20 | bool shouldRevert = false; 21 | 22 | function sendMessage( 23 | uint256 _destinationChainId, 24 | string calldata _adaptorName, 25 | ICCMPGateway.CCMPMessagePayload[] calldata _payloads, 26 | ICCMPGateway.GasFeePaymentArgs calldata _gasFeePaymentArgs, 27 | bytes calldata _routerArgs 28 | ) external payable override returns (bool sent) { 29 | if (shouldRevert) { 30 | revert("Mocked revert"); 31 | } 32 | 33 | if (_gasFeePaymentArgs.feeTokenAddress != NATIVE) { 34 | IERC20(_gasFeePaymentArgs.feeTokenAddress).transferFrom( 35 | msg.sender, 36 | _gasFeePaymentArgs.relayer, 37 | _gasFeePaymentArgs.feeAmount 38 | ); 39 | } else { 40 | (bool success, bytes memory returndata) = _gasFeePaymentArgs.relayer.call{ 41 | value: _gasFeePaymentArgs.feeAmount 42 | }(""); 43 | require(success, string(returndata)); 44 | } 45 | 46 | sent = true; 47 | 48 | lastCallArgs.destinationChainId = _destinationChainId; 49 | lastCallArgs.adaptorName = _adaptorName; 50 | lastCallArgs.routerArgs = _routerArgs; 51 | lastCallArgs.gasFeePaymentArgs = _gasFeePaymentArgs; 52 | 53 | for (uint256 i = 0; i < _payloads.length; i++) { 54 | lastCallArgs.payloads.push(_payloads[i]); 55 | } 56 | } 57 | 58 | function lastCallPayload() external view returns (ICCMPGateway.CCMPMessagePayload[] memory) { 59 | return lastCallArgs.payloads; 60 | } 61 | 62 | function setRevertStatus(bool _shouldRevert) external { 63 | shouldRevert = _shouldRevert; 64 | } 65 | 66 | function callContract( 67 | address to, 68 | bytes calldata _calldata, 69 | uint256 _fromChainId, 70 | address _fromContractAddress 71 | ) external { 72 | (bool success, bytes memory returnData) = to.call( 73 | abi.encodePacked(_calldata, _fromChainId, _fromContractAddress) 74 | ); 75 | require(success, string(returnData)); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /contracts/security/Pausable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.8.0; 4 | 5 | import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; 6 | import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; 7 | 8 | /** 9 | * @dev Contract module which allows children to implement an emergency stop 10 | * mechanism that can be triggered by an authorized account. 11 | * 12 | * This module is used through inheritance. It will make available the 13 | * modifiers `whenNotPaused` and `whenPaused`, which can be applied to 14 | * the functions of your contract. Note that they will not be pausable by 15 | * simply including this module, only once the modifiers are put in place. 16 | */ 17 | abstract contract Pausable is Initializable, PausableUpgradeable { 18 | address private _pauser; 19 | 20 | event PauserChanged(address indexed previousPauser, address indexed newPauser); 21 | 22 | /** 23 | * @dev The pausable constructor sets the original `pauser` of the contract to the sender 24 | * account & Initializes the contract in unpaused state.. 25 | */ 26 | function __Pausable_init(address pauser) internal initializer { 27 | require(pauser != address(0), "Pauser Address cannot be 0"); 28 | __Pausable_init(); 29 | _pauser = pauser; 30 | } 31 | 32 | /** 33 | * @return true if `msg.sender` is the owner of the contract. 34 | */ 35 | function isPauser(address pauser) public view returns (bool) { 36 | return pauser == _pauser; 37 | } 38 | 39 | /** 40 | * @dev Throws if called by any account other than the pauser. 41 | */ 42 | modifier onlyPauser() { 43 | require(isPauser(msg.sender), "Only pauser is allowed to perform this operation"); 44 | _; 45 | } 46 | 47 | /** 48 | * @dev Allows the current pauser to transfer control of the contract to a newPauser. 49 | * @param newPauser The address to transfer pauserShip to. 50 | */ 51 | function changePauser(address newPauser) public onlyPauser whenNotPaused { 52 | _changePauser(newPauser); 53 | } 54 | 55 | /** 56 | * @dev Transfers control of the contract to a newPauser. 57 | * @param newPauser The address to transfer ownership to. 58 | */ 59 | function _changePauser(address newPauser) internal { 60 | require(newPauser != address(0)); 61 | emit PauserChanged(_pauser, newPauser); 62 | _pauser = newPauser; 63 | } 64 | 65 | function renouncePauser() external virtual onlyPauser whenNotPaused { 66 | emit PauserChanged(_pauser, address(0)); 67 | _pauser = address(0); 68 | } 69 | 70 | function pause() public onlyPauser { 71 | _pause(); 72 | } 73 | 74 | function unpause() public onlyPauser { 75 | _unpause(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /contracts/hyphen/mock/MockAdaptor.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.0; 2 | import "../interfaces/ISwapAdaptor.sol"; 3 | import "../interfaces/ISwapRouter.sol"; 4 | import "../lib/TransferHelper.sol"; 5 | 6 | contract MockAdaptor is ISwapAdaptor { 7 | uint24 public constant POOL_FEE = 3000; 8 | address private constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; 9 | 10 | address public immutable NATIVE_WRAP_ADDRESS; 11 | ISwapRouter public immutable swapRouter; 12 | 13 | constructor(ISwapRouter _swapRouter, address nativeWrapAddress) { 14 | NATIVE_WRAP_ADDRESS = nativeWrapAddress; 15 | swapRouter = _swapRouter; // "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45" 16 | } 17 | 18 | function swap( 19 | address inputTokenAddress, 20 | uint256 amountInMaximum, 21 | address receiver, 22 | SwapRequest[] memory swapRequests 23 | ) external override returns (uint256 amountOut) { 24 | require(inputTokenAddress != NATIVE, "wrong function"); 25 | uint256 swapArrayLength = swapRequests.length; 26 | require(swapArrayLength <= 2, "too many swap requests"); 27 | require(swapArrayLength == 1 || swapRequests[1].operation == SwapOperation.ExactInput, "Invalid swap operation"); 28 | 29 | TransferHelper.safeTransferFrom(inputTokenAddress, msg.sender, address(this), amountInMaximum); 30 | TransferHelper.safeApprove(inputTokenAddress, address(swapRouter), amountInMaximum); 31 | 32 | uint256 amountIn; 33 | if(swapArrayLength == 1) { 34 | if (swapRequests[0].operation == SwapOperation.ExactOutput ){ 35 | amountIn = amountInMaximum - amountInMaximum/2; // half of the amount used up in swap 36 | 37 | if(amountIn < amountInMaximum) { 38 | TransferHelper.safeApprove(inputTokenAddress, address(swapRouter), 0); 39 | TransferHelper.safeTransfer(inputTokenAddress, receiver, amountInMaximum - amountIn); 40 | } 41 | } else { 42 | // do nothing, all amountIn is used up in swap 43 | amountOut = amountIn; 44 | } 45 | } else { 46 | amountIn = amountInMaximum - amountInMaximum/2; // half of the amount used up in swap 47 | if(amountIn < amountInMaximum){ 48 | amountOut = amountIn; 49 | } 50 | } 51 | } 52 | 53 | function swapNative( 54 | uint256 amountInMaximum, 55 | address receiver, 56 | SwapRequest[] memory swapRequests 57 | ) override external returns (uint256 amountOut) { 58 | } 59 | 60 | function unwrap(uint256 amountMinimum, address recipient) internal { 61 | 62 | } 63 | 64 | receive() external payable { 65 | require(msg.sender == NATIVE_WRAP_ADDRESS, 'Not WETH9'); 66 | } 67 | } -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.0; 2 | pragma abicoder v2; 3 | 4 | /** 5 | * @dev Interface of the ERC20 standard as defined in the EIP. 6 | */ 7 | interface IERC20 { 8 | /** 9 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 10 | * another (`to`). 11 | * 12 | * Note that `value` may be zero. 13 | */ 14 | event Transfer(address indexed from, address indexed to, uint256 value); 15 | 16 | /** 17 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 18 | * a call to {approve}. `value` is the new allowance. 19 | */ 20 | event Approval(address indexed owner, address indexed spender, uint256 value); 21 | 22 | /** 23 | * @dev Returns the amount of tokens in existence. 24 | */ 25 | function totalSupply() external view returns (uint256); 26 | 27 | /** 28 | * @dev Returns the amount of tokens owned by `account`. 29 | */ 30 | function balanceOf(address account) external view returns (uint256); 31 | 32 | /** 33 | * @dev Moves `amount` tokens from the caller's account to `to`. 34 | * 35 | * Returns a boolean value indicating whether the operation succeeded. 36 | * 37 | * Emits a {Transfer} event. 38 | */ 39 | function transfer(address to, uint256 amount) external returns (bool); 40 | 41 | /** 42 | * @dev Returns the remaining number of tokens that `spender` will be 43 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 44 | * zero by default. 45 | * 46 | * This value changes when {approve} or {transferFrom} are called. 47 | */ 48 | function allowance(address owner, address spender) external view returns (uint256); 49 | 50 | /** 51 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 52 | * 53 | * Returns a boolean value indicating whether the operation succeeded. 54 | * 55 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 56 | * that someone may use both the old and the new allowance by unfortunate 57 | * transaction ordering. One possible solution to mitigate this race 58 | * condition is to first reduce the spender's allowance to 0 and set the 59 | * desired value afterwards: 60 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 61 | * 62 | * Emits an {Approval} event. 63 | */ 64 | function approve(address spender, uint256 amount) external returns (bool); 65 | 66 | /** 67 | * @dev Moves `amount` tokens from `from` to `to` using the 68 | * allowance mechanism. `amount` is then deducted from the caller's 69 | * allowance. 70 | * 71 | * Returns a boolean value indicating whether the operation succeeded. 72 | * 73 | * Emits a {Transfer} event. 74 | */ 75 | function transferFrom( 76 | address from, 77 | address to, 78 | uint256 amount 79 | ) external returns (bool); 80 | } 81 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/ILPToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | import "../structures/LpTokenMetadata.sol"; 5 | 6 | interface ILPToken { 7 | function approve(address to, uint256 tokenId) external; 8 | 9 | function balanceOf(address _owner) external view returns (uint256); 10 | 11 | function exists(uint256 _tokenId) external view returns (bool); 12 | 13 | function getAllNftIdsByUser(address _owner) external view returns (uint256[] memory); 14 | 15 | function getApproved(uint256 tokenId) external view returns (address); 16 | 17 | function initialize( 18 | string memory _name, 19 | string memory _symbol, 20 | address _trustedForwarder 21 | ) external; 22 | 23 | function isApprovedForAll(address _owner, address operator) external view returns (bool); 24 | 25 | function isTrustedForwarder(address forwarder) external view returns (bool); 26 | 27 | function liquidityPoolAddress() external view returns (address); 28 | 29 | function mint(address _to) external returns (uint256); 30 | 31 | function name() external view returns (string memory); 32 | 33 | function owner() external view returns (address); 34 | 35 | function ownerOf(uint256 tokenId) external view returns (address); 36 | 37 | function paused() external view returns (bool); 38 | 39 | function renounceOwnership() external; 40 | 41 | function safeTransferFrom( 42 | address from, 43 | address to, 44 | uint256 tokenId 45 | ) external; 46 | 47 | function safeTransferFrom( 48 | address from, 49 | address to, 50 | uint256 tokenId, 51 | bytes memory _data 52 | ) external; 53 | 54 | function setApprovalForAll(address operator, bool approved) external; 55 | 56 | function setLiquidityPool(address _lpm) external; 57 | 58 | function setWhiteListPeriodManager(address _whiteListPeriodManager) external; 59 | 60 | function supportsInterface(bytes4 interfaceId) external view returns (bool); 61 | 62 | function symbol() external view returns (string memory); 63 | 64 | function tokenByIndex(uint256 index) external view returns (uint256); 65 | 66 | function tokenMetadata(uint256) 67 | external 68 | view 69 | returns ( 70 | address token, 71 | uint256 totalSuppliedLiquidity, 72 | uint256 totalShares 73 | ); 74 | 75 | function tokenOfOwnerByIndex(address _owner, uint256 index) external view returns (uint256); 76 | 77 | function tokenURI(uint256 tokenId) external view returns (string memory); 78 | 79 | function totalSupply() external view returns (uint256); 80 | 81 | function transferFrom( 82 | address from, 83 | address to, 84 | uint256 tokenId 85 | ) external; 86 | 87 | function transferOwnership(address newOwner) external; 88 | 89 | function updateTokenMetadata(uint256 _tokenId, LpTokenMetadata memory _lpTokenMetadata) external; 90 | 91 | function whiteListPeriodManager() external view returns (address); 92 | } 93 | -------------------------------------------------------------------------------- /scripts/token-manager/deploy-avalanche.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy, IDeployConfig } from "./helper"; 4 | 5 | (async () => { 6 | const config: IDeployConfig = { 7 | trustedForwarder: "0x64CD353384109423a966dCd3Aa30D884C9b2E057", 8 | bicoOwner: "0xd76b82204be75ab9610b04cf27c4f4a34291d5e6", 9 | pauser: "0xF1033Eb90b969666A82a7485803606fE7ef97f81", 10 | tokens: [ 11 | // USDC 12 | { 13 | tokenAddress: "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664", 14 | minCap: parseUnits("10", 6), 15 | maxCap: parseUnits("221813", 6), 16 | depositConfigs: [ 17 | { 18 | chainId: 1, 19 | minCap: parseUnits("100", 6), 20 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 21 | maxCap: parseUnits("200000", 6), 22 | }, 23 | { 24 | chainId: 137, 25 | minCap: parseUnits("10", 6), 26 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 27 | maxCap: parseUnits("200000", 6), 28 | }, 29 | { 30 | chainId: 56, 31 | minCap: parseUnits("10", 6), 32 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 33 | maxCap: parseUnits("200000", 6), 34 | }, 35 | ], 36 | equilibriumFee: ethers.utils.parseUnits("0.075", 8), 37 | maxFee: ethers.utils.parseUnits("0.5", 8), 38 | transferOverhead: 89491, // TODO 39 | excessStateTransferFeePer: parseUnits("0.045", 8), 40 | }, 41 | // WETH 42 | { 43 | tokenAddress: "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB", 44 | minCap: parseUnits("0.0039", 18), 45 | maxCap: parseUnits("143", 18), 46 | depositConfigs: [ 47 | { 48 | chainId: 1, 49 | minCap: parseUnits("0.02", 18), 50 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 51 | maxCap: parseUnits("100", 18), 52 | }, 53 | { 54 | chainId: 137, 55 | minCap: parseUnits("0.0039", 18), 56 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 57 | maxCap: parseUnits("100", 18), 58 | }, 59 | { 60 | chainId: 56, 61 | minCap: parseUnits("0.02", 18), 62 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 63 | maxCap: parseUnits("135", 18), 64 | }, 65 | ], 66 | equilibriumFee: ethers.utils.parseUnits("0.075", 8), 67 | maxFee: ethers.utils.parseUnits("0.5", 8), 68 | transferOverhead: 72945, // TODO 69 | excessStateTransferFeePer: parseUnits("0.045", 8) 70 | }, 71 | ], 72 | }; 73 | await deploy(config); 74 | })(); 75 | -------------------------------------------------------------------------------- /scripts/upgrades/upgrade-all/upgrade-all.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import axios from "axios"; 3 | import { 4 | upgradeLPToken, 5 | upgradeLiquidityFarming, 6 | upgradeLiquidityFarmingV2, 7 | upgradeLiquidityPool, 8 | upgradeLiquidityProviders, 9 | upgradeTokenManager, 10 | upgradeWhiteListPeriodManager, 11 | } from "../upgrade"; 12 | import { verifyImplementation } from "../../deploy/deploy-utils"; 13 | 14 | import type { IContractAddresses } from "../../types"; 15 | import { providers } from "ethers"; 16 | 17 | export const getProviderMapByChain = async (baseUrl: string): Promise> => { 18 | const response = (await axios.get(`${baseUrl}/api/v1/configuration/networks`)).data.message as any[]; 19 | return Object.fromEntries(response.map(({ chainId, rpc }) => [chainId, new ethers.providers.JsonRpcProvider(rpc)])); 20 | }; 21 | 22 | export const getContractAddresses = async (baseUrl: string): Promise> => { 23 | const response = (await axios.get(`${baseUrl}/api/v1/configuration/networks`)).data.message as any[]; 24 | return Object.fromEntries(response.map(({ chainId, contracts }) => [chainId, contracts.hyphen])); 25 | }; 26 | 27 | export const getContractAddressesByChain = async (baseUrl: string, chainId: number): Promise => { 28 | const response = (await axios.get(`${baseUrl}/api/v1/configuration/networks`)).data.message as any[]; 29 | const chain = response.filter((c) => c.chainId === chainId)[0]; 30 | return chain.contracts.hyphen; 31 | }; 32 | 33 | export const getSupportedTokenAddresses = async (baseUrl: string, chainId: number): Promise => { 34 | const response = (await axios.get(`${baseUrl}/api/v1/configuration/tokens`)).data.message as any[]; 35 | const supportedTokenAddresses = response 36 | .map((token) => token[chainId]) 37 | .filter((x) => x) 38 | .map((x) => x.address); 39 | return supportedTokenAddresses; 40 | }; 41 | 42 | export const upgradeAllContracts = async (addresses: IContractAddresses) => { 43 | await upgradeAndVerify(addresses.lpToken, upgradeLPToken); 44 | await upgradeAndVerify(addresses.liquidityPool, upgradeLiquidityPool); 45 | await upgradeAndVerify(addresses.liquidityProviders, upgradeLiquidityProviders); 46 | await upgradeAndVerify(addresses.tokenManager, upgradeTokenManager); 47 | await upgradeAndVerify(addresses.whitelistPeriodManager, upgradeWhiteListPeriodManager); 48 | if (addresses.liquidityFarmingV1) { 49 | await upgradeAndVerify(addresses.liquidityFarmingV1, upgradeLiquidityFarming); 50 | } 51 | if (addresses.liquidityFarmingV2) { 52 | await upgradeAndVerify(addresses.liquidityFarmingV2, upgradeLiquidityFarmingV2); 53 | } 54 | }; 55 | 56 | const upgradeAndVerify = async (proxy: string, upgrader: (address: string) => Promise) => { 57 | try { 58 | const [signer] = await ethers.getSigners(); 59 | console.log("Proxy: ", proxy, " Deployer: ", signer.address); 60 | console.log("Upgrading Proxy..."); 61 | await upgrader(proxy); 62 | await new Promise((resolve) => { 63 | setTimeout(resolve, 5000); 64 | }); 65 | await verifyImplementation(proxy); 66 | } catch (e) { 67 | console.error(`Error upgrading ${proxy}: ${e}`); 68 | } 69 | }; -------------------------------------------------------------------------------- /scripts/backend-api-script/mainnet/deposit-config-optimism.ts: -------------------------------------------------------------------------------- 1 | import { setConfig } from "../set-deposit-config"; 2 | import { getBackendConfig } from "../utils"; 3 | 4 | (async () => { 5 | let deposit_config = [ 6 | { 7 | chainId: 1, 8 | depositConfig: { 9 | toChainIds: [10,10,10], 10 | tokenAddresses: [ 11 | "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC 12 | "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH 13 | "0xf17e65822b568b3903685a7c9f496cf7656cc6c2" // BICO 14 | ], 15 | tokenConfigs: [ 16 | { 17 | min: "10000000", 18 | max: "200000000000", 19 | }, 20 | { 21 | min: "20000000000000000", 22 | max: "135000000000000000000", 23 | }, 24 | { 25 | min: "10000000000000000000", 26 | max: "500000000000000000000000", 27 | }, 28 | ], 29 | }, 30 | }, 31 | { 32 | chainId: 137, 33 | depositConfig: { 34 | toChainIds: [10,10,10], 35 | tokenAddresses: [ 36 | "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // USDC 37 | "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619", // ETH 38 | "0x91c89A94567980f0e9723b487b0beD586eE96aa7" // BICO 39 | ], 40 | tokenConfigs: [ 41 | { 42 | min: "10000000", 43 | max: "200000000000", 44 | }, 45 | { 46 | min: "3900000000000000", 47 | max: "135000000000000000000", 48 | }, 49 | { 50 | min: "10000000000000000000", 51 | max: "500000000000000000000000", 52 | }, 53 | ], 54 | }, 55 | }, 56 | { 57 | chainId: 43114, 58 | depositConfig: { 59 | toChainIds: [10,10], 60 | tokenAddresses: [ 61 | "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664", // USDC 62 | "0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab", // ETH 63 | ], 64 | tokenConfigs: [ 65 | { 66 | min: "10000000", 67 | max: "200000000000", 68 | }, 69 | { 70 | min: "3900000000000000", 71 | max: "135000000000000000000", 72 | } 73 | ], 74 | }, 75 | }, 76 | { 77 | chainId: 56, 78 | depositConfig: { 79 | toChainIds: [10], 80 | tokenAddresses: [ 81 | "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", // USDC 82 | "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", // ETH 83 | "0x06250a4962558F0F3E69FC07F4c67BB9c9eAc739" // BICO 84 | ], 85 | tokenConfigs: [ 86 | { 87 | min: "10000000000000000000", 88 | max: "200000000000000000000000", 89 | }, 90 | { 91 | min: "3900000000000000", 92 | max: "135000000000000000000", 93 | }, 94 | { 95 | min: "10000000000000000000", 96 | max: "500000000000000000000000", 97 | }, 98 | ], 99 | }, 100 | } 101 | ]; 102 | 103 | setConfig(deposit_config, getBackendConfig("staging")); 104 | })(); 105 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/ISwapRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-or-later 2 | pragma solidity 0.8.0; 3 | import "./IUniswapV3SwapCallback.sol"; 4 | 5 | /// @title Router token swapping functionality 6 | /// @notice Functions for swapping tokens via Uniswap V3 7 | interface ISwapRouter is IUniswapV3SwapCallback { 8 | struct ExactInputSingleParams { 9 | address tokenIn; 10 | address tokenOut; 11 | uint24 fee; 12 | address recipient; 13 | uint256 amountIn; 14 | uint256 amountOutMinimum; 15 | uint160 sqrtPriceLimitX96; 16 | } 17 | 18 | /// @notice Swaps `amountIn` of one token for as much as possible of another token 19 | /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance, 20 | /// and swap the entire amount, enabling contracts to send tokens before calling this function. 21 | /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata 22 | /// @return amountOut The amount of the received token 23 | function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); 24 | 25 | struct ExactInputParams { 26 | bytes path; 27 | address recipient; 28 | uint256 amountIn; 29 | uint256 amountOutMinimum; 30 | } 31 | 32 | /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path 33 | /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance, 34 | /// and swap the entire amount, enabling contracts to send tokens before calling this function. 35 | /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata 36 | /// @return amountOut The amount of the received token 37 | function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); 38 | 39 | struct ExactOutputSingleParams { 40 | address tokenIn; 41 | address tokenOut; 42 | uint24 fee; 43 | address recipient; 44 | uint256 amountOut; 45 | uint256 amountInMaximum; 46 | uint160 sqrtPriceLimitX96; 47 | } 48 | 49 | /// @notice Swaps as little as possible of one token for `amountOut` of another token 50 | /// that may remain in the router after the swap. 51 | /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata 52 | /// @return amountIn The amount of the input token 53 | function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); 54 | 55 | struct ExactOutputParams { 56 | bytes path; 57 | address recipient; 58 | uint256 amountOut; 59 | uint256 amountInMaximum; 60 | } 61 | 62 | /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) 63 | /// that may remain in the router after the swap. 64 | /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata 65 | /// @return amountIn The amount of the input token 66 | function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); 67 | } -------------------------------------------------------------------------------- /scripts/deploy/mainnet/deploy-avalanche.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy } from "../deploy-utils"; 4 | import type { IDeployConfig } from "../../types"; 5 | 6 | (async () => { 7 | const config: IDeployConfig = { 8 | trustedForwarder: "0x64CD353384109423a966dCd3Aa30D884C9b2E057", 9 | bicoOwner: "0xd76b82204be75ab9610b04cf27c4f4a34291d5e6", 10 | pauser: "0xF1033Eb90b969666A82a7485803606fE7ef97f81", 11 | tokens: [ 12 | // USDC 13 | { 14 | tokenAddress: "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664", 15 | minCap: parseUnits("10", 6), 16 | maxCap: parseUnits("221813", 6), 17 | depositConfigs: [ 18 | { 19 | chainId: 1, 20 | minCap: parseUnits("100", 6), 21 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 22 | maxCap: parseUnits("200000", 6), 23 | }, 24 | { 25 | chainId: 137, 26 | minCap: parseUnits("10", 6), 27 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 28 | maxCap: parseUnits("200000", 6), 29 | }, 30 | ], 31 | equilibriumFee: ethers.utils.parseUnits("0.1", 8), 32 | maxFee: ethers.utils.parseUnits("2.5", 8), 33 | transferOverhead: 89491, 34 | maxWalletLiquidityCap: parseUnits("10000", 6), 35 | maxLiquidityCap: parseUnits("503108", 6), 36 | svgHelper: await ethers.getContractFactory("AvalancheUSDC"), 37 | decimals: 6, 38 | rewardTokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 39 | rewardRatePerSecond: parseUnits("0.000034814379098636", 18), 40 | excessStateTransferFeePer: parseUnits("0.045", 8), 41 | }, 42 | // WETH 43 | { 44 | tokenAddress: "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB", 45 | minCap: parseUnits("0.0039", 18), 46 | maxCap: parseUnits("143", 18), 47 | depositConfigs: [ 48 | { 49 | chainId: 1, 50 | minCap: parseUnits("0.02", 18), 51 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 52 | maxCap: parseUnits("100", 18), 53 | }, 54 | { 55 | chainId: 137, 56 | minCap: parseUnits("0.0039", 18), 57 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 58 | maxCap: parseUnits("100", 18), 59 | }, 60 | ], 61 | equilibriumFee: ethers.utils.parseUnits("0.1", 8), 62 | maxFee: ethers.utils.parseUnits("2.5", 8), 63 | transferOverhead: 72945, 64 | maxWalletLiquidityCap: parseUnits("3.86", 18), 65 | maxLiquidityCap: parseUnits("171", 18), 66 | svgHelper: await ethers.getContractFactory("AvalancheETH"), 67 | decimals: 18, 68 | rewardTokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 69 | rewardRatePerSecond: parseUnits("0.000030666706752555", 18), 70 | excessStateTransferFeePer: parseUnits("0.045", 8), 71 | }, 72 | ], 73 | }; 74 | await deploy(config); 75 | })(); 76 | -------------------------------------------------------------------------------- /contracts/hyphen/lib/Fee.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | library Fee { 5 | uint256 private constant TOKEN_PRICE_BASE_DIVISOR = 10**28; 6 | uint256 private constant BASE_DIVISOR = 10000000000; // Basis Points * 100 for better accuracy 7 | 8 | function getTransferFee( 9 | uint256 _transferredAmount, 10 | uint256 _currentLiquidity, 11 | uint256 _suppliedLiquidity, 12 | uint256 _equilibriumFee, 13 | uint256 _maxFee, 14 | uint256 _excessStateTransferFee 15 | ) public pure returns (uint256) { 16 | uint256 resultingLiquidity = _currentLiquidity - _transferredAmount; 17 | 18 | // We return a constant value in excess state 19 | if (resultingLiquidity > _suppliedLiquidity) { 20 | return _excessStateTransferFee; 21 | } 22 | 23 | // Fee is represented in basis points * 10 for better accuracy 24 | uint256 numerator = _suppliedLiquidity * _suppliedLiquidity * _equilibriumFee * _maxFee; // F(max) * F(e) * L(e) ^ 2 25 | uint256 denominator = _equilibriumFee * 26 | _suppliedLiquidity * 27 | _suppliedLiquidity + 28 | (_maxFee - _equilibriumFee) * 29 | resultingLiquidity * 30 | resultingLiquidity; // F(e) * L(e) ^ 2 + (F(max) - F(e)) * L(r) ^ 2 31 | 32 | uint256 fee; 33 | if (denominator == 0) { 34 | fee = 0; 35 | } else { 36 | fee = numerator / denominator; 37 | } 38 | 39 | return fee; 40 | } 41 | 42 | function getFeeComponents( 43 | uint256 _transferredAmount, 44 | uint256 _currentLiquidity, 45 | uint256 _suppliedLiquidity, 46 | uint256 _equilibriumFee, 47 | uint256 _maxFee, 48 | uint256 _excessStateTransferFee 49 | ) 50 | external 51 | pure 52 | returns ( 53 | uint256, 54 | uint256, 55 | uint256 56 | ) 57 | { 58 | uint256 transferFeePerc = getTransferFee( 59 | _transferredAmount, 60 | _currentLiquidity, 61 | _suppliedLiquidity, 62 | _equilibriumFee, 63 | _maxFee, 64 | _excessStateTransferFee 65 | ); 66 | 67 | uint256 lpFee; 68 | uint256 incentivePoolFee; 69 | if (transferFeePerc > _equilibriumFee) { 70 | lpFee = (_transferredAmount * _equilibriumFee) / BASE_DIVISOR; 71 | unchecked { 72 | incentivePoolFee = (_transferredAmount * (transferFeePerc - _equilibriumFee)) / BASE_DIVISOR; 73 | } 74 | } else { 75 | lpFee = (_transferredAmount * transferFeePerc) / BASE_DIVISOR; 76 | } 77 | uint256 transferFee = (_transferredAmount * transferFeePerc) / BASE_DIVISOR; 78 | return (lpFee, incentivePoolFee, transferFee); 79 | } 80 | 81 | function calculateGasFee( 82 | uint256 nativeTokenPriceInTransferredToken, 83 | uint256 gasUsed, 84 | uint256 tokenGasBaseFee 85 | ) external view returns (uint256) { 86 | uint256 gasFee = (gasUsed * nativeTokenPriceInTransferredToken * tx.gasprice) / 87 | TOKEN_PRICE_BASE_DIVISOR + 88 | tokenGasBaseFee; 89 | 90 | return gasFee; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /scripts/deploy/testnet/deploy-fuji.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy } from "../deploy-utils"; 4 | import type { IDeployConfig } from "../../types"; 5 | 6 | (async () => { 7 | const config: IDeployConfig = { 8 | trustedForwarder: "0x6271Ca63D30507f2Dcbf99B52787032506D75BBF", 9 | bicoOwner: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 10 | pauser: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 11 | tokens: [ 12 | { 13 | tokenAddress: "0xB4E0F6FEF81BdFea0856bB846789985c9CFf7e85", 14 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 15 | maxCap: ethers.BigNumber.from(10).pow(18 + 4), 16 | depositConfigs: [ 17 | { 18 | chainId: 5, 19 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 20 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 21 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 22 | }, 23 | { 24 | chainId: 80001, 25 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 26 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 27 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 28 | }, 29 | ], 30 | equilibriumFee: 10000000, 31 | maxFee: 200000000, 32 | transferOverhead: 0, 33 | maxWalletLiquidityCap: ethers.BigNumber.from(10).pow(18 + 4), 34 | maxLiquidityCap: ethers.BigNumber.from(10).pow(18 + 5), 35 | svgHelper: await ethers.getContractFactory("AvalancheUSDT"), 36 | decimals: 18, 37 | rewardRatePerSecond: 100, 38 | rewardTokenAddress: "0xB4E0F6FEF81BdFea0856bB846789985c9CFf7e85", 39 | excessStateTransferFeePer: parseUnits("0.045", 8) 40 | }, 41 | { 42 | tokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", 43 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 44 | maxCap: ethers.BigNumber.from(10).pow(18 + 2), 45 | depositConfigs: [ 46 | { 47 | chainId: 80001, 48 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 49 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 50 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 51 | }, 52 | { 53 | chainId: 5, 54 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 55 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 56 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 57 | }, 58 | ], 59 | equilibriumFee: 10000000, 60 | maxFee: 200000000, 61 | transferOverhead: 0, 62 | maxWalletLiquidityCap: ethers.BigNumber.from(10).pow(18 + 4), 63 | maxLiquidityCap: ethers.BigNumber.from(10).pow(18 + 5), 64 | svgHelper: await ethers.getContractFactory("AvalancheETH"), 65 | decimals: 18, 66 | rewardRatePerSecond: 100, 67 | rewardTokenAddress: "0xB4E0F6FEF81BdFea0856bB846789985c9CFf7e85", 68 | excessStateTransferFeePer: parseUnits("0.045", 8) 69 | }, 70 | ], 71 | }; 72 | await deploy(config); 73 | })(); 74 | -------------------------------------------------------------------------------- /scripts/token-manager/deploy-mumbai.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { deploy, IDeployConfig } from "./helper"; 3 | import { parseUnits } from "ethers/lib/utils"; 4 | 5 | (async () => { 6 | const config: IDeployConfig = { 7 | trustedForwarder: "0x9399BB24DBB5C4b782C70c2969F58716Ebbd6a3b", 8 | bicoOwner: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 9 | pauser: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 10 | tokens: [ 11 | { 12 | tokenAddress: "0xeabc4b91d9375796aa4f69cc764a4ab509080a58", 13 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 14 | maxCap: ethers.BigNumber.from(10).pow(18 + 4), 15 | depositConfigs: [ 16 | { 17 | chainId: 43113, 18 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 19 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 20 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 21 | }, 22 | { 23 | chainId: 5, 24 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 25 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 26 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 27 | }, 28 | ], 29 | equilibriumFee: 10000000, 30 | maxFee: 200000000, 31 | transferOverhead: 0, 32 | excessStateTransferFeePer: parseUnits("0.045", 8), 33 | }, 34 | { 35 | tokenAddress: "0xa6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa", 36 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 37 | maxCap: ethers.BigNumber.from(10).pow(18 + 2), 38 | depositConfigs: [ 39 | { 40 | chainId: 43113, 41 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 42 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 43 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 44 | }, 45 | { 46 | chainId: 5, 47 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 48 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 49 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 50 | }, 51 | ], 52 | equilibriumFee: 10000000, 53 | maxFee: 200000000, 54 | transferOverhead: 0, 55 | excessStateTransferFeePer: parseUnits("0.045", 8), 56 | }, 57 | { 58 | tokenAddress: "0xdA5289fCAAF71d52a80A254da614a192b693e977", 59 | minCap: ethers.BigNumber.from(10).pow(6 + 2), 60 | maxCap: ethers.BigNumber.from(10).pow(6 + 4), 61 | depositConfigs: [ 62 | { 63 | chainId: 5, 64 | minCap: ethers.BigNumber.from(10).pow(6 + 2), 65 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 66 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(6 + 3)), 67 | }, 68 | ], 69 | equilibriumFee: 10000000, 70 | maxFee: 200000000, 71 | transferOverhead: 0, 72 | excessStateTransferFeePer: parseUnits("0.045", 8), 73 | }, 74 | ], 75 | }; 76 | await deploy(config); 77 | })(); 78 | -------------------------------------------------------------------------------- /scripts/token-manager/deploy-goerli.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy, IDeployConfig } from "./helper"; 4 | 5 | (async () => { 6 | const config: IDeployConfig = { 7 | trustedForwarder: "0xE041608922d06a4F26C0d4c27d8bCD01daf1f792", 8 | bicoOwner: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 9 | pauser: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 10 | tokens: [ 11 | { 12 | tokenAddress: "0x64ef393b6846114bad71e2cb2ccc3e10736b5716", 13 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 14 | maxCap: ethers.BigNumber.from(10).pow(18 + 4), 15 | depositConfigs: [ 16 | { 17 | chainId: 43113, 18 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 19 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 20 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 21 | }, 22 | { 23 | chainId: 80001, 24 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 25 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 26 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 27 | }, 28 | ], 29 | equilibriumFee: 10000000, 30 | maxFee: 200000000, 31 | transferOverhead: 0, 32 | excessStateTransferFeePer: parseUnits("0.045", 8), 33 | }, 34 | { 35 | tokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", 36 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 37 | maxCap: ethers.BigNumber.from(10).pow(18 + 2), 38 | depositConfigs: [ 39 | { 40 | chainId: 43113, 41 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 42 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 43 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 44 | }, 45 | { 46 | chainId: 80001, 47 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 48 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 49 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 50 | }, 51 | ], 52 | equilibriumFee: 10000000, 53 | maxFee: 200000000, 54 | transferOverhead: 0, 55 | excessStateTransferFeePer: parseUnits("0.045", 8), 56 | }, 57 | { 58 | tokenAddress: "0xb5B640E6414b6DeF4FC9B3C1EeF373925effeCcF", 59 | minCap: ethers.BigNumber.from(10).pow(6 + 2), 60 | maxCap: ethers.BigNumber.from(10).pow(6 + 4), 61 | depositConfigs: [ 62 | { 63 | chainId: 80001, 64 | minCap: ethers.BigNumber.from(10).pow(6 + 2), 65 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 66 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(6 + 3)), 67 | }, 68 | ], 69 | equilibriumFee: 10000000, 70 | maxFee: 200000000, 71 | transferOverhead: 0, 72 | excessStateTransferFeePer: parseUnits("0.045", 8), 73 | }, 74 | ], 75 | }; 76 | await deploy(config); 77 | })(); 78 | -------------------------------------------------------------------------------- /contracts/hyphen/interfaces/IHyphenLiquidityFarmingV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.0; 3 | 4 | interface IHyphenLiquidityFarmingV2 { 5 | function changePauser(address newPauser) external; 6 | 7 | function deposit(uint256 _nftId, address _to) external; 8 | 9 | function extractRewards( 10 | uint256 _nftId, 11 | address[] memory _rewardTokens, 12 | address _to 13 | ) external; 14 | 15 | function getNftIdsStaked(address _user) external view returns (uint256[] memory nftIds); 16 | 17 | function getRewardRatePerSecond(address _baseToken, address _rewardToken) external view returns (uint256); 18 | 19 | function getRewardTokens(address _baseToken) external view returns (address[] memory); 20 | 21 | function getStakedNftIndex(address _staker, uint256 _nftId) external view returns (uint256); 22 | 23 | function getUpdatedAccTokenPerShare(address _baseToken, address _rewardToken) external view returns (uint256); 24 | 25 | function initialize( 26 | address _trustedForwarder, 27 | address _pauser, 28 | address _liquidityProviders, 29 | address _lpToken 30 | ) external; 31 | 32 | function isPauser(address pauser) external view returns (bool); 33 | 34 | function isTrustedForwarder(address forwarder) external view returns (bool); 35 | 36 | function liquidityProviders() external view returns (address); 37 | 38 | function lpToken() external view returns (address); 39 | 40 | function nftIdsStaked(address, uint256) external view returns (uint256); 41 | 42 | function nftInfo(uint256) external view returns (address staker, bool isStaked); 43 | 44 | function onERC721Received( 45 | address, 46 | address, 47 | uint256, 48 | bytes memory 49 | ) external pure returns (bytes4); 50 | 51 | function owner() external view returns (address); 52 | 53 | function pause() external; 54 | 55 | function paused() external view returns (bool); 56 | 57 | function pendingToken(uint256 _nftId, address _rewardToken) external view returns (uint256); 58 | 59 | function poolInfo(address, address) external view returns (uint256 accTokenPerShare, uint256 lastRewardTime); 60 | 61 | function reclaimTokens( 62 | address _token, 63 | uint256 _amount, 64 | address _to 65 | ) external; 66 | 67 | function renounceOwnership() external; 68 | 69 | function renouncePauser() external; 70 | 71 | function rewardRateLog( 72 | address, 73 | address, 74 | uint256 75 | ) external view returns (uint256 rewardsPerSecond, uint256 timestamp); 76 | 77 | function setRewardPerSecond( 78 | address _baseToken, 79 | address _rewardToken, 80 | uint256 _rewardPerSecond 81 | ) external; 82 | 83 | function setTrustedForwarder(address _tf) external; 84 | 85 | function totalSharesStaked(address) external view returns (uint256); 86 | 87 | function transferOwnership(address newOwner) external; 88 | 89 | function unpause() external; 90 | 91 | function updateLiquidityProvider(address _liquidityProviders) external; 92 | 93 | function withdraw(uint256 _nftId, address _to) external; 94 | 95 | function withdrawAtIndex( 96 | uint256 _nftId, 97 | address _to, 98 | uint256 _index 99 | ) external; 100 | } 101 | -------------------------------------------------------------------------------- /scripts/backend-api-script/testnet/deposit-config-arbiTestnet.ts: -------------------------------------------------------------------------------- 1 | import { setConfig } from "../set-deposit-config"; 2 | import { getBackendConfig } from "../utils"; 3 | 4 | (async () => { 5 | let deposit_config = [ 6 | { 7 | chainId: 5, 8 | depositConfig: { 9 | toChainIds: [421611,421611,421611], 10 | tokenAddresses: [ 11 | "0xb5B640E6414b6DeF4FC9B3C1EeF373925effeCcF", // USDC 12 | "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", // ETH 13 | "0xDdc47b0cA071682e8dc373391aCA18dA0Fe28699" // BICO 14 | ], 15 | tokenConfigs: [ 16 | { 17 | min: "100000000", 18 | max: "52000000000", 19 | }, 20 | { 21 | min: "20000000000000000", 22 | max: "135000000000000000000", 23 | }, 24 | { 25 | min: "10000000000000000000", 26 | max: "500000000000000000000000", 27 | }, 28 | ], 29 | }, 30 | }, 31 | { 32 | chainId: 80001, 33 | depositConfig: { 34 | toChainIds: [421611,421611,421611], 35 | tokenAddresses: [ 36 | "0xdA5289fCAAF71d52a80A254da614a192b693e977", // USDC 37 | "0xa6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa", // ETH 38 | "0xac42d8319ce458b22a72b45f58c0dcfeee824691" // BICO 39 | ], 40 | tokenConfigs: [ 41 | { 42 | min: "100000000", 43 | max: "52000000000", 44 | }, 45 | { 46 | min: "3900000000000000", 47 | max: "135000000000000000000", 48 | }, 49 | { 50 | min: "10000000000000000000", 51 | max: "500000000000000000000000", 52 | }, 53 | ], 54 | }, 55 | }, 56 | { 57 | chainId: 69, 58 | depositConfig: { 59 | toChainIds: [421611,421611,421611], 60 | tokenAddresses: [ 61 | "0x4995E4dd58Fa9eF9D80F3111777fdd4bC3300a7C", // USDC 62 | "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH 63 | "0x439725d33Fe46f1C167F6116aeEd7d910E482D2E", // Bico 64 | ], 65 | tokenConfigs: [ 66 | { 67 | min: "100000000", 68 | max: "52000000000", 69 | }, 70 | { 71 | min: "3900000000000000", 72 | max: "135000000000000000000", 73 | }, 74 | { 75 | min: "10000000000000000000", 76 | max: "500000000000000000000000", 77 | } 78 | ], 79 | }, 80 | }, 81 | { 82 | chainId: 43113, 83 | depositConfig: { 84 | toChainIds: [421611], 85 | tokenAddresses: [ 86 | "0x7fcdc2c1ef3e4a0bcc8155a558bb20a7218f2b05", // ETH 87 | ], 88 | tokenConfigs: [ 89 | { 90 | min: "3900000000000000", 91 | max: "135000000000000000000", 92 | } 93 | ], 94 | }, 95 | }, 96 | { 97 | chainId: 97, 98 | depositConfig: { 99 | toChainIds: [421611], 100 | tokenAddresses: [ 101 | "0x756289346D2b3C867966899c6D0467EdEb4Da3C4", // Bico 102 | ], 103 | tokenConfigs: [ 104 | { 105 | min: "10000000000000000000", 106 | max: "500000000000000000000000", 107 | }, 108 | ], 109 | }, 110 | } 111 | ]; 112 | 113 | setConfig(deposit_config, getBackendConfig("staging")); 114 | })(); 115 | -------------------------------------------------------------------------------- /scripts/prod-replica-helpers/abi/ProxyAdmin.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | anonymous: false, 4 | inputs: [ 5 | { 6 | indexed: true, 7 | internalType: "address", 8 | name: "previousOwner", 9 | type: "address", 10 | }, 11 | { 12 | indexed: true, 13 | internalType: "address", 14 | name: "newOwner", 15 | type: "address", 16 | }, 17 | ], 18 | name: "OwnershipTransferred", 19 | type: "event", 20 | }, 21 | { 22 | inputs: [ 23 | { 24 | internalType: "contract TransparentUpgradeableProxy", 25 | name: "proxy", 26 | type: "address", 27 | }, 28 | { 29 | internalType: "address", 30 | name: "newAdmin", 31 | type: "address", 32 | }, 33 | ], 34 | name: "changeProxyAdmin", 35 | outputs: [], 36 | stateMutability: "nonpayable", 37 | type: "function", 38 | }, 39 | { 40 | inputs: [ 41 | { 42 | internalType: "contract TransparentUpgradeableProxy", 43 | name: "proxy", 44 | type: "address", 45 | }, 46 | ], 47 | name: "getProxyAdmin", 48 | outputs: [ 49 | { 50 | internalType: "address", 51 | name: "", 52 | type: "address", 53 | }, 54 | ], 55 | stateMutability: "view", 56 | type: "function", 57 | }, 58 | { 59 | inputs: [ 60 | { 61 | internalType: "contract TransparentUpgradeableProxy", 62 | name: "proxy", 63 | type: "address", 64 | }, 65 | ], 66 | name: "getProxyImplementation", 67 | outputs: [ 68 | { 69 | internalType: "address", 70 | name: "", 71 | type: "address", 72 | }, 73 | ], 74 | stateMutability: "view", 75 | type: "function", 76 | }, 77 | { 78 | inputs: [], 79 | name: "owner", 80 | outputs: [ 81 | { 82 | internalType: "address", 83 | name: "", 84 | type: "address", 85 | }, 86 | ], 87 | stateMutability: "view", 88 | type: "function", 89 | }, 90 | { 91 | inputs: [], 92 | name: "renounceOwnership", 93 | outputs: [], 94 | stateMutability: "nonpayable", 95 | type: "function", 96 | }, 97 | { 98 | inputs: [ 99 | { 100 | internalType: "address", 101 | name: "newOwner", 102 | type: "address", 103 | }, 104 | ], 105 | name: "transferOwnership", 106 | outputs: [], 107 | stateMutability: "nonpayable", 108 | type: "function", 109 | }, 110 | { 111 | inputs: [ 112 | { 113 | internalType: "contract TransparentUpgradeableProxy", 114 | name: "proxy", 115 | type: "address", 116 | }, 117 | { 118 | internalType: "address", 119 | name: "implementation", 120 | type: "address", 121 | }, 122 | ], 123 | name: "upgrade", 124 | outputs: [], 125 | stateMutability: "nonpayable", 126 | type: "function", 127 | }, 128 | { 129 | inputs: [ 130 | { 131 | internalType: "contract TransparentUpgradeableProxy", 132 | name: "proxy", 133 | type: "address", 134 | }, 135 | { 136 | internalType: "address", 137 | name: "implementation", 138 | type: "address", 139 | }, 140 | { 141 | internalType: "bytes", 142 | name: "data", 143 | type: "bytes", 144 | }, 145 | ], 146 | name: "upgradeAndCall", 147 | outputs: [], 148 | stateMutability: "payable", 149 | type: "function", 150 | }, 151 | ]; 152 | -------------------------------------------------------------------------------- /scripts/backend-api-script/mainnet/deposit-config-fantom.ts: -------------------------------------------------------------------------------- 1 | import { setConfig } from "../set-deposit-config"; 2 | import { getBackendConfig } from "../utils"; 3 | 4 | (async () => { 5 | let deposit_config = [ 6 | { 7 | chainId: 1, 8 | depositConfig: { 9 | toChainIds: [250,250], 10 | tokenAddresses: [ 11 | "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC 12 | "0xf17e65822b568b3903685a7c9f496cf7656cc6c2" // BICO 13 | ], 14 | tokenConfigs: [ 15 | { 16 | min: "10000000", 17 | max: "200000000000", 18 | }, 19 | { 20 | min: "10000000000000000000", 21 | max: "500000000000000000000000", 22 | }, 23 | ], 24 | }, 25 | }, 26 | { 27 | chainId: 137, 28 | depositConfig: { 29 | toChainIds: [250,250], 30 | tokenAddresses: [ 31 | "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // USDC 32 | "0x91c89A94567980f0e9723b487b0beD586eE96aa7" // BICO 33 | ], 34 | tokenConfigs: [ 35 | { 36 | min: "10000000", 37 | max: "200000000000", 38 | }, 39 | { 40 | min: "10000000000000000000", 41 | max: "500000000000000000000000", 42 | }, 43 | ], 44 | }, 45 | }, 46 | { 47 | chainId: 43114, 48 | depositConfig: { 49 | toChainIds: [250], 50 | tokenAddresses: [ 51 | "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664", // USDC 52 | ], 53 | tokenConfigs: [ 54 | { 55 | min: "10000000", 56 | max: "200000000000", 57 | }, 58 | ], 59 | }, 60 | }, 61 | { 62 | chainId: 56, 63 | depositConfig: { 64 | toChainIds: [250,250], 65 | tokenAddresses: [ 66 | "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", // USDC 67 | "0x06250a4962558F0F3E69FC07F4c67BB9c9eAc739" // BICO 68 | ], 69 | tokenConfigs: [ 70 | { 71 | min: "10000000000000000000", 72 | max: "200000000000000000000000", 73 | }, 74 | { 75 | min: "10000000000000000000", 76 | max: "500000000000000000000000", 77 | }, 78 | ], 79 | }, 80 | }, 81 | { 82 | chainId: 10, 83 | depositConfig: { 84 | toChainIds: [250,250], 85 | tokenAddresses: [ 86 | "0x7f5c764cbc14f9669b88837ca1490cca17c31607", // USDC 87 | "0xd6909e9e702024eb93312b989ee46794c0fb1c9d" // BICO 88 | ], 89 | tokenConfigs: [ 90 | { 91 | min: "10000000", 92 | max: "200000000000", 93 | }, 94 | { 95 | min: "10000000000000000000", 96 | max: "500000000000000000000000", 97 | }, 98 | ], 99 | }, 100 | }, 101 | { 102 | chainId: 42161, 103 | depositConfig: { 104 | toChainIds: [250,250], 105 | tokenAddresses: [ 106 | "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8", // USDC 107 | "0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d" // BICO 108 | ], 109 | tokenConfigs: [ 110 | { 111 | min: "10000000", 112 | max: "200000000000", 113 | }, 114 | { 115 | min: "10000000000000000000", 116 | max: "500000000000000000000000", 117 | }, 118 | ], 119 | }, 120 | } 121 | ]; 122 | 123 | setConfig(deposit_config, getBackendConfig("prod")); 124 | })(); 125 | -------------------------------------------------------------------------------- /scripts/deploy/testnet/deploy-bsc-testnet.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy } from "../deploy-utils"; 4 | import type { IDeployConfig } from "../../types"; 5 | 6 | (async () => { 7 | const config: IDeployConfig = { 8 | trustedForwarder: "0x61456BF1715C1415730076BB79ae118E806E74d2", 9 | bicoOwner: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 10 | pauser: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 11 | tokens: [ 12 | // USDT 13 | { 14 | tokenAddress: "0xbf22b04E250A5921ab4dC0d4ceD6E391459e92D4", 15 | minCap: parseUnits("100", 18), 16 | maxCap: parseUnits("58160",18), 17 | depositConfigs: [ 18 | { 19 | chainId: 5, 20 | minCap: parseUnits("10", 18), 21 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 22 | maxCap: parseUnits("50000", 18), 23 | }, 24 | { 25 | chainId: 80001, 26 | minCap: parseUnits("10",18), 27 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 28 | maxCap: parseUnits("50000", 18), 29 | }, 30 | { 31 | chainId: 43113, 32 | minCap: parseUnits("10", 18), 33 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 34 | maxCap: parseUnits("50000", 18), 35 | }, 36 | ], 37 | equilibriumFee: parseUnits("0.1", 8), 38 | maxFee: parseUnits("2.5", 8), 39 | transferOverhead: 82491, 40 | maxWalletLiquidityCap: parseUnits("10000", 18), 41 | maxLiquidityCap: parseUnits("578829", 18), 42 | svgHelper: await ethers.getContractFactory("BSCUSDT"), 43 | decimals: 18, 44 | rewardTokenAddress: "0x756289346D2b3C867966899c6D0467EdEb4Da3C4", 45 | rewardRatePerSecond: parseUnits("0.003662", 18), 46 | excessStateTransferFeePer: parseUnits("0.045", 8), 47 | }, 48 | // BICO 49 | { 50 | tokenAddress: "0x756289346D2b3C867966899c6D0467EdEb4Da3C4", 51 | minCap: parseUnits("50", 18), 52 | maxCap: parseUnits("123220", 18), 53 | depositConfigs: [ 54 | { 55 | chainId: 5, 56 | minCap: parseUnits("10", 18), 57 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 58 | maxCap: parseUnits("100000", 18), 59 | }, 60 | { 61 | chainId: 80001, 62 | minCap: parseUnits("10", 18), 63 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 64 | maxCap: parseUnits("100000", 18), 65 | }, 66 | { 67 | chainId: 43113, 68 | minCap: parseUnits("10", 18), 69 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 70 | maxCap: parseUnits("100000", 18), 71 | }, 72 | ], 73 | equilibriumFee: ethers.utils.parseUnits("0.1", 8), 74 | maxFee: ethers.utils.parseUnits("2.5", 8), 75 | transferOverhead: 85949, 76 | maxWalletLiquidityCap: parseUnits("8474.57", 18), 77 | maxLiquidityCap: parseUnits("610350", 18), 78 | svgHelper: await ethers.getContractFactory("BSCBICO"), 79 | decimals: 18, 80 | rewardTokenAddress: "0x756289346D2b3C867966899c6D0467EdEb4Da3C4", 81 | rewardRatePerSecond: parseUnits("0", 18), 82 | excessStateTransferFeePer: parseUnits("0.045", 8), 83 | }, 84 | ], 85 | }; 86 | await deploy(config); 87 | })(); 88 | -------------------------------------------------------------------------------- /scripts/backend-api-script/mainnet/deposit-config-arbitrum.ts: -------------------------------------------------------------------------------- 1 | import { setConfig } from "../set-deposit-config"; 2 | import { getBackendConfig } from "../utils"; 3 | 4 | (async () => { 5 | let deposit_config = [ 6 | { 7 | chainId: 1, 8 | depositConfig: { 9 | toChainIds: [42161,42161,42161], 10 | tokenAddresses: [ 11 | "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC 12 | "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH 13 | "0xf17e65822b568b3903685a7c9f496cf7656cc6c2" // BICO 14 | ], 15 | tokenConfigs: [ 16 | { 17 | min: "10000000", 18 | max: "200000000000", 19 | }, 20 | { 21 | min: "20000000000000000", 22 | max: "135000000000000000000", 23 | }, 24 | { 25 | min: "10000000000000000000", 26 | max: "500000000000000000000000", 27 | }, 28 | ], 29 | }, 30 | }, 31 | { 32 | chainId: 137, 33 | depositConfig: { 34 | toChainIds: [42161,42161,42161], 35 | tokenAddresses: [ 36 | "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // USDC 37 | "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619", // ETH 38 | "0x91c89A94567980f0e9723b487b0beD586eE96aa7" // BICO 39 | ], 40 | tokenConfigs: [ 41 | { 42 | min: "10000000", 43 | max: "200000000000", 44 | }, 45 | { 46 | min: "20000000000000000", 47 | max: "135000000000000000000", 48 | }, 49 | { 50 | min: "10000000000000000000", 51 | max: "500000000000000000000000", 52 | }, 53 | ], 54 | }, 55 | }, 56 | { 57 | chainId: 43114, 58 | depositConfig: { 59 | toChainIds: [42161,42161], 60 | tokenAddresses: [ 61 | "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664", // USDC 62 | "0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab", // ETH 63 | ], 64 | tokenConfigs: [ 65 | { 66 | min: "10000000", 67 | max: "200000000000", 68 | }, 69 | { 70 | min: "20000000000000000", 71 | max: "135000000000000000000", 72 | } 73 | ], 74 | }, 75 | }, 76 | { 77 | chainId: 56, 78 | depositConfig: { 79 | toChainIds: [42161,42161,42161], 80 | tokenAddresses: [ 81 | "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", // USDC 82 | "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", // ETH 83 | "0x06250a4962558F0F3E69FC07F4c67BB9c9eAc739" // BICO 84 | ], 85 | tokenConfigs: [ 86 | { 87 | min: "10000000000000000000", 88 | max: "200000000000000000000000", 89 | }, 90 | { 91 | min: "20000000000000000", 92 | max: "135000000000000000000", 93 | }, 94 | { 95 | min: "10000000000000000000", 96 | max: "500000000000000000000000", 97 | }, 98 | ], 99 | }, 100 | }, 101 | { 102 | chainId: 10, 103 | depositConfig: { 104 | toChainIds: [42161,42161,42161], 105 | tokenAddresses: [ 106 | "0x7f5c764cbc14f9669b88837ca1490cca17c31607", // USDC 107 | "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", // ETH 108 | "0xd6909e9e702024eb93312b989ee46794c0fb1c9d" // BICO 109 | ], 110 | tokenConfigs: [ 111 | { 112 | min: "10000000000000000000", 113 | max: "200000000000000000000000", 114 | }, 115 | { 116 | min: "20000000000000000", 117 | max: "135000000000000000000", 118 | }, 119 | { 120 | min: "10000000000000000000", 121 | max: "500000000000000000000000", 122 | }, 123 | ], 124 | }, 125 | } 126 | ]; 127 | 128 | setConfig(deposit_config, getBackendConfig("prod")); 129 | })(); 130 | -------------------------------------------------------------------------------- /scripts/backend-api-script/ethereum_config.ts: -------------------------------------------------------------------------------- 1 | import { setConfig } from "./set-deposit-config"; 2 | import { getBackendConfig } from "./utils"; 3 | 4 | (async () => { 5 | let deposit_config = [ 6 | { 7 | chainId: 5, 8 | depositConfig: { 9 | toChainIds: [4002, 4002, 4002], 10 | tokenAddresses: [ 11 | "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 12 | "0xb5B640E6414b6DeF4FC9B3C1EeF373925effeCcF", 13 | "0xDdc47b0cA071682e8dc373391aCA18dA0Fe28699", 14 | ], 15 | tokenConfigs: [ 16 | { 17 | min: "10000000000000000", 18 | max: "10000000000000000000000", 19 | }, 20 | { 21 | min: "1000000", 22 | max: "10000000000", 23 | }, 24 | { 25 | min: "10000000000000000000", 26 | max: "10000000000000000000000", 27 | }, 28 | ], 29 | }, 30 | }, 31 | { 32 | chainId: 80001, 33 | depositConfig: { 34 | toChainIds: [4002, 4002, 4002], 35 | tokenAddresses: [ 36 | "0xdA5289fCAAF71d52a80A254da614a192b693e977", 37 | "0xa6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa", 38 | "0xac42d8319ce458b22a72b45f58c0dcfeee824691", 39 | ], 40 | tokenConfigs: [ 41 | { 42 | min: "100000000", 43 | max: "1000000000000", 44 | }, 45 | { 46 | min: "100000000000000000000", 47 | max: "10000000000000000000000", 48 | }, 49 | { 50 | min: "100000000000000000000", 51 | max: "10000000000000000000000", 52 | }, 53 | ], 54 | }, 55 | }, 56 | { 57 | chainId: 43113, 58 | depositConfig: { 59 | toChainIds: [4002], 60 | tokenAddresses: ["0x7fcdc2c1ef3e4a0bcc8155a558bb20a7218f2b05"], 61 | tokenConfigs: [ 62 | { 63 | min: "100000000000000000000", 64 | max: "10000000000000000000000", 65 | }, 66 | ], 67 | }, 68 | }, 69 | { 70 | chainId: 97, 71 | depositConfig: { 72 | toChainIds: [4002], 73 | tokenAddresses: ["0x756289346D2b3C867966899c6D0467EdEb4Da3C4"], 74 | tokenConfigs: [ 75 | { 76 | min: "100000000000000000000", 77 | max: "10000000000000000000000", 78 | }, 79 | ], 80 | }, 81 | }, 82 | { 83 | chainId: 69, 84 | depositConfig: { 85 | toChainIds: [4002, 4002, 4002], 86 | tokenAddresses: [ 87 | "0x439725d33Fe46f1C167F6116aeEd7d910E482D2E", 88 | "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 89 | "0x4995E4dd58Fa9eF9D80F3111777fdd4bC3300a7C", 90 | ], 91 | tokenConfigs: [ 92 | { 93 | min: "100000000000000000000", 94 | max: "10000000000000000000000", 95 | }, 96 | { 97 | min: "10000000000000000", 98 | max: "10000000000000000000000", 99 | }, 100 | { 101 | min: "100000000", 102 | max: "1000000000000", 103 | }, 104 | ], 105 | }, 106 | }, 107 | { 108 | chainId: 421611, 109 | depositConfig: { 110 | toChainIds: [4002, 4002, 4002], 111 | tokenAddresses: [ 112 | "0xd8e71dedbd081e9b702c69a6afca61c07076a148", 113 | "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 114 | "0x31b02918d86afdb502e48958a8190e98952a9c0c", 115 | ], 116 | tokenConfigs: [ 117 | { 118 | min: "100000000000000000000", 119 | max: "10000000000000000000000", 120 | }, 121 | { 122 | min: "10000000000000000", 123 | max: "10000000000000000000000", 124 | }, 125 | { 126 | min: "100000000", 127 | max: "1000000000000", 128 | }, 129 | ], 130 | }, 131 | }, 132 | ]; 133 | 134 | setConfig(deposit_config, getBackendConfig("integration")); 135 | })(); 136 | -------------------------------------------------------------------------------- /scripts/deploy/mainnet/deploy-fantom.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy } from "../deploy-utils"; 4 | import type { IDeployConfig } from "../../types"; 5 | 6 | (async () => { 7 | const config: IDeployConfig = { 8 | trustedForwarder: "0x64CD353384109423a966dCd3Aa30D884C9b2E057", 9 | bicoOwner: "0xd76b82204be75ab9610b04cf27c4f4a34291d5e6", 10 | pauser: "0x129443cA2a9Dec2020808a2868b38dDA457eaCC7", 11 | tokens: [ 12 | // USDC 13 | { 14 | tokenAddress: "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75", // please cross-check this address 15 | minCap: parseUnits("10", 6), 16 | maxCap: parseUnits("221813", 6), 17 | depositConfigs: [ 18 | { 19 | chainId: 1, // Ethereum 20 | minCap: parseUnits("100", 6), 21 | maxCap: parseUnits("200000", 6), 22 | }, 23 | { 24 | chainId: 137, // Polygon 25 | minCap: parseUnits("10", 6), 26 | maxCap: parseUnits("200000", 6), 27 | }, 28 | { 29 | chainId: 43114, // Avalanche 30 | minCap: parseUnits("10", 6), 31 | maxCap: parseUnits("200000", 6), 32 | }, 33 | { 34 | chainId: 56, // Binance chain 35 | minCap: parseUnits("10", 6), 36 | maxCap: parseUnits("200000", 6), 37 | }, 38 | { 39 | chainId: 10, // Optimism 40 | minCap: parseUnits("10", 6), 41 | maxCap: parseUnits("200000", 6), 42 | }, 43 | { 44 | chainId: 42161, // arbitrum 45 | minCap: parseUnits("10", 6), 46 | maxCap: parseUnits("200000", 6), 47 | }, 48 | ], 49 | equilibriumFee: parseUnits("0.075", 8), 50 | maxFee: parseUnits("0.5", 8), 51 | transferOverhead: 89491, 52 | maxWalletLiquidityCap: parseUnits("0", 6), // not used 53 | maxLiquidityCap: parseUnits("500000", 6), 54 | svgHelper: await ethers.getContractFactory("FantomUSDC"), 55 | decimals: 6, 56 | rewardTokenAddress: "0x524cabe5b2f66cbd6f6b08def086f18f8dde033a", 57 | rewardRatePerSecond: parseUnits("0.001801", 18), 58 | excessStateTransferFeePer: parseUnits("0.045", 8), 59 | }, 60 | // BICO 61 | { 62 | tokenAddress: "0x524cabe5b2f66cbd6f6b08def086f18f8dde033a", 63 | minCap: parseUnits("10", 18), 64 | maxCap: parseUnits("510000", 18), 65 | depositConfigs: [ 66 | { 67 | chainId: 1, // Ethereum 68 | minCap: parseUnits("50", 18), 69 | maxCap: parseUnits("500000", 18), 70 | }, 71 | { 72 | chainId: 137, // Polygon 73 | minCap: parseUnits("10", 18), 74 | maxCap: parseUnits("300000", 18), 75 | }, 76 | { 77 | chainId: 56, // Binance chain 78 | minCap: parseUnits("10", 18), 79 | maxCap: parseUnits("500000", 18), 80 | }, 81 | { 82 | chainId: 10, // Optimism 83 | minCap: parseUnits("10", 18), 84 | maxCap: parseUnits("500000", 18), 85 | }, 86 | { 87 | chainId: 42161, // arbitrum 88 | minCap: parseUnits("10", 18), 89 | maxCap: parseUnits("500000", 18), 90 | }, 91 | ], 92 | equilibriumFee: parseUnits("0.075", 8), 93 | maxFee: parseUnits("0.5", 8), 94 | transferOverhead: 85949, 95 | maxWalletLiquidityCap: parseUnits("0", 18), // not used 96 | maxLiquidityCap: parseUnits("750000", 18), 97 | svgHelper: await ethers.getContractFactory("FantomBICO"), 98 | decimals: 18, 99 | rewardTokenAddress: "0x524cabe5b2f66cbd6f6b08def086f18f8dde033a", // please cross-check this address 100 | rewardRatePerSecond: parseUnits("0", 18), 101 | excessStateTransferFeePer: parseUnits("0.045", 8), 102 | }, 103 | ], 104 | }; 105 | await deploy(config); 106 | })(); 107 | -------------------------------------------------------------------------------- /scripts/deploy/testnet/deploy-mumbai.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import type { IDeployConfig } from "../../types"; 4 | 5 | (async () => { 6 | const config: IDeployConfig = { 7 | trustedForwarder: "0x9399BB24DBB5C4b782C70c2969F58716Ebbd6a3b", 8 | bicoOwner: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 9 | pauser: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 10 | tokens: [ 11 | { 12 | tokenAddress: "0xeabc4b91d9375796aa4f69cc764a4ab509080a58", 13 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 14 | maxCap: ethers.BigNumber.from(10).pow(18 + 4), 15 | depositConfigs: [ 16 | { 17 | chainId: 43113, 18 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 19 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 20 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 21 | }, 22 | { 23 | chainId: 5, 24 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 25 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 26 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 27 | }, 28 | ], 29 | equilibriumFee: 10000000, 30 | maxFee: 200000000, 31 | transferOverhead: 0, 32 | maxWalletLiquidityCap: ethers.BigNumber.from(10).pow(18 + 4), 33 | maxLiquidityCap: ethers.BigNumber.from(10).pow(18 + 5), 34 | svgHelper: await ethers.getContractFactory("PolygonUSDT"), 35 | decimals: 18, 36 | rewardRatePerSecond: 100, 37 | rewardTokenAddress: "0xeabc4b91d9375796aa4f69cc764a4ab509080a58", 38 | excessStateTransferFeePer: parseUnits("0.045", 8), 39 | }, 40 | { 41 | tokenAddress: "0xa6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa", 42 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 43 | maxCap: ethers.BigNumber.from(10).pow(18 + 2), 44 | depositConfigs: [ 45 | { 46 | chainId: 43113, 47 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 48 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 49 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 50 | }, 51 | { 52 | chainId: 5, 53 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 54 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 55 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 56 | }, 57 | ], 58 | equilibriumFee: 10000000, 59 | maxFee: 200000000, 60 | transferOverhead: 0, 61 | maxWalletLiquidityCap: ethers.BigNumber.from(10).pow(18 + 4), 62 | maxLiquidityCap: ethers.BigNumber.from(10).pow(18 + 5), 63 | svgHelper: await ethers.getContractFactory("PolygonETH"), 64 | decimals: 18, 65 | rewardRatePerSecond: 100, 66 | rewardTokenAddress: "0xeabc4b91d9375796aa4f69cc764a4ab509080a58", 67 | excessStateTransferFeePer: parseUnits("0.045", 8), 68 | }, 69 | { 70 | tokenAddress: "0xdA5289fCAAF71d52a80A254da614a192b693e977", 71 | minCap: ethers.BigNumber.from(10).pow(6 + 2), 72 | maxCap: ethers.BigNumber.from(10).pow(6 + 4), 73 | depositConfigs: [ 74 | { 75 | chainId: 5, 76 | minCap: ethers.BigNumber.from(10).pow(6 + 2), 77 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 78 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(6 + 3)), 79 | }, 80 | ], 81 | equilibriumFee: 10000000, 82 | maxFee: 200000000, 83 | transferOverhead: 0, 84 | maxWalletLiquidityCap: ethers.BigNumber.from(10).pow(6 + 4), 85 | maxLiquidityCap: ethers.BigNumber.from(10).pow(6 + 5), 86 | svgHelper: await ethers.getContractFactory("PolygonUSDC"), 87 | decimals: 6, 88 | rewardRatePerSecond: 100, 89 | rewardTokenAddress: "0xeabc4b91d9375796aa4f69cc764a4ab509080a58", 90 | excessStateTransferFeePer: parseUnits("0.045", 8), 91 | }, 92 | ], 93 | }; 94 | await deploy(config); 95 | })(); 96 | -------------------------------------------------------------------------------- /scripts/deploy/testnet/deploy-goerli.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy } from "../deploy-utils"; 4 | import type { IDeployConfig } from "../../types"; 5 | 6 | (async () => { 7 | const config: IDeployConfig = { 8 | trustedForwarder: "0xE041608922d06a4F26C0d4c27d8bCD01daf1f792", 9 | bicoOwner: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 10 | pauser: "0x46b65ae065341D034fEA45D76c6fA936EAfBfdeb", 11 | tokens: [ 12 | { 13 | tokenAddress: "0x64ef393b6846114bad71e2cb2ccc3e10736b5716", 14 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 15 | maxCap: ethers.BigNumber.from(10).pow(18 + 4), 16 | depositConfigs: [ 17 | { 18 | chainId: 43113, 19 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 20 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 21 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 22 | }, 23 | { 24 | chainId: 80001, 25 | minCap: ethers.BigNumber.from(10).pow(18 + 2), 26 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 27 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(18 + 3)), 28 | }, 29 | ], 30 | equilibriumFee: 10000000, 31 | maxFee: 200000000, 32 | transferOverhead: 0, 33 | maxWalletLiquidityCap: ethers.BigNumber.from(10).pow(18 + 4), 34 | maxLiquidityCap: ethers.BigNumber.from(10).pow(18 + 5), 35 | svgHelper: await ethers.getContractFactory("EthereumUSDT"), 36 | decimals: 18, 37 | rewardRatePerSecond: 100, 38 | rewardTokenAddress: "0x64ef393b6846114bad71e2cb2ccc3e10736b5716", 39 | excessStateTransferFeePer: parseUnits("0.045", 8), 40 | }, 41 | { 42 | tokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", 43 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 44 | maxCap: ethers.BigNumber.from(10).pow(18 + 2), 45 | depositConfigs: [ 46 | { 47 | chainId: 43113, 48 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 49 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 50 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 51 | }, 52 | { 53 | chainId: 80001, 54 | minCap: ethers.BigNumber.from(10).pow(18 - 2), 55 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 56 | maxCap: ethers.BigNumber.from(97).mul(ethers.BigNumber.from(10).pow(18)), 57 | }, 58 | ], 59 | equilibriumFee: 10000000, 60 | maxFee: 200000000, 61 | transferOverhead: 0, 62 | maxWalletLiquidityCap: ethers.BigNumber.from(10).pow(18 + 4), 63 | maxLiquidityCap: ethers.BigNumber.from(10).pow(18 + 5), 64 | svgHelper: await ethers.getContractFactory("EthereumETH"), 65 | decimals: 18, 66 | rewardRatePerSecond: 100, 67 | rewardTokenAddress: "0x64ef393b6846114bad71e2cb2ccc3e10736b5716", 68 | excessStateTransferFeePer: parseUnits("0.045", 8), 69 | }, 70 | { 71 | tokenAddress: "0xb5B640E6414b6DeF4FC9B3C1EeF373925effeCcF", 72 | minCap: ethers.BigNumber.from(10).pow(6 + 2), 73 | maxCap: ethers.BigNumber.from(10).pow(6 + 4), 74 | depositConfigs: [ 75 | { 76 | chainId: 80001, 77 | minCap: ethers.BigNumber.from(10).pow(6 + 2), 78 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 79 | maxCap: ethers.BigNumber.from(9).mul(ethers.BigNumber.from(10).pow(6 + 3)), 80 | }, 81 | ], 82 | equilibriumFee: 10000000, 83 | maxFee: 200000000, 84 | transferOverhead: 0, 85 | maxWalletLiquidityCap: ethers.BigNumber.from(10).pow(6 + 4), 86 | maxLiquidityCap: ethers.BigNumber.from(10).pow(6 + 5), 87 | svgHelper: await ethers.getContractFactory("EthereumUSDC"), 88 | decimals: 6, 89 | rewardRatePerSecond: 100, 90 | rewardTokenAddress: "0x64ef393b6846114bad71e2cb2ccc3e10736b5716", 91 | excessStateTransferFeePer: parseUnits("0.045", 8), 92 | }, 93 | ], 94 | }; 95 | await deploy(config); 96 | })(); 97 | -------------------------------------------------------------------------------- /contracts/hyphen/ExecutorManager.sol: -------------------------------------------------------------------------------- 1 | // $$$$$$$$\ $$\ $$\ $$\ 2 | // $$ _____| $$ | $$$\ $$$ | 3 | // $$ | $$\ $$\ $$$$$$\ $$$$$$$\ $$\ $$\ $$$$$$\ $$$$$$\ $$$$$$\ $$$$\ $$$$ | $$$$$$\ $$$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ $$$$$$\ 4 | // $$$$$\ \$$\ $$ |$$ __$$\ $$ _____|$$ | $$ |\_$$ _| $$ __$$\ $$ __$$\ $$\$$\$$ $$ | \____$$\ $$ __$$\ \____$$\ $$ __$$\ $$ __$$\ $$ __$$\ 5 | // $$ __| \$$$$ / $$$$$$$$ |$$ / $$ | $$ | $$ | $$ / $$ |$$ | \__| $$ \$$$ $$ | $$$$$$$ |$$ | $$ | $$$$$$$ |$$ / $$ |$$$$$$$$ |$$ | \__| 6 | // $$ | $$ $$< $$ ____|$$ | $$ | $$ | $$ |$$\ $$ | $$ |$$ | $$ |\$ /$$ |$$ __$$ |$$ | $$ |$$ __$$ |$$ | $$ |$$ ____|$$ | 7 | // $$$$$$$$\ $$ /\$$\ \$$$$$$$\ \$$$$$$$\ \$$$$$$ | \$$$$ |\$$$$$$ |$$ | $$ | \_/ $$ |\$$$$$$$ |$$ | $$ |\$$$$$$$ |\$$$$$$$ |\$$$$$$$\ $$ | 8 | // \________|\__/ \__| \_______| \_______| \______/ \____/ \______/ \__| \__| \__| \_______|\__| \__| \_______| \____$$ | \_______|\__| 9 | // $$\ $$ | 10 | // \$$$$$$ | 11 | // \______/ 12 | // 13 | // SPDX-License-Identifier: MIT 14 | 15 | pragma solidity 0.8.0; 16 | 17 | import "@openzeppelin/contracts/access/Ownable.sol"; 18 | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; 19 | import "./interfaces/IExecutorManager.sol"; 20 | 21 | contract ExecutorManager is IExecutorManager, Ownable { 22 | using EnumerableSet for EnumerableSet.AddressSet; 23 | EnumerableSet.AddressSet private executors; 24 | 25 | event ExecutorAdded(address executor, address owner); 26 | event ExecutorRemoved(address executor, address owner); 27 | 28 | // MODIFIERS 29 | modifier onlyExecutor() { 30 | require(getExecutorStatus(msg.sender), "You are not allowed to perform this operation"); 31 | _; 32 | } 33 | 34 | function getExecutorStatus(address executor) public view override returns (bool status) { 35 | return executors.contains(executor); 36 | } 37 | 38 | function getAllExecutors() external view override returns (address[] memory) { 39 | uint256 length = executors.length(); 40 | address[] memory result = new address[](length); 41 | for (uint256 i; i < length; ) { 42 | result[i] = executors.at(i); 43 | unchecked { 44 | ++i; 45 | } 46 | } 47 | return result; 48 | } 49 | 50 | //Register new Executors 51 | function addExecutors(address[] calldata executorArray) external override onlyOwner { 52 | uint256 length = executorArray.length; 53 | for (uint256 i; i < length; ) { 54 | addExecutor(executorArray[i]); 55 | unchecked { 56 | ++i; 57 | } 58 | } 59 | } 60 | 61 | // Register single executor 62 | function addExecutor(address executorAddress) public override onlyOwner { 63 | require(executorAddress != address(0), "executor address can not be 0"); 64 | require(!getExecutorStatus(executorAddress), "Executor already registered"); 65 | executors.add(executorAddress); 66 | emit ExecutorAdded(executorAddress, msg.sender); 67 | } 68 | 69 | //Remove registered Executors 70 | function removeExecutors(address[] calldata executorArray) external override onlyOwner { 71 | uint256 length = executorArray.length; 72 | for (uint256 i; i < length; ) { 73 | removeExecutor(executorArray[i]); 74 | unchecked { 75 | ++i; 76 | } 77 | } 78 | } 79 | 80 | // Remove Register single executor 81 | function removeExecutor(address executorAddress) public override onlyOwner { 82 | require(getExecutorStatus(executorAddress), "Executor not registered"); 83 | executors.remove(executorAddress); 84 | emit ExecutorRemoved(executorAddress, msg.sender); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /scripts/backend-api-script/mainnet/token-config-fantom.ts: -------------------------------------------------------------------------------- 1 | import { setTokenConfig } from "../add-supported-token"; 2 | import { getBackendConfig } from "../utils"; 3 | 4 | (async () => { 5 | let tokenConfig = [ 6 | // USDC 7 | [ 8 | { 9 | tokenSymbol: "USDC", 10 | decimal: 6, 11 | chainId: 1, 12 | tokenAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", 13 | }, 14 | { 15 | tokenSymbol: "USDC", 16 | decimal: 6, 17 | chainId: 250, 18 | tokenAddress: "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75", 19 | }, 20 | ], 21 | [ 22 | { 23 | tokenSymbol: "USDC", 24 | decimal: 6, 25 | chainId: 137, 26 | tokenAddress: "0x2791bca1f2de4661ed88a30c99a7a9449aa84174", 27 | }, 28 | { 29 | tokenSymbol: "USDC", 30 | decimal: 6, 31 | chainId: 250, 32 | tokenAddress: "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75", 33 | }, 34 | ], 35 | [ 36 | { 37 | tokenSymbol: "USDC", 38 | decimal: 6, 39 | chainId: 43114, 40 | tokenAddress: "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664", 41 | }, 42 | { 43 | tokenSymbol: "USDC", 44 | decimal: 6, 45 | chainId: 250, 46 | tokenAddress: "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75", 47 | }, 48 | ], 49 | [ 50 | { 51 | tokenSymbol: "USDC", 52 | decimal: 18, 53 | chainId: 56, 54 | tokenAddress: "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", 55 | }, 56 | { 57 | tokenSymbol: "USDC", 58 | decimal: 6, 59 | chainId: 250, 60 | tokenAddress: "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75", 61 | }, 62 | ], 63 | [ 64 | { 65 | tokenSymbol: "USDC", 66 | decimal: 6, 67 | chainId: 10, 68 | tokenAddress: "0x7f5c764cbc14f9669b88837ca1490cca17c31607", 69 | }, 70 | { 71 | tokenSymbol: "USDC", 72 | decimal: 6, 73 | chainId: 250, 74 | tokenAddress: "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75", 75 | }, 76 | ], 77 | [ 78 | { 79 | tokenSymbol: "USDC", 80 | decimal: 6, 81 | chainId: 42161, 82 | tokenAddress: "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8", 83 | }, 84 | { 85 | tokenSymbol: "USDC", 86 | decimal: 6, 87 | chainId: 250, 88 | tokenAddress: "0x04068DA6C83AFCFA0e13ba15A6696662335D5B75", 89 | }, 90 | ], 91 | // BICO 92 | [ 93 | { 94 | tokenSymbol: "BICO", 95 | decimal: 18, 96 | chainId: 1, 97 | tokenAddress: "0xf17e65822b568b3903685a7c9f496cf7656cc6c2", 98 | }, 99 | { 100 | tokenSymbol: "BICO", 101 | decimal: 18, 102 | chainId: 250, 103 | tokenAddress: "0x524cabe5b2f66cbd6f6b08def086f18f8dde033a", 104 | }, 105 | ], 106 | [ 107 | { 108 | tokenSymbol: "BICO", 109 | decimal: 18, 110 | chainId: 137, 111 | tokenAddress: "0x91c89a94567980f0e9723b487b0bed586ee96aa7", 112 | }, 113 | { 114 | tokenSymbol: "BICO", 115 | decimal: 18, 116 | chainId: 250, 117 | tokenAddress: "0x524cabe5b2f66cbd6f6b08def086f18f8dde033a", 118 | }, 119 | ], 120 | [ 121 | { 122 | tokenSymbol: "BICO", 123 | decimal: 18, 124 | chainId: 56, 125 | tokenAddress: "0x06250a4962558f0f3e69fc07f4c67bb9c9eac739", 126 | }, 127 | { 128 | tokenSymbol: "BICO", 129 | decimal: 18, 130 | chainId: 250, 131 | tokenAddress: "0x524cabe5b2f66cbd6f6b08def086f18f8dde033a", 132 | }, 133 | ], 134 | [ 135 | { 136 | tokenSymbol: "BICO", 137 | decimal: 18, 138 | chainId: 10, 139 | tokenAddress: "0xd6909e9e702024eb93312b989ee46794c0fb1c9d", 140 | }, 141 | { 142 | tokenSymbol: "BICO", 143 | decimal: 18, 144 | chainId: 250, 145 | tokenAddress: "0x524cabe5b2f66cbd6f6b08def086f18f8dde033a", 146 | }, 147 | ], 148 | [ 149 | { 150 | tokenSymbol: "BICO", 151 | decimal: 18, 152 | chainId: 42161, 153 | tokenAddress: "0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d", 154 | }, 155 | { 156 | tokenSymbol: "BICO", 157 | decimal: 18, 158 | chainId: 250, 159 | tokenAddress: "0x524cabe5b2f66cbd6f6b08def086f18f8dde033a", 160 | }, 161 | ], 162 | ]; 163 | 164 | setTokenConfig(tokenConfig, getBackendConfig("prod")); 165 | })(); 166 | -------------------------------------------------------------------------------- /scripts/backend-api-script/mainnet/token-config-optimism.ts: -------------------------------------------------------------------------------- 1 | import { setTokenConfig } from "../add-supported-token"; 2 | import { getBackendConfig } from "../utils"; 3 | 4 | (async () => { 5 | let tokenConfig = [ 6 | // USDC 7 | [ 8 | { 9 | tokenSymbol: "USDC", 10 | decimal: 6, 11 | chainId: 1, 12 | tokenAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", 13 | }, 14 | { 15 | tokenSymbol: "USDC", 16 | decimal: 6, 17 | chainId: 10, 18 | tokenAddress: "0x7f5c764cbc14f9669b88837ca1490cca17c31607", 19 | }, 20 | ], 21 | [ 22 | { 23 | tokenSymbol: "USDC", 24 | decimal: 6, 25 | chainId: 137, 26 | tokenAddress: "0x2791bca1f2de4661ed88a30c99a7a9449aa84174", 27 | }, 28 | { 29 | tokenSymbol: "USDC", 30 | decimal: 6, 31 | chainId: 10, 32 | tokenAddress: "0x7f5c764cbc14f9669b88837ca1490cca17c31607", 33 | }, 34 | ], 35 | [ 36 | { 37 | tokenSymbol: "USDC", 38 | decimal: 6, 39 | chainId: 43114, 40 | tokenAddress: "0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664", 41 | }, 42 | { 43 | tokenSymbol: "USDC", 44 | decimal: 6, 45 | chainId: 10, 46 | tokenAddress: "0x7f5c764cbc14f9669b88837ca1490cca17c31607", 47 | }, 48 | ], 49 | [ 50 | { 51 | tokenSymbol: "USDC", 52 | decimal: 18, 53 | chainId: 56, 54 | tokenAddress: "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d", 55 | }, 56 | { 57 | tokenSymbol: "USDC", 58 | decimal: 6, 59 | chainId: 10, 60 | tokenAddress: "0x7f5c764cbc14f9669b88837ca1490cca17c31607", 61 | }, 62 | ], 63 | // BICO 64 | [ 65 | { 66 | tokenSymbol: "BICO", 67 | decimal: 18, 68 | chainId: 1, 69 | tokenAddress: "0xf17e65822b568b3903685a7c9f496cf7656cc6c2", 70 | }, 71 | { 72 | tokenSymbol: "BICO", 73 | decimal: 18, 74 | chainId: 10, 75 | tokenAddress: "0x7f5c764cbc14f9669b88837ca1490cca17c31607", 76 | }, 77 | ], 78 | [ 79 | { 80 | tokenSymbol: "BICO", 81 | decimal: 18, 82 | chainId: 137, 83 | tokenAddress: "0x91c89a94567980f0e9723b487b0bed586ee96aa7", 84 | }, 85 | { 86 | tokenSymbol: "BICO", 87 | decimal: 18, 88 | chainId: 10, 89 | tokenAddress: "0x7f5c764cbc14f9669b88837ca1490cca17c31607", 90 | }, 91 | ], 92 | [ 93 | { 94 | tokenSymbol: "BICO", 95 | decimal: 18, 96 | chainId: 56, 97 | tokenAddress: "0x06250a4962558f0f3e69fc07f4c67bb9c9eac739", 98 | }, 99 | { 100 | tokenSymbol: "BICO", 101 | decimal: 18, 102 | chainId: 10, 103 | tokenAddress: "0x7f5c764cbc14f9669b88837ca1490cca17c31607", 104 | }, 105 | ], 106 | // ETH 107 | [ 108 | { 109 | tokenSymbol: "ETH", 110 | decimal: 18, 111 | chainId: 1, 112 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 113 | }, 114 | { 115 | tokenSymbol: "ETH", 116 | decimal: 18, 117 | chainId: 10, 118 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 119 | }, 120 | ], 121 | [ 122 | { 123 | tokenSymbol: "ETH", 124 | decimal: 18, 125 | chainId: 137, 126 | tokenAddress: "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619", 127 | }, 128 | { 129 | tokenSymbol: "ETH", 130 | decimal: 18, 131 | chainId: 10, 132 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 133 | }, 134 | ], 135 | [ 136 | { 137 | tokenSymbol: "ETH", 138 | decimal: 18, 139 | chainId: 56, 140 | tokenAddress: "0x2170ed0880ac9a755fd29b2688956bd959f933f8", 141 | }, 142 | { 143 | tokenSymbol: "ETH", 144 | decimal: 18, 145 | chainId: 10, 146 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 147 | }, 148 | ], 149 | [ 150 | { 151 | tokenSymbol: "ETH", 152 | decimal: 18, 153 | chainId: 43114, 154 | tokenAddress: "0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab", 155 | }, 156 | { 157 | tokenSymbol: "ETH", 158 | decimal: 18, 159 | chainId: 10, 160 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 161 | }, 162 | ], 163 | ]; 164 | 165 | setTokenConfig(tokenConfig, getBackendConfig("prod")); 166 | })(); 167 | -------------------------------------------------------------------------------- /scripts/backend-api-script/testnet/token-config-arbitestnet.ts: -------------------------------------------------------------------------------- 1 | import { setTokenConfig } from "../add-supported-token"; 2 | import { getBackendConfig } from "../utils"; 3 | 4 | (async () => { 5 | let tokenConfig = [ 6 | // USDC 7 | [ 8 | { 9 | tokenSymbol: "USDC", 10 | decimal: 6, 11 | chainId: 5, 12 | tokenAddress: "0xb5B640E6414b6DeF4FC9B3C1EeF373925effeCcF", 13 | }, 14 | { 15 | tokenSymbol: "USDC", 16 | decimal: 6, 17 | chainId: 421611, 18 | tokenAddress: "0x31b02918d86afdb502e48958a8190e98952a9c0c", 19 | }, 20 | ], 21 | [ 22 | { 23 | tokenSymbol: "USDC", 24 | decimal: 6, 25 | chainId: 80001, 26 | tokenAddress: "0xdA5289fCAAF71d52a80A254da614a192b693e977", 27 | }, 28 | { 29 | tokenSymbol: "USDC", 30 | decimal: 6, 31 | chainId: 421611, 32 | tokenAddress: "0x31b02918d86afdb502e48958a8190e98952a9c0c", 33 | }, 34 | ], 35 | [ 36 | { 37 | tokenSymbol: "USDC", 38 | decimal: 6, 39 | chainId: 69, 40 | tokenAddress: "0x4995E4dd58Fa9eF9D80F3111777fdd4bC3300a7C", 41 | }, 42 | { 43 | tokenSymbol: "USDC", 44 | decimal: 6, 45 | chainId: 421611, 46 | tokenAddress: "0x31b02918d86afdb502e48958a8190e98952a9c0c", 47 | }, 48 | ], 49 | 50 | // BICO 51 | [ 52 | { 53 | tokenSymbol: "BICO", 54 | decimal: 18, 55 | chainId: 5, 56 | tokenAddress: "0xDdc47b0cA071682e8dc373391aCA18dA0Fe28699", 57 | }, 58 | { 59 | tokenSymbol: "BICO", 60 | decimal: 18, 61 | chainId: 421611, 62 | tokenAddress: "0xd8e71dedbd081e9b702c69a6afca61c07076a148", 63 | }, 64 | ], 65 | [ 66 | { 67 | tokenSymbol: "BICO", 68 | decimal: 18, 69 | chainId: 80001, 70 | tokenAddress: "0xac42d8319ce458b22a72b45f58c0dcfeee824691", 71 | }, 72 | { 73 | tokenSymbol: "BICO", 74 | decimal: 18, 75 | chainId: 421611, 76 | tokenAddress: "0xd8e71dedbd081e9b702c69a6afca61c07076a148", 77 | }, 78 | ], 79 | [ 80 | { 81 | tokenSymbol: "BICO", 82 | decimal: 18, 83 | chainId: 69, 84 | tokenAddress: "0x439725d33Fe46f1C167F6116aeEd7d910E482D2E", 85 | }, 86 | { 87 | tokenSymbol: "BICO", 88 | decimal: 18, 89 | chainId: 421611, 90 | tokenAddress: "0xd8e71dedbd081e9b702c69a6afca61c07076a148", 91 | }, 92 | ], 93 | [ 94 | { 95 | tokenSymbol: "BICO", 96 | decimal: 18, 97 | chainId: 97, 98 | tokenAddress: "0x756289346D2b3C867966899c6D0467EdEb4Da3C4", 99 | }, 100 | { 101 | tokenSymbol: "BICO", 102 | decimal: 18, 103 | chainId: 421611, 104 | tokenAddress: "0xd8e71dedbd081e9b702c69a6afca61c07076a148", 105 | }, 106 | ], 107 | 108 | // ETH 109 | [ 110 | { 111 | tokenSymbol: "ETH", 112 | decimal: 18, 113 | chainId: 5, 114 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 115 | }, 116 | { 117 | tokenSymbol: "ETH", 118 | decimal: 18, 119 | chainId: 421611, 120 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 121 | }, 122 | ], 123 | [ 124 | { 125 | tokenSymbol: "ETH", 126 | decimal: 18, 127 | chainId: 80001, 128 | tokenAddress: "0xa6fa4fb5f76172d178d61b04b0ecd319c5d1c0aa", 129 | }, 130 | { 131 | tokenSymbol: "ETH", 132 | decimal: 18, 133 | chainId: 421611, 134 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 135 | }, 136 | ], 137 | [ 138 | { 139 | tokenSymbol: "ETH", 140 | decimal: 18, 141 | chainId: 43113, 142 | tokenAddress: "0x7fcdc2c1ef3e4a0bcc8155a558bb20a7218f2b05", 143 | }, 144 | { 145 | tokenSymbol: "ETH", 146 | decimal: 18, 147 | chainId: 421611, 148 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 149 | }, 150 | ], 151 | [ 152 | { 153 | tokenSymbol: "ETH", 154 | decimal: 18, 155 | chainId: 97, 156 | tokenAddress: "0x756289346D2b3C867966899c6D0467EdEb4Da3C4", 157 | }, 158 | { 159 | tokenSymbol: "ETH", 160 | decimal: 18, 161 | chainId: 421611, 162 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 163 | }, 164 | ], 165 | ]; 166 | 167 | setTokenConfig(tokenConfig, getBackendConfig("staging")); 168 | })(); 169 | -------------------------------------------------------------------------------- /scripts/prod-replica-helpers/transfer-ownership.ts: -------------------------------------------------------------------------------- 1 | import { getContractAddressesByChain } from "../upgrades/upgrade-all/upgrade-all"; 2 | import { ethers } from "hardhat"; 3 | import { 4 | ExecutorManager__factory, 5 | HyphenLiquidityFarmingV2__factory, 6 | HyphenLiquidityFarming__factory, 7 | LiquidityPool__factory, 8 | LiquidityProviders__factory, 9 | LPToken__factory, 10 | TokenManager__factory, 11 | WhitelistPeriodManager__factory, 12 | } from "../../typechain"; 13 | import { getProxyAdmin } from "../deploy/deploy-utils"; 14 | import proxyAdminAbi from "./abi/ProxyAdmin"; 15 | import { IContractAddresses } from "../types"; 16 | import { impersonateAndExecute, sendTransaction, setNativeBalance } from "./utils"; 17 | 18 | const transferOwnership = async (contracts: IContractAddresses, newOwner: string) => { 19 | const chainId = (await ethers.provider.getNetwork()).chainId; 20 | const oldOwner = await ExecutorManager__factory.connect(contracts.executorManager, ethers.provider).owner(); 21 | if (!oldOwner) { 22 | throw new Error("Error while fetching old owner"); 23 | } 24 | console.log(`Current Contract Owner on chain ${chainId}: ${oldOwner}`); 25 | 26 | await impersonateAndExecute(oldOwner, async (signer) => { 27 | console.log(`Transferring Ownership For Executor Manager on chain ${chainId}...`); 28 | const executorManager = ExecutorManager__factory.connect(contracts.executorManager, signer); 29 | await sendTransaction(executorManager.transferOwnership(newOwner), "Updating Executor Manager Owner"); 30 | 31 | console.log(`Transferring Ownership For LiquidityPool on chain ${chainId}...`); 32 | const liquidityPool = LiquidityPool__factory.connect(contracts.liquidityPool, signer); 33 | await sendTransaction(liquidityPool.transferOwnership(newOwner), "Updating Liquidity Pool Owner"); 34 | 35 | console.log(`Transferring Ownership For LiquidityProviderson chain ${chainId}...`); 36 | const liquidityProviders = LiquidityProviders__factory.connect(contracts.liquidityProviders, signer); 37 | await sendTransaction(liquidityProviders.transferOwnership(newOwner), "Updating LiquidityProviders Owner"); 38 | 39 | console.log(`Transferring Ownership For LpToken on chain ${chainId}...`); 40 | const lpToken = LPToken__factory.connect(contracts.lpToken, signer); 41 | await sendTransaction(lpToken.transferOwnership(newOwner), "Updating LpToken Owner"); 42 | 43 | console.log(`Transferring Ownership For TokenManager on chain ${chainId}...`); 44 | const tokenManager = TokenManager__factory.connect(contracts.tokenManager, signer); 45 | await sendTransaction(tokenManager.transferOwnership(newOwner), "Updating TokenManager Owner"); 46 | 47 | console.log(`Transferring Ownership For WhiteListPeriodManager on chain ${chainId}...`); 48 | const wlpm = WhitelistPeriodManager__factory.connect(contracts.whitelistPeriodManager, signer); 49 | await sendTransaction(wlpm.transferOwnership(newOwner), "Updating WhitelistPeriod Manager Owner"); 50 | 51 | if (contracts.liquidityFarmingV1) { 52 | console.log(`Transferring Ownership For LiquidityFarmingV1 Manager on chain ${chainId}...`); 53 | const liquidityFarmingV1 = HyphenLiquidityFarming__factory.connect(contracts.liquidityFarmingV1, signer); 54 | await sendTransaction(liquidityFarmingV1.transferOwnership(newOwner), "Updating LiquidityFarmingV1 Owner"); 55 | } 56 | 57 | if (contracts.liquidityFarmingV2) { 58 | console.log(`Transferring Ownership For LiquidityFarmingV2 on chain ${chainId}...`); 59 | const liquidityFarmingV2 = HyphenLiquidityFarmingV2__factory.connect(contracts.liquidityFarmingV2, signer); 60 | await sendTransaction(liquidityFarmingV2.transferOwnership(newOwner), "Updating LiquidityFarmingV2 Owner"); 61 | } 62 | }); 63 | 64 | const proxyAdminAddress = await getProxyAdmin(contracts.liquidityPool); 65 | console.log(`Transferring Ownership For ProxyAdmin ${proxyAdminAddress} on chain ${chainId}...`); 66 | let proxyAdmin = new ethers.Contract(proxyAdminAddress, proxyAdminAbi, ethers.provider); 67 | const currentProxyAdminOwner = await proxyAdmin.owner(); 68 | console.log(`Current ProxyAdmin Owner on chain ${chainId}: ${currentProxyAdminOwner}`); 69 | 70 | await impersonateAndExecute(currentProxyAdminOwner, async (signer) => { 71 | proxyAdmin = new ethers.Contract(proxyAdminAddress, proxyAdminAbi, signer); 72 | await sendTransaction(proxyAdmin.transferOwnership(newOwner), "Updating ProxyAdmin Owner"); 73 | }); 74 | }; 75 | 76 | (async () => { 77 | if (!process.env.NEW_OWNER_ADDRESS) { 78 | throw new Error("NEW_OWNER_ADDRESS is not set"); 79 | } 80 | const NEW_OWNER_ADDRESS: string = process.env.NEW_OWNER_ADDRESS; 81 | console.log(`New Owner Address: ${NEW_OWNER_ADDRESS}`); 82 | await setNativeBalance(NEW_OWNER_ADDRESS, ethers.utils.parseEther("100")); 83 | 84 | const chainId = (await ethers.provider.getNetwork()).chainId; 85 | const contracts = await getContractAddressesByChain(process.env.PROD_API_URL as string, chainId); 86 | console.log(`Contracts on chain ${chainId}: ${JSON.stringify(contracts, null, 2)}`); 87 | 88 | await transferOwnership(contracts, NEW_OWNER_ADDRESS); 89 | })(); 90 | -------------------------------------------------------------------------------- /scripts/token-manager/helper.ts: -------------------------------------------------------------------------------- 1 | import { run, ethers, upgrades } from "hardhat"; 2 | import { TokenManager } from "../../typechain"; 3 | import type { BigNumberish, ContractFactory } from "ethers"; 4 | 5 | interface IAddTokenParameters { 6 | tokenAddress: string; 7 | minCap: BigNumberish; 8 | maxCap: BigNumberish; 9 | depositConfigs: { chainId: number; minCap: BigNumberish; maxCap: BigNumberish }[]; 10 | equilibriumFee: BigNumberish; 11 | maxFee: BigNumberish; 12 | transferOverhead: BigNumberish; 13 | excessStateTransferFeePer: BigNumberish; 14 | } 15 | 16 | interface IContracts { 17 | tokenManager: TokenManager; 18 | } 19 | 20 | interface IDeployConfig { 21 | trustedForwarder: string; 22 | bicoOwner: string; 23 | pauser: string; 24 | tokens: IAddTokenParameters[]; 25 | } 26 | 27 | const wait = (time: number): Promise => { 28 | return new Promise((resolve) => { 29 | setTimeout(resolve, time); 30 | }); 31 | }; 32 | 33 | const deploy = async (deployConfig: IDeployConfig) => { 34 | const contracts = await deployCoreContracts(deployConfig.trustedForwarder, deployConfig.pauser); 35 | 36 | for (const token of deployConfig.tokens) { 37 | await addTokenSupport(contracts, token); 38 | } 39 | 40 | // await configure(contracts, deployConfig.bicoOwner); 41 | await verify(contracts, deployConfig); 42 | }; 43 | 44 | async function deployCoreContracts(trustedForwarder: string, pauser: string): Promise { 45 | const [deployer] = await ethers.getSigners(); 46 | 47 | console.log("Deployer:", deployer.address); 48 | 49 | console.log("Deploying TokenManager..."); 50 | const tokenManager = (await upgrades.deployProxy(await ethers.getContractFactory("TokenManager"), [ 51 | trustedForwarder, 52 | pauser, 53 | ])) as TokenManager; 54 | await tokenManager.deployed(); 55 | console.log("TokenManager deployed to:", tokenManager.address); 56 | await wait(5000); 57 | 58 | return { tokenManager }; 59 | } 60 | 61 | const configure = async (contracts: IContracts, bicoOwner: string) => { 62 | await (await contracts.tokenManager.transferOwnership(bicoOwner)).wait(); 63 | await wait(5000); 64 | 65 | console.log(`Transferred Ownership to ${bicoOwner}`); 66 | }; 67 | 68 | const addTokenSupport = async (contracts: IContracts, token: IAddTokenParameters) => { 69 | // Add support for token 70 | console.log(`Adding token support for ${token.tokenAddress}...`); 71 | await ( 72 | await contracts.tokenManager.addSupportedToken( 73 | token.tokenAddress, 74 | token.minCap, 75 | token.maxCap, 76 | token.equilibriumFee, 77 | token.maxFee, 78 | token.transferOverhead 79 | ) 80 | ).wait(); 81 | 82 | let chainIdArray = []; 83 | let minMaxArray = []; 84 | for (let index = 0; index < token.depositConfigs.length; index++) { 85 | let entry = token.depositConfigs[index]; 86 | chainIdArray.push(entry.chainId); 87 | minMaxArray.push({ min: entry.minCap, max: entry.maxCap }); 88 | } 89 | 90 | console.log(`Setting Deposit Config for ${token.tokenAddress}...`); 91 | await ( 92 | await contracts.tokenManager.setDepositConfig( 93 | chainIdArray, 94 | new Array(chainIdArray.length).fill(token.tokenAddress), 95 | minMaxArray 96 | ) 97 | ).wait(); 98 | 99 | console.log(`Setting Excess State Transfer Fee % for ${token.tokenAddress}...`); 100 | await (await contracts.tokenManager.changeExcessStateFee(token.tokenAddress, token.excessStateTransferFeePer)).wait(); 101 | 102 | console.log("Added token support for", token.tokenAddress); 103 | }; 104 | 105 | const getImplementationAddress = async (proxyAddress: string) => { 106 | return ethers.utils.hexlify( 107 | ethers.BigNumber.from( 108 | await ethers.provider.send("eth_getStorageAt", [ 109 | proxyAddress, 110 | "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", 111 | "latest", 112 | ]) 113 | ) 114 | ); 115 | }; 116 | 117 | const verifyContract = async (address: string, constructorArguments: any[]) => { 118 | try { 119 | await run("verify:verify", { 120 | address, 121 | constructorArguments, 122 | }); 123 | } catch (e) { 124 | console.log(`Failed to verify Contract ${address} `, e); 125 | } 126 | }; 127 | 128 | const verifyImplementation = async (address: string) => { 129 | try { 130 | await run("verify:verify", { 131 | address: await getImplementationAddress(address), 132 | }); 133 | } catch (e) { 134 | console.log(`Failed to verify Contract ${address} `, e); 135 | } 136 | }; 137 | 138 | const verify = async ( 139 | contracts: IContracts, 140 | config: { trustedForwarder: string; pauser: string; tokens: IAddTokenParameters[] } 141 | ) => { 142 | console.log("Verifying Contracts..."); 143 | 144 | await verifyImplementation(contracts.tokenManager.address); 145 | }; 146 | 147 | export { 148 | deployCoreContracts as deployContracts, 149 | configure, 150 | addTokenSupport, 151 | verify, 152 | deploy, 153 | verifyContract, 154 | verifyImplementation, 155 | IDeployConfig, 156 | }; 157 | -------------------------------------------------------------------------------- /scripts/token-manager/deploy-polygon.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy, IDeployConfig } from "./helper"; 4 | 5 | (async () => { 6 | const config: IDeployConfig = { 7 | trustedForwarder: "0x86C80a8aa58e0A4fa09A69624c31Ab2a6CAD56b8", 8 | bicoOwner: "0xd76b82204be75ab9610b04cf27c4f4a34291d5e6", 9 | pauser: "0xc8582180f52B6303F51e7028C3A9f428Eb43DfE7", 10 | tokens: [ 11 | // USDT 12 | { 13 | tokenAddress: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", 14 | minCap: parseUnits("10", 6), 15 | maxCap: parseUnits("58160", 6), 16 | depositConfigs: [ 17 | { 18 | chainId: 1, 19 | minCap: parseUnits("100", 6), 20 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 21 | maxCap: parseUnits("100000", 6), 22 | }, 23 | { 24 | chainId: 56, 25 | minCap: parseUnits("100", 6), 26 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 27 | maxCap: parseUnits("100000", 6), 28 | }, 29 | ], 30 | equilibriumFee: ethers.utils.parseUnits("0.075", 8), 31 | maxFee: ethers.utils.parseUnits("0.5", 8), 32 | transferOverhead: 82491, // TODO 33 | excessStateTransferFeePer: parseUnits("0.045", 8), 34 | }, 35 | // USDC 36 | { 37 | tokenAddress: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", 38 | minCap: parseUnits("10", 6), 39 | maxCap: parseUnits("221813", 6), 40 | depositConfigs: [ 41 | { 42 | chainId: 1, 43 | minCap: parseUnits("100", 6), 44 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 45 | maxCap: parseUnits("200000", 6), 46 | }, 47 | { 48 | chainId: 43114, 49 | minCap: parseUnits("10", 6), 50 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 51 | maxCap: parseUnits("200000", 6), 52 | }, 53 | { 54 | chainId: 56, 55 | minCap: parseUnits("10", 6), 56 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 57 | maxCap: parseUnits("200000", 6), 58 | }, 59 | ], 60 | equilibriumFee: ethers.utils.parseUnits("0.075", 8), 61 | maxFee: ethers.utils.parseUnits("0.5", 8), 62 | transferOverhead: 89491, 63 | excessStateTransferFeePer: parseUnits("0.045", 8), 64 | }, 65 | // BICO 66 | { 67 | tokenAddress: "0x91c89A94567980f0e9723b487b0beD586eE96aa7", 68 | minCap: parseUnits("10", 18), 69 | maxCap: parseUnits("323220", 18), 70 | depositConfigs: [ 71 | { 72 | chainId: 1, 73 | minCap: parseUnits("50", 18), 74 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 75 | maxCap: parseUnits("500000", 18), 76 | }, 77 | { 78 | chainId: 56, 79 | minCap: parseUnits("10", 18), 80 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 81 | maxCap: parseUnits("500000", 18), 82 | }, 83 | ], 84 | equilibriumFee: ethers.utils.parseUnits("0.075", 8), 85 | maxFee: ethers.utils.parseUnits("0.5", 8), 86 | transferOverhead: 85949, 87 | excessStateTransferFeePer: parseUnits("0.045", 8), 88 | }, 89 | // WETH 90 | { 91 | tokenAddress: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", 92 | minCap: parseUnits("0.0039", 18), 93 | maxCap: parseUnits("143", 18), 94 | depositConfigs: [ 95 | { 96 | chainId: 1, 97 | minCap: parseUnits("0.02", 18), 98 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 99 | maxCap: parseUnits("120", 18), 100 | }, 101 | { 102 | chainId: 43114, 103 | minCap: parseUnits("0.0039", 18), 104 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 105 | maxCap: parseUnits("100", 18), 106 | }, 107 | { 108 | chainId: 56, 109 | minCap: parseUnits("0.02", 18), 110 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 111 | maxCap: parseUnits("135", 18), 112 | }, 113 | ], 114 | equilibriumFee: ethers.utils.parseUnits("0.075", 8), 115 | maxFee: ethers.utils.parseUnits("0.5", 8), 116 | transferOverhead: 72945, 117 | excessStateTransferFeePer: parseUnits("0.045", 8), 118 | }, 119 | ], 120 | }; 121 | await deploy(config); 122 | })(); 123 | -------------------------------------------------------------------------------- /scripts/token-manager/deploy-ethereum.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy, IDeployConfig } from "./helper"; 4 | 5 | (async () => { 6 | const config: IDeployConfig = { 7 | trustedForwarder: "0x84a0856b038eaAd1cC7E297cF34A7e72685A8693", 8 | bicoOwner: "0xd76b82204be75ab9610b04cf27c4f4a34291d5e6", 9 | pauser: "0x144A36059cdc0eF8e192ddC4df6E6d2F013fDa6A", 10 | tokens: [ 11 | // USDT 12 | { 13 | tokenAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7", 14 | minCap: parseUnits("100", 6), 15 | maxCap: parseUnits("120000", 6), 16 | depositConfigs: [ 17 | { 18 | chainId: 137, 19 | minCap: parseUnits("10", 6), 20 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 21 | maxCap: parseUnits("50000", 6), 22 | }, 23 | { 24 | chainId: 56, 25 | minCap: parseUnits("10", 6), 26 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 27 | maxCap: parseUnits("100000", 6), 28 | } 29 | ], 30 | equilibriumFee: ethers.utils.parseUnits("0.075", 8), 31 | maxFee: ethers.utils.parseUnits("0.5", 8), 32 | transferOverhead: 82491, // TODO 33 | excessStateTransferFeePer: parseUnits("0.045", 8), 34 | }, 35 | // USDC 36 | { 37 | tokenAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", 38 | minCap: parseUnits("100", 6), 39 | maxCap: parseUnits("221813", 6), 40 | depositConfigs: [ 41 | { 42 | chainId: 137, 43 | minCap: parseUnits("10", 6), 44 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 45 | maxCap: parseUnits("200000", 6), 46 | }, 47 | { 48 | chainId: 43114, 49 | minCap: parseUnits("10", 6), 50 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 51 | maxCap: parseUnits("200000", 6), 52 | }, 53 | { 54 | chainId: 56, 55 | minCap: parseUnits("10", 6), 56 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 57 | maxCap: parseUnits("200000", 6), 58 | }, 59 | ], 60 | equilibriumFee: ethers.utils.parseUnits("0.075", 8), 61 | maxFee: ethers.utils.parseUnits("0.5", 8), 62 | transferOverhead: 89491, 63 | excessStateTransferFeePer: parseUnits("0.045", 8), 64 | }, 65 | // BICO 66 | { 67 | tokenAddress: "0xf17e65822b568b3903685a7c9f496cf7656cc6c2", 68 | minCap: parseUnits("50", 18), 69 | maxCap: parseUnits("550000", 18), 70 | depositConfigs: [ 71 | { 72 | chainId: 137, 73 | minCap: parseUnits("10", 18), 74 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 75 | maxCap: parseUnits("300000", 18), 76 | }, 77 | { 78 | chainId: 56, 79 | minCap: parseUnits("10", 18), 80 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 81 | maxCap: parseUnits("500000", 18), 82 | }, 83 | ], 84 | equilibriumFee: ethers.utils.parseUnits("0.075", 8), 85 | maxFee: ethers.utils.parseUnits("0.5", 8), 86 | transferOverhead: 85949, 87 | excessStateTransferFeePer: parseUnits("0.045", 8), 88 | }, 89 | // ETH 90 | { 91 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 92 | minCap: parseUnits("0.02", 18), 93 | maxCap: parseUnits("143", 18), 94 | depositConfigs: [ 95 | { 96 | chainId: 137, 97 | minCap: parseUnits("0.0039", 18), 98 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 99 | maxCap: parseUnits("100", 18), 100 | }, 101 | { 102 | chainId: 43114, 103 | minCap: parseUnits("0.0039", 18), 104 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 105 | maxCap: parseUnits("100", 18), 106 | }, 107 | { 108 | chainId: 56, 109 | minCap: parseUnits("0.02", 18), 110 | // Max Cap needs to be less than the maxTransfer Fee on destination chain id to cover for incentive amount 111 | maxCap: parseUnits("135", 18), 112 | }, 113 | ], 114 | equilibriumFee: ethers.utils.parseUnits("0.075", 8), 115 | maxFee: ethers.utils.parseUnits("0.5", 8), 116 | transferOverhead: 59271, 117 | excessStateTransferFeePer: parseUnits("0.045", 8), 118 | }, 119 | ], 120 | }; 121 | await deploy(config); 122 | })(); 123 | -------------------------------------------------------------------------------- /scripts/deploy/mainnet/deploy-arbitrum.ts: -------------------------------------------------------------------------------- 1 | import { ethers } from "hardhat"; 2 | import { parseUnits } from "ethers/lib/utils"; 3 | import { deploy } from "../deploy-utils"; 4 | import type { IDeployConfig } from "../../types"; 5 | 6 | (async () => { 7 | const config: IDeployConfig = { 8 | trustedForwarder: "0x64CD353384109423a966dCd3Aa30D884C9b2E057", 9 | bicoOwner: "0xd76b82204be75ab9610b04cf27c4f4a34291d5e6", 10 | pauser: "0x129443cA2a9Dec2020808a2868b38dDA457eaCC7", 11 | tokens: [ 12 | // USDC 13 | { 14 | tokenAddress: "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8", 15 | minCap: parseUnits("10", 6), 16 | maxCap: parseUnits("221813", 6), 17 | depositConfigs: [ 18 | { 19 | chainId: 1, // Ethereum 20 | minCap: parseUnits("100", 6), 21 | maxCap: parseUnits("200000", 6), 22 | }, 23 | { 24 | chainId: 137, // Polygon 25 | minCap: parseUnits("10", 6), 26 | maxCap: parseUnits("200000", 6), 27 | }, 28 | { 29 | chainId: 43114, // Avalanche 30 | minCap: parseUnits("10", 6), 31 | maxCap: parseUnits("200000", 6), 32 | }, 33 | { 34 | chainId: 56, // Binance chain 35 | minCap: parseUnits("10", 6), 36 | maxCap: parseUnits("200000", 6), 37 | }, 38 | { 39 | chainId: 10, // Optimism 40 | minCap: parseUnits("10", 6), 41 | maxCap: parseUnits("200000", 6), 42 | }, 43 | ], 44 | equilibriumFee: parseUnits("0.075", 8), 45 | maxFee: parseUnits("0.5", 8), 46 | transferOverhead: 89491, 47 | maxWalletLiquidityCap: parseUnits("0", 6), // not used 48 | maxLiquidityCap: parseUnits("500000", 6), 49 | svgHelper: await ethers.getContractFactory("ArbitrumUSDC"), 50 | decimals: 6, 51 | rewardTokenAddress: "0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d", 52 | rewardRatePerSecond: parseUnits("0.001604", 18), 53 | excessStateTransferFeePer: parseUnits("0.045", 8), 54 | }, 55 | // BICO 56 | { 57 | tokenAddress: "0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d", 58 | minCap: parseUnits("10", 18), 59 | maxCap: parseUnits("510000", 18), 60 | depositConfigs: [ 61 | { 62 | chainId: 1, // Ethereum 63 | minCap: parseUnits("50", 18), 64 | maxCap: parseUnits("500000", 18), 65 | }, 66 | { 67 | chainId: 137, // Polygon 68 | minCap: parseUnits("10", 18), 69 | maxCap: parseUnits("300000", 18), 70 | }, 71 | { 72 | chainId: 56, // Binance chain 73 | minCap: parseUnits("10", 18), 74 | maxCap: parseUnits("500000", 18), 75 | }, 76 | { 77 | chainId: 10, // Optimism 78 | minCap: parseUnits("10", 18), 79 | maxCap: parseUnits("500000", 18), 80 | }, 81 | ], 82 | equilibriumFee: parseUnits("0.075", 8), 83 | maxFee: parseUnits("0.5", 8), 84 | transferOverhead: 85949, 85 | maxWalletLiquidityCap: parseUnits("0", 18), // not used 86 | maxLiquidityCap: parseUnits("750000", 18), 87 | svgHelper: await ethers.getContractFactory("ArbitrumBICO"), 88 | decimals: 18, 89 | rewardTokenAddress: "0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d", 90 | rewardRatePerSecond: parseUnits("0", 18), 91 | excessStateTransferFeePer: parseUnits("0.045", 8), 92 | }, 93 | // ETH 94 | { 95 | tokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", 96 | minCap: parseUnits("0.02", 18), 97 | maxCap: parseUnits("143", 18), 98 | depositConfigs: [ 99 | { 100 | chainId: 1, // Ethereum 101 | minCap: parseUnits("0.02", 18), 102 | maxCap: parseUnits("130", 18), 103 | }, 104 | { 105 | chainId: 137, // Polygon 106 | minCap: parseUnits("0.0039", 18), 107 | maxCap: parseUnits("130", 18), 108 | }, 109 | { 110 | chainId: 56, // Binance chain 111 | minCap: parseUnits("0.0039", 18), 112 | maxCap: parseUnits("130", 18), 113 | }, 114 | { 115 | chainId: 43114, // Avalanche 116 | minCap: parseUnits("0.0039", 18), 117 | maxCap: parseUnits("130", 18), 118 | }, 119 | { 120 | chainId: 10, // Optimism 121 | minCap: parseUnits("0.0039", 18), 122 | maxCap: parseUnits("130", 18), 123 | }, 124 | ], 125 | equilibriumFee: parseUnits("0.075", 8), 126 | maxFee: parseUnits("0.5", 8), 127 | transferOverhead: 59271, 128 | maxWalletLiquidityCap: parseUnits("0", 18), // not used 129 | maxLiquidityCap: parseUnits("445", 18), 130 | svgHelper: await ethers.getContractFactory("ArbitrumETH"), 131 | decimals: 18, 132 | rewardTokenAddress: "0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d", 133 | rewardRatePerSecond: parseUnits("0.001459", 18), 134 | excessStateTransferFeePer: parseUnits("0.045", 8), 135 | }, 136 | ], 137 | }; 138 | await deploy(config); 139 | })(); 140 | --------------------------------------------------------------------------------