├── .nvmrc ├── audits ├── ABDK_Gambit_Solidity.pdf ├── Quantstamp_Audit_Report.pdf ├── ABDK_Audit_Review.txt └── Quantstamp_Audit_Review.txt ├── data └── whitelist.js ├── test ├── shared │ ├── chainlink.js │ ├── units.js │ └── fixtures.js ├── core │ └── Vault │ │ └── vaultUtils.js └── tokens │ └── YieldFarm.js ├── contracts ├── access │ ├── interfaces │ │ └── IAdmin.sol │ └── Governable.sol ├── gmx │ ├── interfaces │ │ ├── IGmxIou.sol │ │ ├── IGmxMigrator.sol │ │ └── IAmmRouter.sol │ ├── GMX.sol │ ├── GLP.sol │ ├── EsGMX.sol │ └── GmxIou.sol ├── oracle │ ├── interfaces │ │ ├── IChainlinkFlags.sol │ │ ├── IFastPriceEvents.sol │ │ ├── ISecondaryPriceFeed.sol │ │ ├── IPriceFeed.sol │ │ └── IFastPriceFeed.sol │ ├── FastPriceEvents.sol │ └── PriceFeed.sol ├── amm │ ├── UniFactory.sol │ ├── interfaces │ │ ├── IPancakeFactory.sol │ │ ├── IPancakePair.sol │ │ └── IPancakeRouter.sol │ ├── PancakeFactory.sol │ ├── PancakePair.sol │ ├── PancakeRouter.sol │ ├── UniPool.sol │ └── UniNftManager.sol ├── gambit-token │ └── interfaces │ │ └── IGMT.sol ├── tokens │ ├── interfaces │ │ ├── IGLP.sol │ │ ├── IBridge.sol │ │ ├── IWETH.sol │ │ ├── IYieldToken.sol │ │ ├── IUSDG.sol │ │ ├── IMintable.sol │ │ ├── IYieldTracker.sol │ │ ├── IDistributor.sol │ │ └── IBaseToken.sol │ ├── SnapshotToken.sol │ ├── YieldFarm.sol │ ├── MintableBaseToken.sol │ ├── USDG.sol │ └── Bridge.sol ├── core │ ├── interfaces │ │ ├── IPositionRouterCallbackReceiver.sol │ │ ├── IBasePositionManager.sol │ │ ├── IRouter.sol │ │ ├── IPositionRouter.sol │ │ ├── IShortsTracker.sol │ │ ├── IGlpManager.sol │ │ ├── IOrderBook.sol │ │ ├── IVaultPriceFeed.sol │ │ └── IVaultUtils.sol │ ├── test │ │ ├── VaultTest.sol │ │ ├── PositionRouterCallbackReceiverTest.sol │ │ ├── ShortsTrackerTest.sol │ │ └── MaliciousTraderTest.sol │ └── VaultErrorController.sol ├── staking │ ├── interfaces │ │ ├── IRewardRouterV2.sol │ │ ├── IRewardDistributor.sol │ │ ├── IRewardTracker.sol │ │ └── IVester.sol │ ├── StakeManager.sol │ └── StakedGlpMigrator.sol ├── peripherals │ ├── interfaces │ │ ├── IHandlerTarget.sol │ │ ├── ITimelockTarget.sol │ │ ├── IGmxTimelock.sol │ │ └── ITimelock.sol │ ├── BalanceUpdater.sol │ ├── PositionRouterReader.sol │ ├── BatchSender.sol │ └── EsGmxBatchSender.sol ├── referrals │ ├── ReferralReader.sol │ └── interfaces │ │ └── IReferralStorage.sol └── libraries │ ├── math │ ├── UQ112x112.sol │ └── Math.sol │ ├── token │ └── ERC721 │ │ ├── IERC721Metadata.sol │ │ ├── IERC721Receiver.sol │ │ └── IERC721Enumerable.sol │ ├── introspection │ ├── IERC165.sol │ └── ERC165.sol │ ├── GSN │ └── Context.sol │ ├── utils │ └── Strings.sol │ └── access │ └── Ownable.sol ├── .editorconfig ├── scripts ├── staking │ ├── deployStakeManager.js │ ├── deployRewardManager.js │ ├── updateRewards.js │ ├── stakeForAccount.js │ ├── deployStakedGlpMigrator.js │ ├── checkStake.js │ ├── batchSendEsGmx.js │ ├── checkStakedAmounts.js │ ├── batchSetBonusRewards.js │ ├── deployGlpWrappers.js │ ├── removeRewardRouter.js │ └── deployGlpRewardRouter.js ├── access │ ├── deployGovernable.js │ └── deployTokenManager.js ├── gmx │ ├── deployGMX.js │ ├── deployTokens.js │ └── deployMigrationHandler.js ├── peripherals │ ├── deployBalanceUpdater.js │ ├── deployBatchSender.js │ ├── deployRewardReader.js │ ├── deployPositionReader.js │ ├── deployVaultReader.js │ ├── deployOrderBookReader.js │ ├── deployReader.js │ ├── deployEsGmxClaimTokens.js │ ├── updateFees.js │ ├── transfer.js │ ├── transferNFT.js │ ├── fundAccounts.js │ ├── printFeeCalculations.js │ ├── getList.js │ ├── getPairAmount.js │ ├── setGov.js │ ├── referralBatchSend.js │ ├── printFeeValues.js │ ├── serverFees.js │ ├── batchSend.js │ ├── deployGmxTimelock.js │ ├── deployShortsTrackerTimelock.js │ ├── setPriceFeed.js │ ├── deployPriceFeedTimelock.js │ ├── printUniswapLiquidity.js │ └── listSend.js ├── core │ ├── deployReferralReader.js │ ├── addPluginOrderBook.js │ ├── withdrawFees.js │ ├── removeVault.js │ ├── deployOrderExecutor.js │ ├── setVaultConfig.js │ ├── directPoolDeposit.js │ ├── deployVaultUtils.js │ ├── setSwapFees.js │ ├── deployOrderBook.js │ ├── checkAdjustments.js │ ├── setPrices.js │ ├── setAdjustments.js │ ├── removeGlpManager.js │ ├── upgradeVault.js │ ├── deployGlpManager.js │ ├── updatePositionRouterFee.js │ ├── setFees.js │ ├── deployShortsTracker.js │ ├── setTiersReferralStorage.js │ ├── setReferralCodeOwner.js │ ├── whitelistTokens.js │ ├── priceFeedSetTokenConfig.js │ ├── claimTokens.js │ ├── write.js │ ├── deployGlpManagerV2.js │ ├── deployReferralStorage.js │ ├── checkAmounts.js │ ├── setFastPriceEvents.js │ ├── vaultSetTokenConfig.js │ ├── setPriceFeedConfig.js │ ├── checkTokenConfigs.js │ ├── setSpread.js │ └── setReferralTier.js ├── gambit-token │ ├── deployGMT.js │ ├── addLiquidity.js │ ├── setupPresale.js │ ├── airdropGMT.js │ └── deployTreasury.js ├── tokens │ ├── deployXGMT.js │ ├── deployBridge.js │ ├── deploySnapshotToken.js │ ├── mint.js │ ├── deployTokens.js │ ├── mintSnapshotToken.js │ ├── deployAutoFarm.js │ └── addLiquidity.js └── referrals │ ├── printReferralRewards.js │ ├── batchSendReferralRewards.js │ ├── saveDistributionData.js │ └── getReferralRewards.js ├── README.md ├── .gitignore ├── package.json └── LICENSE /.nvmrc: -------------------------------------------------------------------------------- 1 | 16 2 | -------------------------------------------------------------------------------- /audits/ABDK_Gambit_Solidity.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bambum1488/gmx-contracts/HEAD/audits/ABDK_Gambit_Solidity.pdf -------------------------------------------------------------------------------- /audits/Quantstamp_Audit_Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bambum1488/gmx-contracts/HEAD/audits/Quantstamp_Audit_Report.pdf -------------------------------------------------------------------------------- /data/whitelist.js: -------------------------------------------------------------------------------- 1 | const WHITELIST = [] 2 | 3 | function getWhitelist() { 4 | return WHITELIST 5 | } 6 | 7 | module.exports = { getWhitelist } 8 | -------------------------------------------------------------------------------- /test/shared/chainlink.js: -------------------------------------------------------------------------------- 1 | function toChainlinkPrice(value) { 2 | return parseInt(value * Math.pow(10, 8)) 3 | } 4 | 5 | module.exports = { toChainlinkPrice } 6 | -------------------------------------------------------------------------------- /contracts/access/interfaces/IAdmin.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IAdmin { 6 | function setAdmin(address _admin) external; 7 | } 8 | -------------------------------------------------------------------------------- /contracts/gmx/interfaces/IGmxIou.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IGmxIou { 6 | function mint(address account, uint256 amount) external returns (bool); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/oracle/interfaces/IChainlinkFlags.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IChainlinkFlags { 6 | function getFlag(address) external view returns (bool); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/amm/UniFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | contract UniFactory { 6 | mapping(address => mapping(address => mapping(uint24 => address))) public getPool; 7 | } 8 | -------------------------------------------------------------------------------- /contracts/gmx/interfaces/IGmxMigrator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IGmxMigrator { 6 | function iouTokens(address _token) external view returns (address); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/gambit-token/interfaces/IGMT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IGMT { 6 | function beginMigration() external; 7 | function endMigration() external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/oracle/interfaces/IFastPriceEvents.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IFastPriceEvents { 6 | function emitPriceEvent(address _token, uint256 _price) external; 7 | } 8 | -------------------------------------------------------------------------------- /contracts/amm/interfaces/IPancakeFactory.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IPancakeFactory { 6 | function getPair(address tokenA, address tokenB) external view returns (address pair); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/amm/interfaces/IPancakePair.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.5.0; 4 | 5 | interface IPancakePair { 6 | function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/tokens/interfaces/IGLP.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IGLP { 6 | function mint(address _account, uint256 _amount) external; 7 | function burn(address _account, uint256 _amount) external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/oracle/interfaces/ISecondaryPriceFeed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface ISecondaryPriceFeed { 6 | function getPrice(address _token, uint256 _referencePrice, bool _maximise) external view returns (uint256); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/tokens/interfaces/IBridge.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IBridge { 6 | function wrap(uint256 _amount, address _receiver) external; 7 | function unwrap(uint256 _amount, address _receiver) external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/core/interfaces/IPositionRouterCallbackReceiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.0; 4 | 5 | interface IPositionRouterCallbackReceiver { 6 | function gmxPositionCallback(bytes32 positionKey, bool isExecuted, bool isIncrease) external; 7 | } 8 | -------------------------------------------------------------------------------- /contracts/staking/interfaces/IRewardRouterV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IRewardRouterV2 { 6 | function feeGlpTracker() external view returns (address); 7 | function stakedGlpTracker() external view returns (address); 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.sol] 12 | indent_size = 4 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /test/shared/units.js: -------------------------------------------------------------------------------- 1 | function toUsd(value) { 2 | const normalizedValue = parseInt(value * Math.pow(10, 10)) 3 | return ethers.BigNumber.from(normalizedValue).mul(ethers.BigNumber.from(10).pow(20)) 4 | } 5 | 6 | toNormalizedPrice = toUsd 7 | 8 | module.exports = { toUsd, toNormalizedPrice } 9 | -------------------------------------------------------------------------------- /contracts/peripherals/interfaces/IHandlerTarget.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IHandlerTarget { 6 | function isHandler(address _account) external returns (bool); 7 | function setHandler(address _handler, bool _isActive) external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/peripherals/interfaces/ITimelockTarget.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface ITimelockTarget { 6 | function setGov(address _gov) external; 7 | function withdrawToken(address _token, address _account, uint256 _amount) external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/tokens/interfaces/IWETH.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IWETH { 6 | function deposit() external payable; 7 | function transfer(address to, uint value) external returns (bool); 8 | function withdraw(uint) external; 9 | } 10 | -------------------------------------------------------------------------------- /scripts/staking/deployStakeManager.js: -------------------------------------------------------------------------------- 1 | const { deployContract } = require("../shared/helpers") 2 | 3 | async function main() { 4 | await deployContract("StakeManager", []) 5 | } 6 | 7 | main() 8 | .then(() => process.exit(0)) 9 | .catch(error => { 10 | console.error(error) 11 | process.exit(1) 12 | }) 13 | -------------------------------------------------------------------------------- /contracts/core/interfaces/IBasePositionManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IBasePositionManager { 6 | function maxGlobalLongSizes(address _token) external view returns (uint256); 7 | function maxGlobalShortSizes(address _token) external view returns (uint256); 8 | } 9 | -------------------------------------------------------------------------------- /contracts/core/test/VaultTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../Vault.sol"; 6 | 7 | contract VaultTest is Vault { 8 | function increaseGlobalShortSize(address token, uint256 amount) external { 9 | _increaseGlobalShortSize(token, amount); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /scripts/access/deployGovernable.js: -------------------------------------------------------------------------------- 1 | const { deployContract } = require("../shared/helpers") 2 | 3 | async function main() { 4 | await deployContract("Governable", [], "Governable") 5 | } 6 | 7 | main() 8 | .then(() => process.exit(0)) 9 | .catch(error => { 10 | console.error(error) 11 | process.exit(1) 12 | }) 13 | -------------------------------------------------------------------------------- /scripts/gmx/deployGMX.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | async function main() { 4 | await deployContract("GMX", []) 5 | } 6 | 7 | main() 8 | .then(() => process.exit(0)) 9 | .catch(error => { 10 | console.error(error) 11 | process.exit(1) 12 | }) 13 | -------------------------------------------------------------------------------- /scripts/peripherals/deployBalanceUpdater.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt } = require("../shared/helpers") 2 | 3 | async function main() { 4 | await deployContract("BalanceUpdater", []) 5 | } 6 | 7 | main() 8 | .then(() => process.exit(0)) 9 | .catch(error => { 10 | console.error(error) 11 | process.exit(1) 12 | }) 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GMX Contracts 2 | Contracts for GMX. 3 | 4 | Docs at https://gmxio.gitbook.io/gmx/contracts. 5 | 6 | ## Install Dependencies 7 | If npx is not installed yet: 8 | `npm install -g npx` 9 | 10 | Install packages: 11 | `npm i` 12 | 13 | ## Compile Contracts 14 | `npx hardhat compile` 15 | 16 | ## Run Tests 17 | `npx hardhat test` 18 | -------------------------------------------------------------------------------- /contracts/tokens/interfaces/IYieldToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IYieldToken { 6 | function totalStaked() external view returns (uint256); 7 | function stakedBalance(address _account) external view returns (uint256); 8 | function removeAdmin(address _account) external; 9 | } 10 | -------------------------------------------------------------------------------- /contracts/peripherals/interfaces/IGmxTimelock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IGmxTimelock { 6 | function setAdmin(address _admin) external; 7 | function setIsLeverageEnabled(address _vault, bool _isLeverageEnabled) external; 8 | function signalSetGov(address _target, address _gov) external; 9 | } 10 | -------------------------------------------------------------------------------- /scripts/staking/deployRewardManager.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | async function main() { 4 | await deployContract("RewardManager", [], "RewardManager") 5 | } 6 | 7 | main() 8 | .then(() => process.exit(0)) 9 | .catch(error => { 10 | console.error(error) 11 | process.exit(1) 12 | }) 13 | -------------------------------------------------------------------------------- /scripts/peripherals/deployBatchSender.js: -------------------------------------------------------------------------------- 1 | const { deployContract } = require("../shared/helpers") 2 | 3 | async function main() { 4 | const batchSender = await deployContract("BatchSender", []) 5 | return { batchSender } 6 | } 7 | 8 | main() 9 | .then(() => process.exit(0)) 10 | .catch(error => { 11 | console.error(error) 12 | process.exit(1) 13 | }) 14 | -------------------------------------------------------------------------------- /scripts/peripherals/deployRewardReader.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | async function main() { 4 | await deployContract("RewardReader", [], "RewardReader") 5 | } 6 | 7 | main() 8 | .then(() => process.exit(0)) 9 | .catch(error => { 10 | console.error(error) 11 | process.exit(1) 12 | }) 13 | -------------------------------------------------------------------------------- /contracts/gmx/GMX.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../tokens/MintableBaseToken.sol"; 6 | 7 | contract GMX is MintableBaseToken { 8 | constructor() public MintableBaseToken("GMX", "GMX", 0) { 9 | } 10 | 11 | function id() external pure returns (string memory _name) { 12 | return "GMX"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/tokens/interfaces/IUSDG.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IUSDG { 6 | function addVault(address _vault) external; 7 | function removeVault(address _vault) external; 8 | function mint(address _account, uint256 _amount) external; 9 | function burn(address _account, uint256 _amount) external; 10 | } 11 | -------------------------------------------------------------------------------- /contracts/gmx/GLP.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../tokens/MintableBaseToken.sol"; 6 | 7 | contract GLP is MintableBaseToken { 8 | constructor() public MintableBaseToken("GMX LP", "GLP", 0) { 9 | } 10 | 11 | function id() external pure returns (string memory _name) { 12 | return "GLP"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/gmx/EsGMX.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../tokens/MintableBaseToken.sol"; 6 | 7 | contract EsGMX is MintableBaseToken { 8 | constructor() public MintableBaseToken("Escrowed GMX", "esGMX", 0) { 9 | } 10 | 11 | function id() external pure returns (string memory _name) { 12 | return "esGMX"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /scripts/peripherals/deployPositionReader.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses, sendTxn } = require("../shared/helpers") 2 | 3 | async function main() { 4 | await deployContract("PositionRouterReader", [], "PositionRouterReader") 5 | } 6 | 7 | main() 8 | .then(() => process.exit(0)) 9 | .catch(error => { 10 | console.error(error) 11 | process.exit(1) 12 | }) 13 | -------------------------------------------------------------------------------- /contracts/tokens/interfaces/IMintable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IMintable { 6 | function isMinter(address _account) external returns (bool); 7 | function setMinter(address _minter, bool _isActive) external; 8 | function mint(address _account, uint256 _amount) external; 9 | function burn(address _account, uint256 _amount) external; 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .vscode 3 | typechain/ 4 | env.json 5 | .tmp-addresses*.json 6 | data/gmxMigration 7 | data/esGmxDistribution 8 | data/bonds 9 | data/batchSend 10 | data/nft 11 | data/snapshotBalance 12 | data/holders 13 | data/contractList 14 | flattened 15 | distribution-data*.json 16 | fee-reference.json 17 | uniswap-fee-reference.json 18 | **/.DS_Store 19 | 20 | #Hardhat files 21 | cache 22 | artifacts 23 | -------------------------------------------------------------------------------- /contracts/staking/interfaces/IRewardDistributor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IRewardDistributor { 6 | function rewardToken() external view returns (address); 7 | function tokensPerInterval() external view returns (uint256); 8 | function pendingRewards() external view returns (uint256); 9 | function distribute() external returns (uint256); 10 | } 11 | -------------------------------------------------------------------------------- /scripts/core/deployReferralReader.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses, sendTxn } = require("../shared/helpers") 2 | 3 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 4 | 5 | async function main() { 6 | await deployContract("ReferralReader", [], "ReferralReader") 7 | } 8 | 9 | main() 10 | .then(() => process.exit(0)) 11 | .catch(error => { 12 | console.error(error) 13 | process.exit(1) 14 | }) 15 | -------------------------------------------------------------------------------- /contracts/tokens/interfaces/IYieldTracker.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IYieldTracker { 6 | function claim(address _account, address _receiver) external returns (uint256); 7 | function updateRewards(address _account) external; 8 | function getTokensPerInterval() external view returns (uint256); 9 | function claimable(address _account) external view returns (uint256); 10 | } 11 | -------------------------------------------------------------------------------- /scripts/gmx/deployTokens.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | async function main() { 4 | // await deployContract("EsGMX", []) 5 | // await deployContract("GLP", []) 6 | await deployContract("MintableBaseToken", ["esGMX IOU", "esGMX:IOU", 0]) 7 | } 8 | 9 | main() 10 | .then(() => process.exit(0)) 11 | .catch(error => { 12 | console.error(error) 13 | process.exit(1) 14 | }) 15 | -------------------------------------------------------------------------------- /scripts/peripherals/deployVaultReader.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | async function main() { 4 | const contract = await deployContract("VaultReader", [], "VaultReader") 5 | 6 | writeTmpAddresses({ 7 | reader: contract.address 8 | }) 9 | } 10 | 11 | main() 12 | .then(() => process.exit(0)) 13 | .catch(error => { 14 | console.error(error) 15 | process.exit(1) 16 | }) 17 | -------------------------------------------------------------------------------- /contracts/access/Governable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | contract Governable { 6 | address public gov; 7 | 8 | constructor() public { 9 | gov = msg.sender; 10 | } 11 | 12 | modifier onlyGov() { 13 | require(msg.sender == gov, "Governable: forbidden"); 14 | _; 15 | } 16 | 17 | function setGov(address _gov) external onlyGov { 18 | gov = _gov; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /contracts/tokens/interfaces/IDistributor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IDistributor { 6 | function distribute() external returns (uint256); 7 | function getRewardToken(address _receiver) external view returns (address); 8 | function getDistributionAmount(address _receiver) external view returns (uint256); 9 | function tokensPerInterval(address _receiver) external view returns (uint256); 10 | } 11 | -------------------------------------------------------------------------------- /scripts/peripherals/deployOrderBookReader.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | async function main() { 4 | const orderBookReader = await deployContract("OrderBookReader", []) 5 | 6 | writeTmpAddresses({ 7 | orderBookReader: orderBookReader.address 8 | }) 9 | } 10 | 11 | main() 12 | .then(() => process.exit(0)) 13 | .catch(error => { 14 | console.error(error) 15 | process.exit(1) 16 | }) 17 | -------------------------------------------------------------------------------- /scripts/gambit-token/deployGMT.js: -------------------------------------------------------------------------------- 1 | const { deployContract } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const initialSupply = expandDecimals(401 * 1000, 18) 6 | const gmt = await deployContract("GMT", [initialSupply]) 7 | return { gmt } 8 | } 9 | 10 | main() 11 | .then(() => process.exit(0)) 12 | .catch(error => { 13 | console.error(error) 14 | process.exit(1) 15 | }) 16 | -------------------------------------------------------------------------------- /contracts/amm/interfaces/IPancakeRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IPancakeRouter { 6 | function addLiquidity( 7 | address tokenA, 8 | address tokenB, 9 | uint amountADesired, 10 | uint amountBDesired, 11 | uint amountAMin, 12 | uint amountBMin, 13 | address to, 14 | uint deadline 15 | ) external returns (uint amountA, uint amountB, uint liquidity); 16 | } 17 | -------------------------------------------------------------------------------- /scripts/tokens/deployXGMT.js: -------------------------------------------------------------------------------- 1 | const { deployContract } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const initialSupply = expandDecimals(100 * 1000, 18) 6 | const xgmt = await deployContract("YieldToken", ["xGambit", "xGMT", initialSupply]) 7 | return { xgmt } 8 | } 9 | 10 | main() 11 | .then(() => process.exit(0)) 12 | .catch(error => { 13 | console.error(error) 14 | process.exit(1) 15 | }) 16 | -------------------------------------------------------------------------------- /contracts/core/VaultErrorController.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | pragma experimental ABIEncoderV2; 5 | 6 | import "./interfaces/IVault.sol"; 7 | import "../access/Governable.sol"; 8 | 9 | contract VaultErrorController is Governable { 10 | function setErrors(IVault _vault, string[] calldata _errors) external onlyGov { 11 | for (uint256 i = 0; i < _errors.length; i++) { 12 | _vault.setError(i, _errors[i]); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /contracts/oracle/interfaces/IPriceFeed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IPriceFeed { 6 | function description() external view returns (string memory); 7 | function aggregator() external view returns (address); 8 | function latestAnswer() external view returns (int256); 9 | function latestRound() external view returns (uint80); 10 | function getRoundData(uint80 roundId) external view returns (uint80, int256, uint256, uint256, uint80); 11 | } 12 | -------------------------------------------------------------------------------- /contracts/tokens/interfaces/IBaseToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IBaseToken { 6 | function totalStaked() external view returns (uint256); 7 | function stakedBalance(address _account) external view returns (uint256); 8 | function removeAdmin(address _account) external; 9 | function setInPrivateTransferMode(bool _inPrivateTransferMode) external; 10 | function withdrawToken(address _token, address _account, uint256 _amount) external; 11 | } 12 | -------------------------------------------------------------------------------- /scripts/tokens/deployBridge.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | async function main() { 4 | const gmx = { address: "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a" } 5 | const wGmx = { address: "0x590020B1005b8b25f1a2C82c5f743c540dcfa24d" } 6 | await deployContract("Bridge", [gmx.address, wGmx.address], "Bridge") 7 | } 8 | 9 | main() 10 | .then(() => process.exit(0)) 11 | .catch(error => { 12 | console.error(error) 13 | process.exit(1) 14 | }) 15 | -------------------------------------------------------------------------------- /test/shared/fixtures.js: -------------------------------------------------------------------------------- 1 | const { expandDecimals } = require("./utilities") 2 | 3 | async function deployContract(name, args, options) { 4 | const contractFactory = await ethers.getContractFactory(name, options) 5 | return await contractFactory.deploy(...args) 6 | } 7 | 8 | async function contractAt(name, address) { 9 | const contractFactory = await ethers.getContractFactory(name) 10 | return await contractFactory.attach(address) 11 | } 12 | 13 | module.exports = { 14 | deployContract, 15 | contractAt 16 | } 17 | -------------------------------------------------------------------------------- /contracts/staking/StakeManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./interfaces/IRewardTracker.sol"; 6 | import "../access/Governable.sol"; 7 | 8 | contract StakeManager is Governable { 9 | function stakeForAccount( 10 | address _rewardTracker, 11 | address _account, 12 | address _token, 13 | uint256 _amount 14 | ) external onlyGov { 15 | IRewardTracker(_rewardTracker).stakeForAccount(_account, _account, _token, _amount); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/peripherals/interfaces/ITimelock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface ITimelock { 6 | function marginFeeBasisPoints() external returns (uint256); 7 | function setAdmin(address _admin) external; 8 | function enableLeverage(address _vault) external; 9 | function disableLeverage(address _vault) external; 10 | function setIsLeverageEnabled(address _vault, bool _isLeverageEnabled) external; 11 | function signalSetGov(address _target, address _gov) external; 12 | } 13 | -------------------------------------------------------------------------------- /scripts/gambit-token/addLiquidity.js: -------------------------------------------------------------------------------- 1 | const { contractAt, sendTxn } = require("../shared/helpers") 2 | 3 | async function main() { 4 | const treasury = await contractAt("Treasury", "0xa44E7252a0C137748F523F112644042E5987FfC7") 5 | const gmt = await contractAt("GMT", "0x99e92123eB77Bc8f999316f622e5222498438784") 6 | 7 | // await sendTxn(treasury.addLiquidity(), "treasury.addLiquidity") 8 | await sendTxn(gmt.endMigration(), "gmt.endMigration") 9 | } 10 | 11 | main() 12 | .then(() => process.exit(0)) 13 | .catch(error => { 14 | console.error(error) 15 | process.exit(1) 16 | }) 17 | -------------------------------------------------------------------------------- /contracts/core/test/PositionRouterCallbackReceiverTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.0; 4 | 5 | import "../interfaces/IPositionRouterCallbackReceiver.sol"; 6 | 7 | contract PositionRouterCallbackReceiverTest is IPositionRouterCallbackReceiver { 8 | event CallbackCalled( 9 | bytes32 positionKey, 10 | bool isExecuted, 11 | bool isIncrease 12 | ); 13 | 14 | function gmxPositionCallback(bytes32 positionKey, bool isExecuted, bool isIncrease) override external { 15 | emit CallbackCalled(positionKey, isExecuted, isIncrease); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scripts/tokens/deploySnapshotToken.js: -------------------------------------------------------------------------------- 1 | const { deployContract, sendTxn } = require("../shared/helpers") 2 | 3 | async function main() { 4 | const admin = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 5 | const token = await deployContract("SnapshotToken", ["GMX Snapshot 1", "GMX 1", 0]) 6 | await sendTxn(token.setInPrivateTransferMode(true), "token.setInPrivateTransferMode") 7 | await sendTxn(token.setMinter(admin.address, true), "token.setMinter") 8 | } 9 | 10 | main() 11 | .then(() => process.exit(0)) 12 | .catch(error => { 13 | console.error(error) 14 | process.exit(1) 15 | }) 16 | -------------------------------------------------------------------------------- /contracts/referrals/ReferralReader.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./interfaces/IReferralStorage.sol"; 6 | 7 | contract ReferralReader { 8 | function getCodeOwners(IReferralStorage _referralStorage, bytes32[] memory _codes) public view returns (address[] memory) { 9 | address[] memory owners = new address[](_codes.length); 10 | 11 | for (uint256 i = 0; i < _codes.length; i++) { 12 | bytes32 code = _codes[i]; 13 | owners[i] = _referralStorage.codeOwners(code); 14 | } 15 | 16 | return owners; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scripts/core/addPluginOrderBook.js: -------------------------------------------------------------------------------- 1 | const { contractAt , sendTxn, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const router = await callWithRetries(contractAt, ["Router", "0x526f42EA12E167E36E3De747187f53b6989d121A"]) 6 | 7 | await sendTxn(callWithRetries(router.addPlugin.bind(router), [ 8 | "0x84B1FEA4A2c1e0C07f34755ac4cf5aD26a07485d" 9 | ]), "router.addPlugin") 10 | } 11 | 12 | main() 13 | .then(() => process.exit(0)) 14 | .catch(error => { 15 | console.error(error) 16 | process.exit(1) 17 | }) 18 | -------------------------------------------------------------------------------- /scripts/peripherals/deployReader.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses, sendTxn } = require("../shared/helpers") 2 | 3 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 4 | 5 | async function main() { 6 | const reader = await deployContract("Reader", [], "Reader") 7 | 8 | if (network === "avax") { 9 | await sendTxn(reader.setConfig(true), "Reader.setConfig") 10 | } 11 | 12 | writeTmpAddresses({ 13 | reader: reader.address 14 | }) 15 | } 16 | 17 | main() 18 | .then(() => process.exit(0)) 19 | .catch(error => { 20 | console.error(error) 21 | process.exit(1) 22 | }) 23 | -------------------------------------------------------------------------------- /scripts/peripherals/deployEsGmxClaimTokens.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | async function main() { 4 | await deployContract("MintableBaseToken", ["VestingOption", "ARB:GMX", 0]) 5 | await deployContract("MintableBaseToken", ["VestingOption", "ARB:GLP", 0]) 6 | await deployContract("MintableBaseToken", ["VestingOption", "AVAX:GMX", 0]) 7 | await deployContract("MintableBaseToken", ["VestingOption", "AVAX:GLP", 0]) 8 | } 9 | 10 | main() 11 | .then(() => process.exit(0)) 12 | .catch(error => { 13 | console.error(error) 14 | process.exit(1) 15 | }) 16 | -------------------------------------------------------------------------------- /contracts/gmx/interfaces/IAmmRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IAmmRouter { 6 | function removeLiquidity( 7 | address tokenA, 8 | address tokenB, 9 | uint liquidity, 10 | uint amountAMin, 11 | uint amountBMin, 12 | address to, 13 | uint deadline 14 | ) external returns (uint amountA, uint amountB); 15 | 16 | function swapExactTokensForTokens( 17 | uint amountIn, 18 | uint amountOutMin, 19 | address[] calldata path, 20 | address to, 21 | uint deadline 22 | ) external returns (uint[] memory amounts); 23 | } 24 | -------------------------------------------------------------------------------- /scripts/tokens/mint.js: -------------------------------------------------------------------------------- 1 | const { readTmpAddresses, contractAt, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const account = (await ethers.getSigners())[0] 6 | const {BTC, ETH, USDC, USDT} = readTmpAddresses() 7 | 8 | for (const tokenAddress of [BTC, USDC, USDT]) { 9 | const amount = expandDecimals(100000, 18) 10 | console.log(`Minting ${amount} of tokens ${tokenAddress}`) 11 | const tokenContract = await contractAt("FaucetToken", tokenAddress) 12 | await callWithRetries(tokenContract.mint.bind(tokenContract), [account.address, amount]) 13 | } 14 | } 15 | 16 | main() -------------------------------------------------------------------------------- /contracts/tokens/SnapshotToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./MintableBaseToken.sol"; 6 | 7 | contract SnapshotToken is MintableBaseToken { 8 | constructor(string memory _name, string memory _symbol, uint256 _initialSupply) public MintableBaseToken(_name, _symbol, _initialSupply) { 9 | } 10 | 11 | function batchMint(address[] memory _accounts, uint256[] memory _amounts) external onlyMinter { 12 | for (uint256 i = 0; i < _accounts.length; i++) { 13 | address account = _accounts[i]; 14 | uint256 amount = _amounts[i]; 15 | _mint(account, amount); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/libraries/math/UQ112x112.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) 6 | 7 | // range: [0, 2**112 - 1] 8 | // resolution: 1 / 2**112 9 | 10 | library UQ112x112 { 11 | uint224 constant Q112 = 2**112; 12 | 13 | // encode a uint112 as a UQ112x112 14 | function encode(uint112 y) internal pure returns (uint224 z) { 15 | z = uint224(y) * Q112; // never overflows 16 | } 17 | 18 | // divide a UQ112x112 by a uint112, returning a UQ112x112 19 | function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { 20 | z = x / uint224(y); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /scripts/peripherals/updateFees.js: -------------------------------------------------------------------------------- 1 | const { getArbValues, getAvaxValues, postFees } = require("./updateFees") 2 | 3 | const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); 4 | 5 | async function getNetworkValues() { 6 | return [ 7 | await getArbValues(), 8 | await getAvaxValues() 9 | ] 10 | } 11 | 12 | async function main() { 13 | const networkValues = await getNetworkValues() 14 | for (let i = 0; i < networkValues.length; i++) { 15 | const { apiKey, feeUrl, feeUsd } = networkValues[i] 16 | await postFees({ 17 | apiKey, 18 | feeUrl, 19 | feeUsd, 20 | timestamp: Date.now() / 1000 21 | }) 22 | } 23 | } 24 | 25 | main() 26 | 27 | module.exports = { 28 | postFees 29 | } 30 | -------------------------------------------------------------------------------- /contracts/core/interfaces/IRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IRouter { 6 | function addPlugin(address _plugin) external; 7 | function pluginTransfer(address _token, address _account, address _receiver, uint256 _amount) external; 8 | function pluginIncreasePosition(address _account, address _collateralToken, address _indexToken, uint256 _sizeDelta, bool _isLong) external; 9 | function pluginDecreasePosition(address _account, address _collateralToken, address _indexToken, uint256 _collateralDelta, uint256 _sizeDelta, bool _isLong, address _receiver) external returns (uint256); 10 | function swap(address[] memory _path, uint256 _amountIn, uint256 _minOut, address _receiver) external; 11 | } 12 | -------------------------------------------------------------------------------- /contracts/libraries/math/Math.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | // a library for performing various math operations 6 | 7 | library Math { 8 | function min(uint x, uint y) internal pure returns (uint z) { 9 | z = x < y ? x : y; 10 | } 11 | 12 | // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) 13 | function sqrt(uint y) internal pure returns (uint z) { 14 | if (y > 3) { 15 | z = y; 16 | uint x = y / 2 + 1; 17 | while (x < z) { 18 | z = x; 19 | x = (y / x + x) / 2; 20 | } 21 | } else if (y != 0) { 22 | z = 1; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /scripts/core/withdrawFees.js: -------------------------------------------------------------------------------- 1 | const { withdrawFeesArb, withdrawFeesAvax, withdrawFeesBsc } = require("./feeWithdrawal") 2 | 3 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 4 | 5 | // time check to avoid invalid fee withdrawals 6 | const time = 1683679046 7 | 8 | if (Date.now() / 1000 > time + 10 * 60) { 9 | throw new Error("invalid time") 10 | } 11 | 12 | async function main() { 13 | if (network === "bsc") { 14 | await withdrawFeesBsc() 15 | return 16 | } 17 | 18 | if (network === "avax") { 19 | await withdrawFeesAvax() 20 | return 21 | } 22 | 23 | await withdrawFeesArb() 24 | } 25 | 26 | main() 27 | .then(() => process.exit(0)) 28 | .catch(error => { 29 | console.error(error) 30 | process.exit(1) 31 | }) 32 | -------------------------------------------------------------------------------- /scripts/staking/updateRewards.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, contractAt, sendTxn, updateTokensPerInterval } = require("../shared/helpers") 2 | 3 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 4 | 5 | const { getArbValues, getAvaxValues, updateRewards } 6 | 7 | function getValues(signer) { 8 | if (network === "arbitrum") { 9 | return getArbValues(signer) 10 | } 11 | 12 | if (network === "avax") { 13 | return getAvaxValues(signer) 14 | } 15 | } 16 | 17 | async function main() { 18 | const signer = await getFrameSigner() 19 | const values = await getValues(signer) 20 | await updateRewards({ signer, values }) 21 | } 22 | 23 | main() 24 | .then(() => process.exit(0)) 25 | .catch(error => { 26 | console.error(error) 27 | process.exit(1) 28 | }) 29 | -------------------------------------------------------------------------------- /scripts/peripherals/transfer.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const signer = await getFrameSigner() 6 | const receiver = "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" 7 | 8 | const tokenAddress = "0xff970a61a04b1ca14834a43f5de4533ebddb5cc8" 9 | const tokenDecimals = 6 10 | const tokenAmount = 10000 11 | 12 | const token = await contractAt("Token", tokenAddress, signer) 13 | await sendTxn(token.transfer(receiver, expandDecimals(tokenAmount, tokenDecimals)), "token.transfer") 14 | } 15 | 16 | main() 17 | .then(() => process.exit(0)) 18 | .catch(error => { 19 | console.error(error) 20 | process.exit(1) 21 | }) 22 | -------------------------------------------------------------------------------- /scripts/core/removeVault.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt , sendTxn, writeTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function main() { 9 | const usdg = await contractAt("USDG", "0x45096e7aA921f27590f8F19e457794EB09678141") 10 | const vault = await contractAt("Vault", "0xDE3590067c811b6F023b557ed45E4f1067859663") 11 | 12 | await sendTxn(usdg.removeVault(vault.address), "usdg.removeVault") 13 | } 14 | 15 | main() 16 | .then(() => process.exit(0)) 17 | .catch(error => { 18 | console.error(error) 19 | process.exit(1) 20 | }) 21 | -------------------------------------------------------------------------------- /scripts/gambit-token/setupPresale.js: -------------------------------------------------------------------------------- 1 | const { contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { getWhitelist } = require("../../data/whitelist") 4 | 5 | async function main() { 6 | const wallet = { address: "0x9f169c2189A2d975C18965DE985936361b4a9De9" } 7 | const gmt = await contractAt("GMT", "0x99e92123eB77Bc8f999316f622e5222498438784") 8 | const treasury = await contractAt("Treasury", "0xa44E7252a0C137748F523F112644042E5987FfC7") 9 | 10 | const hasActiveMigration = await gmt.hasActiveMigration() 11 | if (!hasActiveMigration) { 12 | throw new Error("GMT migration not started") 13 | } 14 | } 15 | 16 | main() 17 | .then(() => process.exit(0)) 18 | .catch(error => { 19 | console.error(error) 20 | process.exit(1) 21 | }) 22 | -------------------------------------------------------------------------------- /contracts/libraries/token/ERC721/IERC721Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.2; 4 | 5 | import "./IERC721.sol"; 6 | 7 | /** 8 | * @title ERC-721 Non-Fungible Token Standard, optional metadata extension 9 | * @dev See https://eips.ethereum.org/EIPS/eip-721 10 | */ 11 | interface IERC721Metadata is IERC721 { 12 | 13 | /** 14 | * @dev Returns the token collection name. 15 | */ 16 | function name() external view returns (string memory); 17 | 18 | /** 19 | * @dev Returns the token collection symbol. 20 | */ 21 | function symbol() external view returns (string memory); 22 | 23 | /** 24 | * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. 25 | */ 26 | function tokenURI(uint256 tokenId) external view returns (string memory); 27 | } 28 | -------------------------------------------------------------------------------- /contracts/oracle/FastPriceEvents.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | import "../libraries/math/SafeMath.sol"; 4 | 5 | import "./interfaces/IFastPriceEvents.sol"; 6 | import "../access/Governable.sol"; 7 | 8 | pragma solidity 0.6.12; 9 | 10 | contract FastPriceEvents is IFastPriceEvents, Governable { 11 | 12 | mapping (address => bool) public isPriceFeed; 13 | event PriceUpdate(address token, uint256 price, address priceFeed); 14 | 15 | function setIsPriceFeed(address _priceFeed, bool _isPriceFeed) external onlyGov { 16 | isPriceFeed[_priceFeed] = _isPriceFeed; 17 | } 18 | 19 | function emitPriceEvent(address _token, uint256 _price) external override { 20 | require(isPriceFeed[msg.sender], "FastPriceEvents: invalid sender"); 21 | emit PriceUpdate(_token, _price, msg.sender); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scripts/staking/stakeForAccount.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const wallet = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 6 | const gmx = await contractAt("GMX", "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a"); 7 | const rewardRouter = await contractAt("RewardRouter", "0xEa7fCb85802713Cb03291311C66d6012b23402ea") 8 | 9 | const account = "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" 10 | const amount = "1000000000000000000" 11 | 12 | await sendTxn(rewardRouter.stakeGmxForAccount(account, amount), `Stake for ${account}: ${amount}`) 13 | } 14 | 15 | main() 16 | .then(() => process.exit(0)) 17 | .catch(error => { 18 | console.error(error) 19 | process.exit(1) 20 | }) 21 | -------------------------------------------------------------------------------- /scripts/tokens/deployTokens.js: -------------------------------------------------------------------------------- 1 | const { deployContract, sendTxn, writeTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const addresses = {} 6 | addresses.BTC = (await callWithRetries(deployContract, ["FaucetToken", ["Bitcoin", "BTC", 18, expandDecimals(1000, 18)]])).address 7 | addresses.USDC = (await callWithRetries(deployContract, ["FaucetToken", ["USDC Coin", "USDC", 18, expandDecimals(1000, 18)]])).address 8 | addresses.USDT = (await callWithRetries(deployContract, ["FaucetToken", ["Tether", "USDT", 18, expandDecimals(1000, 18)]])).address 9 | 10 | writeTmpAddresses(addresses) 11 | } 12 | 13 | main() 14 | .then(() => process.exit(0)) 15 | .catch(error => { 16 | console.error(error) 17 | process.exit(1) 18 | }) 19 | -------------------------------------------------------------------------------- /scripts/core/deployOrderExecutor.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt , sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | const { errors } = require("../../test/core/Vault/helpers") 5 | 6 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 7 | const tokens = require('./tokens')[network]; 8 | 9 | async function main() { 10 | const vault = await contractAt("Vault", "0x489ee077994B6658eAfA855C308275EAd8097C4A") 11 | const orderBook = await contractAt("OrderBook", "0x09f77E8A13De9a35a7231028187e9fD5DB8a2ACB") 12 | await deployContract("OrderExecutor", [vault.address, orderBook.address]) 13 | } 14 | 15 | main() 16 | .then(() => process.exit(0)) 17 | .catch(error => { 18 | console.error(error) 19 | process.exit(1) 20 | }) 21 | -------------------------------------------------------------------------------- /scripts/access/deployTokenManager.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses, sendTxn } = require("../shared/helpers") 2 | 3 | async function main() { 4 | const tokenManager = await deployContract("TokenManager", [4], "TokenManager") 5 | 6 | const signers = [ 7 | "0x45e48668F090a3eD1C7961421c60Df4E66f693BD", // Dovey 8 | "0xD7941C4Ca57a511F21853Bbc7FBF8149d5eCb398", // G 9 | "0x881690382102106b00a99E3dB86056D0fC71eee6", // Han Wen 10 | "0x2e5d207a4c0f7e7c52f6622dcc6eb44bc0fe1a13", // Krunal Amin 11 | "0x6091646D0354b03DD1e9697D33A7341d8C93a6F5", // xhiroz 12 | "0xd6D5a4070C7CFE0b42bE83934Cc21104AbeF1AD5" // Bybit Security Team 13 | ] 14 | 15 | await sendTxn(tokenManager.initialize(signers), "tokenManager.initialize") 16 | } 17 | 18 | main() 19 | .then(() => process.exit(0)) 20 | .catch(error => { 21 | console.error(error) 22 | process.exit(1) 23 | }) 24 | -------------------------------------------------------------------------------- /scripts/core/setVaultConfig.js: -------------------------------------------------------------------------------- 1 | const { contractAt , sendTxn, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const vault = await callWithRetries(contractAt, ["Vault", "0xA4704fBfaf7c89511668052931Ba0f1816D2c9d3"]) 6 | 7 | await sendTxn(callWithRetries(vault.setFees.bind(vault), [ 8 | 10, // taxBasisPoints, 9 | 10, // stableTaxBasisPoints, 10 | 10, // mintBurnFeeBasisPoints, 11 | 10, // swapFeeBasisPoints, 12 | 10, // stableSwapFeeBasisPoints, 13 | 10, // marginFeeBasisPoints, 14 | expandDecimals(1, 30), // 1 USD, liquidationFeeUsd, 15 | 3600, // 1 hour, minProfitTime, 16 | true // hasDynamicFees 17 | ]), "vault.setFees") 18 | } 19 | 20 | main() 21 | .then(() => process.exit(0)) 22 | .catch(error => { 23 | console.error(error) 24 | process.exit(1) 25 | }) 26 | -------------------------------------------------------------------------------- /contracts/libraries/introspection/IERC165.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.0; 4 | 5 | /** 6 | * @dev Interface of the ERC165 standard, as defined in the 7 | * https://eips.ethereum.org/EIPS/eip-165[EIP]. 8 | * 9 | * Implementers can declare support of contract interfaces, which can then be 10 | * queried by others ({ERC165Checker}). 11 | * 12 | * For an implementation, see {ERC165}. 13 | */ 14 | interface IERC165 { 15 | /** 16 | * @dev Returns true if this contract implements the interface defined by 17 | * `interfaceId`. See the corresponding 18 | * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] 19 | * to learn more about how these ids are created. 20 | * 21 | * This function call must use less than 30 000 gas. 22 | */ 23 | function supportsInterface(bytes4 interfaceId) external view returns (bool); 24 | } 25 | -------------------------------------------------------------------------------- /contracts/referrals/interfaces/IReferralStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IReferralStorage { 6 | function codeOwners(bytes32 _code) external view returns (address); 7 | function traderReferralCodes(address _account) external view returns (bytes32); 8 | function referrerDiscountShares(address _account) external view returns (uint256); 9 | function referrerTiers(address _account) external view returns (uint256); 10 | function getTraderReferralInfo(address _account) external view returns (bytes32, address); 11 | function setTraderReferralCode(address _account, bytes32 _code) external; 12 | function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external; 13 | function setReferrerTier(address _referrer, uint256 _tierId) external; 14 | function govSetCodeOwner(bytes32 _code, address _newAccount) external; 15 | } 16 | -------------------------------------------------------------------------------- /scripts/core/directPoolDeposit.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | const tokens = require('./tokens')[network]; 6 | 7 | async function main() { 8 | const token = await contractAt("Token", "0x82af49447d8a07e3bd95bd0d56f35241523fbab1") 9 | const router = await contractAt("Router", "0xaBBc5F99639c9B6bCb58544ddf04EFA6802F4064") 10 | // const amount = expandDecimals(3000, 6) 11 | const amount = "300000000000000000" 12 | await sendTxn(token.approve(router.address, amount), "router.approve") 13 | await sendTxn(router.directPoolDeposit(token.address, amount), "router.directPoolDeposit") 14 | } 15 | 16 | main() 17 | .then(() => process.exit(0)) 18 | .catch(error => { 19 | console.error(error) 20 | process.exit(1) 21 | }) 22 | -------------------------------------------------------------------------------- /audits/ABDK_Audit_Review.txt: -------------------------------------------------------------------------------- 1 | The major issues raised in the ABDK Audit have been resolved. 2 | 3 | 1. CVF-42, CVF-51: The mentioned functions have been removed, the intention of these functions was to support future features. We have decided to keep the supported features compact, when new features are needed the new code will be sent for another audit 4 | 5 | 2. CVF-87: The function is meant to be re-callable, token whitelisting is currently controlled by a Timelock contract with a delay of 5 days: https://bscscan.com/address/0x330EeF6b9B1ea6EDd620C825c9919DC8b611d5d5 6 | 7 | 3. CVF-90: The returned value was not affecting any behaviour, but for correctness it has been fixed: https://github.com/xvi10/gambit-contracts/blob/master/contracts/core/Vault.sol#L310 8 | 9 | 4. CVF-130: The spread between prices is assumed to be small, it is large only if the prices are volatile, in which case, a larger spread is desirable to protect the assets in the system 10 | -------------------------------------------------------------------------------- /contracts/libraries/token/ERC721/IERC721Receiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.0; 4 | 5 | /** 6 | * @title ERC721 token receiver interface 7 | * @dev Interface for any contract that wants to support safeTransfers 8 | * from ERC721 asset contracts. 9 | */ 10 | interface IERC721Receiver { 11 | /** 12 | * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} 13 | * by `operator` from `from`, this function is called. 14 | * 15 | * It must return its Solidity selector to confirm the token transfer. 16 | * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. 17 | * 18 | * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. 19 | */ 20 | function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4); 21 | } 22 | -------------------------------------------------------------------------------- /contracts/amm/PancakeFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./interfaces/IPancakeFactory.sol"; 6 | 7 | contract PancakeFactory is IPancakeFactory { 8 | address public btc; 9 | address public bnb; 10 | address public busd; 11 | 12 | address public bnbBusdPair; 13 | address public btcBnbPair; 14 | 15 | constructor(address[] memory _addresses) public { 16 | btc = _addresses[0]; 17 | bnb = _addresses[1]; 18 | busd = _addresses[2]; 19 | 20 | bnbBusdPair = _addresses[3]; 21 | btcBnbPair = _addresses[4]; 22 | } 23 | 24 | function getPair(address tokenA, address tokenB) external override view returns (address) { 25 | if (tokenA == busd && tokenB == bnb) { 26 | return bnbBusdPair; 27 | } 28 | if (tokenA == bnb && tokenB == btc) { 29 | return btcBnbPair; 30 | } 31 | revert("Invalid tokens"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /contracts/amm/PancakePair.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./interfaces/IPancakePair.sol"; 6 | 7 | contract PancakePair is IPancakePair { 8 | uint112 private reserve0; // uses single storage slot, accessible via getReserves 9 | uint112 private reserve1; // uses single storage slot, accessible via getReserves 10 | uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves 11 | 12 | function setReserves(uint256 balance0, uint256 balance1) external { 13 | reserve0 = uint112(balance0); 14 | reserve1 = uint112(balance1); 15 | blockTimestampLast = uint32(block.timestamp); 16 | } 17 | 18 | function getReserves() public override view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) { 19 | _reserve0 = reserve0; 20 | _reserve1 = reserve1; 21 | _blockTimestampLast = blockTimestampLast; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/tokens/YieldFarm.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../libraries/token/IERC20.sol"; 6 | import "../libraries/token/SafeERC20.sol"; 7 | import "../libraries/utils/ReentrancyGuard.sol"; 8 | 9 | import "./YieldToken.sol"; 10 | 11 | contract YieldFarm is YieldToken, ReentrancyGuard { 12 | using SafeERC20 for IERC20; 13 | 14 | address public stakingToken; 15 | 16 | constructor(string memory _name, string memory _symbol, address _stakingToken) public YieldToken(_name, _symbol, 0) { 17 | stakingToken = _stakingToken; 18 | } 19 | 20 | function stake(uint256 _amount) external nonReentrant { 21 | IERC20(stakingToken).safeTransferFrom(msg.sender, address(this), _amount); 22 | _mint(msg.sender, _amount); 23 | } 24 | 25 | function unstake(uint256 _amount) external nonReentrant { 26 | _burn(msg.sender, _amount); 27 | IERC20(stakingToken).safeTransfer(msg.sender, _amount); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /scripts/core/deployVaultUtils.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt , sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | const { errors } = require("../../test/core/Vault/helpers") 5 | 6 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 7 | const tokens = require('./tokens')[network]; 8 | 9 | async function main() { 10 | const signer = await getFrameSigner() 11 | const vault = await contractAt("Vault", "0x9ab2De34A33fB459b538c43f251eB825645e8595") 12 | const timelock = await contractAt("Timelock", await vault.gov(), signer) 13 | const vaultUtils = await deployContract("VaultUtils", [vault.address]) 14 | await sendTxn(timelock.setVaultUtils(vault.address, vaultUtils.address), "timelock.setVaultUtils") 15 | } 16 | 17 | main() 18 | .then(() => process.exit(0)) 19 | .catch(error => { 20 | console.error(error) 21 | process.exit(1) 22 | }) 23 | -------------------------------------------------------------------------------- /contracts/core/interfaces/IPositionRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IPositionRouter { 6 | function increasePositionRequestKeysStart() external view returns (uint256); 7 | function decreasePositionRequestKeysStart() external view returns (uint256); 8 | function increasePositionRequestKeys(uint256 index) external view returns (bytes32); 9 | function decreasePositionRequestKeys(uint256 index) external view returns (bytes32); 10 | function executeIncreasePositions(uint256 _count, address payable _executionFeeReceiver) external; 11 | function executeDecreasePositions(uint256 _count, address payable _executionFeeReceiver) external; 12 | function getRequestQueueLengths() external view returns (uint256, uint256, uint256, uint256); 13 | function getIncreasePositionRequestPath(bytes32 _key) external view returns (address[] memory); 14 | function getDecreasePositionRequestPath(bytes32 _key) external view returns (address[] memory); 15 | } 16 | -------------------------------------------------------------------------------- /scripts/core/setSwapFees.js: -------------------------------------------------------------------------------- 1 | const { contractAt , sendTxn } = require("../shared/helpers") 2 | 3 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 4 | 5 | async function main() { 6 | let vault 7 | if (network === "avax") { 8 | vault = await contractAt("Vault", "0x9ab2De34A33fB459b538c43f251eB825645e8595") 9 | } 10 | if (network === "arbitrum") { 11 | vault = await contractAt("Vault", "0x489ee077994B6658eAfA855C308275EAd8097C4A") 12 | } 13 | 14 | const timelock = await contractAt("Timelock", await vault.gov()) 15 | console.log("timelock", timelock.address) 16 | 17 | await sendTxn(timelock.setSwapFees( 18 | vault.address, 19 | 60, // _taxBasisPoints 20 | 5, // _stableTaxBasisPoints 21 | 25, // _mintBurnFeeBasisPoints 22 | 25, // _swapFeeBasisPoints 23 | 1, // _stableSwapFeeBasisPoints 24 | ), "vault.setSwapFees") 25 | } 26 | 27 | main() 28 | .then(() => process.exit(0)) 29 | .catch(error => { 30 | console.error(error) 31 | process.exit(1) 32 | }) 33 | -------------------------------------------------------------------------------- /contracts/peripherals/BalanceUpdater.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../libraries/token/IERC20.sol"; 6 | import "../libraries/math/SafeMath.sol"; 7 | import "../core/interfaces/IVault.sol"; 8 | 9 | contract BalanceUpdater { 10 | using SafeMath for uint256; 11 | 12 | function updateBalance( 13 | address _vault, 14 | address _token, 15 | address _usdg, 16 | uint256 _usdgAmount 17 | ) public { 18 | IVault vault = IVault(_vault); 19 | IERC20 token = IERC20(_token); 20 | uint256 poolAmount = vault.poolAmounts(_token); 21 | uint256 fee = vault.feeReserves(_token); 22 | uint256 balance = token.balanceOf(_vault); 23 | 24 | uint256 transferAmount = poolAmount.add(fee).sub(balance); 25 | token.transferFrom(msg.sender, _vault, transferAmount); 26 | IERC20(_usdg).transferFrom(msg.sender, _vault, _usdgAmount); 27 | 28 | vault.sellUSDG(_token, msg.sender); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /contracts/tokens/MintableBaseToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./BaseToken.sol"; 6 | import "./interfaces/IMintable.sol"; 7 | 8 | contract MintableBaseToken is BaseToken, IMintable { 9 | 10 | mapping (address => bool) public override isMinter; 11 | 12 | constructor(string memory _name, string memory _symbol, uint256 _initialSupply) public BaseToken(_name, _symbol, _initialSupply) { 13 | } 14 | 15 | modifier onlyMinter() { 16 | require(isMinter[msg.sender], "MintableBaseToken: forbidden"); 17 | _; 18 | } 19 | 20 | function setMinter(address _minter, bool _isActive) external override onlyGov { 21 | isMinter[_minter] = _isActive; 22 | } 23 | 24 | function mint(address _account, uint256 _amount) external override onlyMinter { 25 | _mint(_account, _amount); 26 | } 27 | 28 | function burn(address _account, uint256 _amount) external override onlyMinter { 29 | _burn(_account, _amount); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/core/interfaces/IShortsTracker.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IShortsTracker { 6 | function isGlobalShortDataReady() external view returns (bool); 7 | function globalShortAveragePrices(address _token) external view returns (uint256); 8 | function getNextGlobalShortData( 9 | address _account, 10 | address _collateralToken, 11 | address _indexToken, 12 | uint256 _nextPrice, 13 | uint256 _sizeDelta, 14 | bool _isIncrease 15 | ) external view returns (uint256, uint256); 16 | function updateGlobalShortData( 17 | address _account, 18 | address _collateralToken, 19 | address _indexToken, 20 | bool _isLong, 21 | uint256 _sizeDelta, 22 | uint256 _markPrice, 23 | bool _isIncrease 24 | ) external; 25 | function setIsGlobalShortDataReady(bool value) external; 26 | function setInitData(address[] calldata _tokens, uint256[] calldata _averagePrices) external; 27 | } 28 | -------------------------------------------------------------------------------- /contracts/tokens/USDG.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./interfaces/IUSDG.sol"; 6 | import "./YieldToken.sol"; 7 | 8 | contract USDG is YieldToken, IUSDG { 9 | 10 | mapping (address => bool) public vaults; 11 | 12 | modifier onlyVault() { 13 | require(vaults[msg.sender], "USDG: forbidden"); 14 | _; 15 | } 16 | 17 | constructor(address _vault) public YieldToken("USD Gambit", "USDG", 0) { 18 | vaults[_vault] = true; 19 | } 20 | 21 | function addVault(address _vault) external override onlyGov { 22 | vaults[_vault] = true; 23 | } 24 | 25 | function removeVault(address _vault) external override onlyGov { 26 | vaults[_vault] = false; 27 | } 28 | 29 | function mint(address _account, uint256 _amount) external override onlyVault { 30 | _mint(_account, _amount); 31 | } 32 | 33 | function burn(address _account, uint256 _amount) external override onlyVault { 34 | _burn(_account, _amount); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts/libraries/GSN/Context.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | /* 6 | * @dev Provides information about the current execution context, including the 7 | * sender of the transaction and its data. While these are generally available 8 | * via msg.sender and msg.data, they should not be accessed in such a direct 9 | * manner, since when dealing with GSN meta-transactions the account sending and 10 | * paying for execution may not be the actual sender (as far as an application 11 | * is concerned). 12 | * 13 | * This contract is only required for intermediate, library-like contracts. 14 | */ 15 | abstract contract Context { 16 | function _msgSender() internal view virtual returns (address payable) { 17 | return msg.sender; 18 | } 19 | 20 | function _msgData() internal view virtual returns (bytes memory) { 21 | this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 22 | return msg.data; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gmx-contracts", 3 | "version": "1.0.0", 4 | "description": "", 5 | "files": [ 6 | "contracts/**/*.sol" 7 | ], 8 | "scripts": { 9 | "test": "npx hardhat test", 10 | "compile": "hardhat compile", 11 | "typechain": "hardhat typechain" 12 | }, 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "@nomiclabs/hardhat-ethers": "^2.0.1", 17 | "@nomiclabs/hardhat-etherscan": "^3.0.3", 18 | "@nomiclabs/hardhat-waffle": "^2.0.1", 19 | "@typechain/ethers-v5": "^7.0.1", 20 | "@typechain/hardhat": "^2.3.0", 21 | "argparse": "2.0.1", 22 | "chai": "^4.3.0", 23 | "ethereum-waffle": "^3.4.4", 24 | "ethers": "^5.4.6", 25 | "hardhat": "^2.6.1", 26 | "hardhat-contract-sizer": "^2.0.3", 27 | "node-fetch": "3.2.3", 28 | "typechain": "^5.1.2" 29 | }, 30 | "dependencies": { 31 | "@synapseprotocol/sdk": "^0.94.1", 32 | "@uniswap/sdk-core": "^3.0.1", 33 | "@uniswap/v3-sdk": "^3.8.2", 34 | "bn.js": "^5.2.0", 35 | "csv-parse": "^4.16.3" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /contracts/libraries/token/ERC721/IERC721Enumerable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.2; 4 | 5 | import "./IERC721.sol"; 6 | 7 | /** 8 | * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension 9 | * @dev See https://eips.ethereum.org/EIPS/eip-721 10 | */ 11 | interface IERC721Enumerable is IERC721 { 12 | 13 | /** 14 | * @dev Returns the total amount of tokens stored by the contract. 15 | */ 16 | function totalSupply() external view returns (uint256); 17 | 18 | /** 19 | * @dev Returns a token ID owned by `owner` at a given `index` of its token list. 20 | * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. 21 | */ 22 | function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); 23 | 24 | /** 25 | * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. 26 | * Use along with {totalSupply} to enumerate all tokens. 27 | */ 28 | function tokenByIndex(uint256 index) external view returns (uint256); 29 | } 30 | -------------------------------------------------------------------------------- /contracts/libraries/utils/Strings.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.0; 4 | 5 | /** 6 | * @dev String operations. 7 | */ 8 | library Strings { 9 | /** 10 | * @dev Converts a `uint256` to its ASCII `string` representation. 11 | */ 12 | function toString(uint256 value) internal pure returns (string memory) { 13 | // Inspired by OraclizeAPI's implementation - MIT licence 14 | // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol 15 | 16 | if (value == 0) { 17 | return "0"; 18 | } 19 | uint256 temp = value; 20 | uint256 digits; 21 | while (temp != 0) { 22 | digits++; 23 | temp /= 10; 24 | } 25 | bytes memory buffer = new bytes(digits); 26 | uint256 index = digits - 1; 27 | temp = value; 28 | while (temp != 0) { 29 | buffer[index--] = byte(uint8(48 + temp % 10)); 30 | temp /= 10; 31 | } 32 | return string(buffer); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /scripts/core/deployOrderBook.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt , sendTxn, writeTmpAddresses } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | const tokens = require('./tokens')[network]; 6 | 7 | async function main() { 8 | const { nativeToken } = tokens 9 | 10 | const orderBook = await deployContract("OrderBook", []); 11 | 12 | // Arbitrum mainnet addresses 13 | await sendTxn(orderBook.initialize( 14 | "0x5F719c2F1095F7B9fc68a68e35B51194f4b6abe8", // router 15 | "0x9ab2De34A33fB459b538c43f251eB825645e8595", // vault 16 | nativeToken.address, // weth 17 | "0xc0253c3cC6aa5Ab407b5795a04c28fB063273894", // usdg 18 | "10000000000000000", // 0.01 AVAX 19 | expandDecimals(10, 30) // min purchase token amount usd 20 | ), "orderBook.initialize"); 21 | 22 | writeTmpAddresses({ 23 | orderBook: orderBook.address 24 | }) 25 | } 26 | 27 | main() 28 | .then(() => process.exit(0)) 29 | .catch(error => { 30 | console.error(error) 31 | process.exit(1) 32 | }) 33 | -------------------------------------------------------------------------------- /scripts/referrals/printReferralRewards.js: -------------------------------------------------------------------------------- 1 | const { getArbValues, getAvaxValues, getReferralRewardsInfo } = require("./getReferralRewards") 2 | 3 | async function getNetworkValues() { 4 | return [ 5 | await getArbValues(), 6 | await getAvaxValues() 7 | ] 8 | } 9 | 10 | async function main() { 11 | const wallet = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 12 | const values = await getNetworkValues() 13 | 14 | let totalAffiliateUsd = bigNumberify(0) 15 | let totalDiscountUsd = bigNumberify(0) 16 | 17 | for (let i = 0; i < values.length; i++) { 18 | const { data } = values[i] 19 | const rewardsInfo = getReferralRewardsInfo(data) 20 | totalAffiliateUsd = totalAffiliateUsd.add(rewardsInfo.allAffiliateUsd) 21 | totalDiscountUsd = totalDiscountUsd.add(rewardsInfo.allDiscountUsd) 22 | } 23 | 24 | console.log("Trader Rebates:", ethers.utils.formatUnits(totalDiscountUsd, 30)) 25 | console.log("Affiliate Rewards:", ethers.utils.formatUnits(totalAffiliateUsd, 30)) 26 | } 27 | 28 | main() 29 | .then(() => process.exit(0)) 30 | .catch(error => { 31 | console.error(error) 32 | process.exit(1) 33 | }) 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2020 zOS Global Limited 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /scripts/core/checkAdjustments.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt , sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function main() { 9 | const gov = await contractAt("Timelock", "0xa870b459ba1f206bbcb0df90ef887b19fcde66ae") 10 | const vaultPriceFeed = await contractAt("VaultPriceFeed", "0x82b1fa2741a6591d30e61830b1cfda0e7ba3abd3") 11 | const tokenKeys = ["btc", "eth", "bnb"] 12 | 13 | for (let i = 0; i < tokenKeys.length; i++) { 14 | const key = tokenKeys[i] 15 | const token = tokens[key] 16 | const adjustmentBasisPoints = await vaultPriceFeed.adjustmentBasisPoints(token.address) 17 | const isAdditive = await vaultPriceFeed.isAdjustmentAdditive(token.address) 18 | 19 | console.log(`${key}: ${isAdditive ? "+" : "-"}${adjustmentBasisPoints}`) 20 | } 21 | } 22 | 23 | main() 24 | .then(() => process.exit(0)) 25 | .catch(error => { 26 | console.error(error) 27 | process.exit(1) 28 | }) 29 | -------------------------------------------------------------------------------- /contracts/amm/PancakeRouter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../tokens/Token.sol"; 6 | import "../libraries/token/IERC20.sol"; 7 | import "./interfaces/IPancakeRouter.sol"; 8 | 9 | contract PancakeRouter is IPancakeRouter { 10 | address public pair; 11 | 12 | constructor(address _pair) public { 13 | pair = _pair; 14 | } 15 | 16 | function addLiquidity( 17 | address tokenA, 18 | address tokenB, 19 | uint256 amountADesired, 20 | uint256 amountBDesired, 21 | uint256 /*amountAMin*/, 22 | uint256 /*amountBMin*/, 23 | address to, 24 | uint256 deadline 25 | ) external override returns (uint256 amountA, uint256 amountB, uint256 liquidity) { 26 | require(deadline >= block.timestamp, 'PancakeRouter: EXPIRED'); 27 | 28 | Token(pair).mint(to, 1000); 29 | 30 | IERC20(tokenA).transferFrom(msg.sender, pair, amountADesired); 31 | IERC20(tokenB).transferFrom(msg.sender, pair, amountBDesired); 32 | 33 | amountA = amountADesired; 34 | amountB = amountBDesired; 35 | liquidity = 1000; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /scripts/core/setPrices.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt , sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function main() { 9 | const secondaryPriceFeed = await contractAt("FastPriceFeed", "0x06588aad1eCc1275CBF68ab192257714ac1ed89c") 10 | const vaultPriceFeed = await contractAt("VaultPriceFeed", "0x82B1Fa2741a6591D30E61830b1CfDA0E7ba3ABd3") 11 | 12 | // await sendTxn(vaultPriceFeed.setIsAmmEnabled(false), "vaultPriceFeed.setIsAmmEnabled") 13 | // console.log("vaultPriceFeed.isSecondaryPriceEnabled", await vaultPriceFeed.isSecondaryPriceEnabled()) 14 | 15 | await sendTxn(secondaryPriceFeed.setPrices( 16 | [tokens.btc.address, tokens.eth.address, tokens.bnb.address], 17 | [expandDecimals(35000, 30), expandDecimals(4000, 30), expandDecimals(310, 30)] 18 | ), "secondaryPriceFeed.setPrices") 19 | } 20 | 21 | main() 22 | .then(() => process.exit(0)) 23 | .catch(error => { 24 | console.error(error) 25 | process.exit(1) 26 | }) 27 | -------------------------------------------------------------------------------- /scripts/core/setAdjustments.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt , sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function main() { 9 | const gov = await contractAt("Timelock", "0xa870b459ba1f206bbcb0df90ef887b19fcde66ae") 10 | const vaultPriceFeed = await contractAt("VaultPriceFeed", "0x82b1fa2741a6591d30e61830b1cfda0e7ba3abd3") 11 | 12 | await sendTxn(gov.setAdjustment( 13 | vaultPriceFeed.address, 14 | tokens.btc.address, 15 | false, 16 | 0 17 | ), "gov.setAdjustment(btc)") 18 | 19 | await sendTxn(gov.setAdjustment( 20 | vaultPriceFeed.address, 21 | tokens.eth.address, 22 | false, 23 | 0 24 | ), "gov.setAdjustment(eth)") 25 | 26 | await sendTxn(gov.setAdjustment( 27 | vaultPriceFeed.address, 28 | tokens.bnb.address, 29 | false, 30 | 0 31 | ), "gov.setAdjustment(bnb)") 32 | } 33 | 34 | main() 35 | .then(() => process.exit(0)) 36 | .catch(error => { 37 | console.error(error) 38 | process.exit(1) 39 | }) 40 | -------------------------------------------------------------------------------- /scripts/core/removeGlpManager.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt , sendTxn, writeTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function main() { 9 | const { 10 | nativeToken 11 | } = tokens 12 | 13 | const vault = await contractAt("Vault", "0xDE3590067c811b6F023b557ed45E4f1067859663") 14 | const usdg = await contractAt("USDG", "0x45096e7aA921f27590f8F19e457794EB09678141") 15 | const glp = await contractAt("GLP", "0x4277f8F2c384827B5273592FF7CeBd9f2C1ac258") 16 | 17 | const glpManager = await contractAt("GlpManager", "0x91425Ac4431d068980d497924DD540Ae274f3270") 18 | 19 | await sendTxn(glp.setMinter(glpManager.address, false), "glp.setMinter") 20 | await sendTxn(usdg.removeVault(glpManager.address), "usdg.removeVault") 21 | await sendTxn(vault.setManager(glpManager.address, false), "vault.setManager") 22 | } 23 | 24 | main() 25 | .then(() => process.exit(0)) 26 | .catch(error => { 27 | console.error(error) 28 | process.exit(1) 29 | }) 30 | -------------------------------------------------------------------------------- /scripts/gmx/deployMigrationHandler.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | async function main() { 4 | const ammRouterV1 = { address: "0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F" } 5 | const ammRouterV2 = { address: "0x10ED43C718714eb63d5aA57B78B54704E256024E" } 6 | const vault = { address: "0xc73A8DcAc88498FD4b4B1b2AaA37b0a2614Ff67B" } 7 | const gmt = { address: "0x99e92123eB77Bc8f999316f622e5222498438784" } 8 | const xgmt = { address: "0xe304ff0983922787Fd84BC9170CD21bF78B16B10" } 9 | const usdg = { address: "0x85E76cbf4893c1fbcB34dCF1239A91CE2A4CF5a7" } 10 | const busd = { address: "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56" } 11 | const bnb = { address: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c" } 12 | 13 | const migrationHandler = await deployContract("MigrationHandler", []) 14 | 15 | await migrationHandler.initialize( 16 | ammRouterV1.address, 17 | ammRouterV2.address, 18 | vault.address, 19 | gmt.address, 20 | xgmt.address, 21 | usdg.address, 22 | bnb.address, 23 | busd.address 24 | ) 25 | } 26 | 27 | main() 28 | .then(() => process.exit(0)) 29 | .catch(error => { 30 | console.error(error) 31 | process.exit(1) 32 | }) 33 | -------------------------------------------------------------------------------- /scripts/staking/deployStakedGlpMigrator.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt, sendTxn, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 4 | 5 | async function getArbValues() { 6 | const glp = { address: "0x4277f8F2c384827B5273592FF7CeBd9f2C1ac258" } 7 | const stakedGlpTracker = await contractAt("RewardTracker", "0x1aDDD80E6039594eE970E5872D247bf0414C8903") 8 | const feeGlpTracker = await contractAt("RewardTracker", "0x4e971a87900b931fF39d1Aad67697F49835400b6") 9 | 10 | return { glp, stakedGlpTracker, feeGlpTracker } 11 | } 12 | 13 | async function getValues() { 14 | if (network === "arbitrum") { 15 | return getArbValues() 16 | } 17 | } 18 | 19 | async function main() { 20 | const { glp, stakedGlpTracker, feeGlpTracker } = await getValues() 21 | const sender = { address: "0xA7Ce4434A29549864a46fcE8662fD671c06BA49a" } 22 | 23 | await deployContract("StakedGlpMigrator", [ 24 | sender.address, 25 | glp.address, 26 | stakedGlpTracker.address, 27 | feeGlpTracker.address 28 | ]) 29 | } 30 | 31 | main() 32 | .then(() => process.exit(0)) 33 | .catch(error => { 34 | console.error(error) 35 | process.exit(1) 36 | }) 37 | -------------------------------------------------------------------------------- /contracts/staking/interfaces/IRewardTracker.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IRewardTracker { 6 | function depositBalances(address _account, address _depositToken) external view returns (uint256); 7 | function stakedAmounts(address _account) external view returns (uint256); 8 | function updateRewards() external; 9 | function stake(address _depositToken, uint256 _amount) external; 10 | function stakeForAccount(address _fundingAccount, address _account, address _depositToken, uint256 _amount) external; 11 | function unstake(address _depositToken, uint256 _amount) external; 12 | function unstakeForAccount(address _account, address _depositToken, uint256 _amount, address _receiver) external; 13 | function tokensPerInterval() external view returns (uint256); 14 | function claim(address _receiver) external returns (uint256); 15 | function claimForAccount(address _account, address _receiver) external returns (uint256); 16 | function claimable(address _account) external view returns (uint256); 17 | function averageStakedAmounts(address _account) external view returns (uint256); 18 | function cumulativeRewards(address _account) external view returns (uint256); 19 | } 20 | -------------------------------------------------------------------------------- /test/core/Vault/vaultUtils.js: -------------------------------------------------------------------------------- 1 | const { expect, use } = require("chai") 2 | const { solidity } = require("ethereum-waffle") 3 | const { deployContract } = require("../../shared/fixtures") 4 | const { expandDecimals, getBlockTime, increaseTime, mineBlock, reportGasUsed } = require("../../shared/utilities") 5 | const { toChainlinkPrice } = require("../../shared/chainlink") 6 | const { toUsd, toNormalizedPrice } = require("../../shared/units") 7 | const { initVault, getBnbConfig, getBtcConfig, getDaiConfig } = require("./helpers") 8 | 9 | describe("VaultUtils", function () { 10 | const provider = waffle.provider 11 | const [wallet, user0] = provider.getWallets() 12 | let vault 13 | let vaultUtils 14 | let vaultPriceFeed 15 | let usdg 16 | let router 17 | let bnb 18 | 19 | beforeEach(async () => { 20 | bnb = await deployContract("Token", []) 21 | 22 | vault = await deployContract("Vault", []) 23 | usdg = await deployContract("USDG", [vault.address]) 24 | router = await deployContract("Router", [vault.address, usdg.address, bnb.address]) 25 | vaultPriceFeed = await deployContract("VaultPriceFeed", []) 26 | 27 | const _ = await initVault(vault, router, usdg, vaultPriceFeed) 28 | vaultUtils = _.vaultUtils 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /contracts/oracle/interfaces/IFastPriceFeed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IFastPriceFeed { 6 | function lastUpdatedAt() external view returns (uint256); 7 | function lastUpdatedBlock() external view returns (uint256); 8 | function setSigner(address _account, bool _isActive) external; 9 | function setUpdater(address _account, bool _isActive) external; 10 | function setPriceDuration(uint256 _priceDuration) external; 11 | function setMaxPriceUpdateDelay(uint256 _maxPriceUpdateDelay) external; 12 | function setSpreadBasisPointsIfInactive(uint256 _spreadBasisPointsIfInactive) external; 13 | function setSpreadBasisPointsIfChainError(uint256 _spreadBasisPointsIfChainError) external; 14 | function setMinBlockInterval(uint256 _minBlockInterval) external; 15 | function setIsSpreadEnabled(bool _isSpreadEnabled) external; 16 | function setMaxDeviationBasisPoints(uint256 _maxDeviationBasisPoints) external; 17 | function setMaxCumulativeDeltaDiffs(address[] memory _tokens, uint256[] memory _maxCumulativeDeltaDiffs) external; 18 | function setPriceDataInterval(uint256 _priceDataInterval) external; 19 | function setVaultPriceFeed(address _vaultPriceFeed) external; 20 | } 21 | -------------------------------------------------------------------------------- /scripts/gambit-token/airdropGMT.js: -------------------------------------------------------------------------------- 1 | const { contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { getAccounts } = require("../../data/airdrop") 4 | 5 | async function main() { 6 | const gmt = await contractAt("GMT", "0x99e92123eB77Bc8f999316f622e5222498438784") 7 | const batchSender = await contractAt("BatchSender", "0x04c5B7575De2E00079e11578bF00F09C07007Bda") 8 | const accounts = getAccounts() 9 | 10 | // await sendTxn(gmt.beginMigration(), "gmt.beginMigration") 11 | // await sendTxn(gmt.addMsgSender(batchSender.address), "gmt.addMsgSender(batchSender)") 12 | 13 | // await sendTxn(gmt.approve(batchSender.address, "112000000000000000000000"), "gmt.approve") 14 | 15 | const addresses = [] 16 | const amounts = [] 17 | 18 | for (let i = 0; i < accounts.length; i++) { 19 | console.info("accounts[i]", i, accounts[i]) 20 | addresses.push(accounts[i][0]) 21 | amounts.push(ethers.utils.parseEther(accounts[i][1])) 22 | } 23 | 24 | await sendTxn(batchSender.send(gmt.address, addresses, amounts), "batchSender.send") 25 | } 26 | 27 | main() 28 | .then(() => process.exit(0)) 29 | .catch(error => { 30 | console.error(error) 31 | process.exit(1) 32 | }) 33 | -------------------------------------------------------------------------------- /scripts/peripherals/transferNFT.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt, writeTmpAddresses, sendTxn } = require("../shared/helpers") 2 | 3 | async function main() { 4 | // const signer = await getFrameSigner() 5 | const wallet = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 6 | // const wallet = { address: "0x49B373D422BdA4C6BfCdd5eC1E48A9a26fdA2F8b" } 7 | // const nft = await contractAt("ERC721", "0xC36442b4a4522E871399CD717aBDD847Ab11FE88", signer) 8 | const nft = await contractAt("ERC721", "0xC36442b4a4522E871399CD717aBDD847Ab11FE88") 9 | const nftId = 17080 10 | // const tokenManager = await contractAt("TokenManager", "0x50F22389C10FcC3bA9B1AB9BCDafE40448a357FB") 11 | // const tokenManager = await contractAt("TokenManager", "0x4E29d2ee6973E5Bd093df40ef9d0B28BD56C9e4E") 12 | const tokenManager = await contractAt("TokenManager", "0xddDc546e07f1374A07b270b7d863371e575EA96A") 13 | await sendTxn(nft.transferFrom(wallet.address, tokenManager.address, nftId), "nft.transferFrom") 14 | // await sendTxn(nft.transferFrom(tokenManager.address, wallet.address, nftId), "nft.transferFrom") 15 | } 16 | 17 | main() 18 | .then(() => process.exit(0)) 19 | .catch(error => { 20 | console.error(error) 21 | process.exit(1) 22 | }) 23 | -------------------------------------------------------------------------------- /contracts/amm/UniPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | contract UniPool { 6 | struct Slot0 { 7 | // the current price 8 | uint160 sqrtPriceX96; 9 | // the current tick 10 | int24 tick; 11 | // the most-recently updated index of the observations array 12 | uint16 observationIndex; 13 | // the current maximum number of observations that are being stored 14 | uint16 observationCardinality; 15 | // the next maximum number of observations to store, triggered in observations.write 16 | uint16 observationCardinalityNext; 17 | // the current protocol fee as a percentage of the swap fee taken on withdrawal 18 | // represented as an integer denominator (1/x)% 19 | uint8 feeProtocol; 20 | // whether the pool is locked 21 | bool unlocked; 22 | } 23 | 24 | Slot0 public slot0; 25 | 26 | function tickSpacing() external pure returns (int24) { return 0; } 27 | 28 | function observe(uint32[] calldata /* secondsAgos */) 29 | external 30 | pure 31 | returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s) 32 | { 33 | return (tickCumulatives, secondsPerLiquidityCumulativeX128s); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /contracts/core/interfaces/IGlpManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./IVault.sol"; 6 | 7 | interface IGlpManager { 8 | function glp() external view returns (address); 9 | function usdg() external view returns (address); 10 | function vault() external view returns (IVault); 11 | function cooldownDuration() external returns (uint256); 12 | function getAumInUsdg(bool maximise) external view returns (uint256); 13 | function lastAddedAt(address _account) external returns (uint256); 14 | function addLiquidity(address _token, uint256 _amount, uint256 _minUsdg, uint256 _minGlp) external returns (uint256); 15 | function addLiquidityForAccount(address _fundingAccount, address _account, address _token, uint256 _amount, uint256 _minUsdg, uint256 _minGlp) external returns (uint256); 16 | function removeLiquidity(address _tokenOut, uint256 _glpAmount, uint256 _minOut, address _receiver) external returns (uint256); 17 | function removeLiquidityForAccount(address _account, address _tokenOut, uint256 _glpAmount, uint256 _minOut, address _receiver) external returns (uint256); 18 | function setShortsTrackerAveragePriceWeight(uint256 _shortsTrackerAveragePriceWeight) external; 19 | function setCooldownDuration(uint256 _cooldownDuration) external; 20 | } 21 | -------------------------------------------------------------------------------- /scripts/staking/checkStake.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const wallet = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 6 | 7 | const account = "0x9f169c2189A2d975C18965DE985936361b4a9De9" 8 | 9 | const gmx = await contractAt("GMX", "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a"); 10 | const bnGmx = await contractAt("MintableBaseToken", "0x35247165119B69A40edD5304969560D0ef486921"); 11 | const stakedGmxTracker = await contractAt("RewardTracker", "0x908C4D94D34924765f1eDc22A1DD098397c59dD4") 12 | const bonusGmxTracker = await contractAt("RewardTracker", "0x4d268a7d4C16ceB5a606c173Bd974984343fea13") 13 | const feeGmxTracker = await contractAt("RewardTracker", "0xd2D1162512F927a7e282Ef43a362659E4F2a728F") 14 | 15 | console.log("stakedGmxTracker.claimable", (await stakedGmxTracker.claimable(account)).toString()) 16 | console.log("bonusGmxTracker.claimable", (await bonusGmxTracker.claimable(account)).toString()) 17 | console.log("feeGmxTracker.claimable", (await feeGmxTracker.claimable(account)).toString()) 18 | } 19 | 20 | main() 21 | .then(() => process.exit(0)) 22 | .catch(error => { 23 | console.error(error) 24 | process.exit(1) 25 | }) 26 | -------------------------------------------------------------------------------- /scripts/peripherals/fundAccounts.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, sendTxn, contractAt } = require("../shared/helpers") 2 | const { formatAmount } = require("../../test/shared/utilities") 3 | const { getValues } = require("../shared/fundAccountsUtils") 4 | 5 | async function main() { 6 | const signer = await getFrameSigner() 7 | const { sender, transfers, totalTransferAmount, tokens, gasToken } = await getValues() 8 | const nativeTokenForSigner = await contractAt("WETH", tokens.nativeToken.address, signer) 9 | 10 | await sendTxn(nativeTokenForSigner.transfer(sender.address, totalTransferAmount), `to distributor, ${formatAmount(totalTransferAmount, 18, 2)} ${gasToken} to ${sender.address}`) 11 | 12 | const nativeToken = await contractAt("WETH", tokens.nativeToken.address) 13 | await sendTxn(nativeToken.withdraw(totalTransferAmount), `nativeToken.withdraw(${formatAmount(totalTransferAmount, 18, 2)})`) 14 | 15 | for (let i = 0; i < transfers.length; i++) { 16 | const transferItem = transfers[i] 17 | 18 | await sendTxn(sender.sendTransaction({ 19 | to: transferItem.address, 20 | value: transferItem.amount 21 | }), `${formatAmount(transferItem.amount, 18, 2)} ${gasToken} to ${transferItem.address}`) 22 | } 23 | } 24 | 25 | main() 26 | .then(() => process.exit(0)) 27 | .catch(error => { 28 | console.error(error) 29 | process.exit(1) 30 | }) 31 | -------------------------------------------------------------------------------- /scripts/core/upgradeVault.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt , sendTxn, writeTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | const { errors } = require("../../test/core/Vault/helpers") 5 | 6 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 7 | const tokens = require('./tokens')[network]; 8 | 9 | // this should only be used for development 10 | // mainnet contracts should be controller by a timelock 11 | async function main() { 12 | const wallet = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 13 | 14 | const vault = await contractAt("Vault", "0xDE3590067c811b6F023b557ed45E4f1067859663") 15 | const { eth, btc, usdc } = tokens 16 | const tokenArr = [eth, btc, usdc] 17 | for (let i = 0; i < tokenArr.length; i++) { 18 | const tokenInfo = tokenArr[i] 19 | const token = await contractAt("Token", tokenInfo.address) 20 | const balance = await token.balanceOf(vault.address) 21 | console.log(tokenInfo.name, balance.toString()) 22 | await sendTxn(vault.upgradeVault(wallet.address, token.address, balance), `vault.upgradeVault(${tokenInfo.name})`) 23 | } 24 | } 25 | 26 | main() 27 | .then(() => process.exit(0)) 28 | .catch(error => { 29 | console.error(error) 30 | process.exit(1) 31 | }) 32 | -------------------------------------------------------------------------------- /contracts/tokens/Bridge.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../libraries/token/IERC20.sol"; 6 | import "../libraries/math/SafeMath.sol"; 7 | import "../libraries/token/SafeERC20.sol"; 8 | import "../libraries/utils/ReentrancyGuard.sol"; 9 | 10 | import "../access/Governable.sol"; 11 | 12 | contract Bridge is ReentrancyGuard, Governable { 13 | using SafeMath for uint256; 14 | using SafeERC20 for IERC20; 15 | 16 | address public token; 17 | address public wToken; 18 | 19 | constructor(address _token, address _wToken) public { 20 | token = _token; 21 | wToken = _wToken; 22 | } 23 | 24 | function wrap(uint256 _amount, address _receiver) external nonReentrant { 25 | IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 26 | IERC20(wToken).safeTransfer(_receiver, _amount); 27 | } 28 | 29 | function unwrap(uint256 _amount, address _receiver) external nonReentrant { 30 | IERC20(wToken).safeTransferFrom(msg.sender, address(this), _amount); 31 | IERC20(token).safeTransfer(_receiver, _amount); 32 | } 33 | 34 | // to help users who accidentally send their tokens to this contract 35 | function withdrawToken(address _token, address _account, uint256 _amount) external onlyGov { 36 | IERC20(_token).safeTransfer(_account, _amount); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /scripts/referrals/batchSendReferralRewards.js: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | 3 | const { contractAt, sendTxn, processBatch, getFrameSigner } = require("../shared/helpers") 4 | const { expandDecimals, bigNumberify } = require("../../test/shared/utilities") 5 | const { getArbValues, getAvaxValues, sendReferralRewards } = require("./referralRewards") 6 | 7 | const gmxPrice = expandDecimals("62", 30) 8 | 9 | const nativeTokenPrices = { 10 | arbitrum: expandDecimals("1855", 30), 11 | avax: expandDecimals("16", 30) 12 | } 13 | 14 | const shouldSendTxn = false 15 | 16 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 17 | const tokens = require('../core/tokens')[network]; 18 | const nativeToken = tokens.nativeToken 19 | 20 | const nativeTokenPrice = nativeTokenPrices[network] 21 | 22 | async function getValues() { 23 | if (network === "arbitrum") { 24 | return getArbValues() 25 | } 26 | 27 | if (network === "avax") { 28 | return getAvaxValues() 29 | } 30 | } 31 | 32 | async function main() { 33 | let signer 34 | if (shouldSendTxn) { 35 | signer = await getFrameSigner() 36 | } 37 | 38 | const values = await getValues() 39 | await sendReferralRewards({ signer, shouldSendTxn, nativeToken, nativeTokenPrice, gmxPrice, values }) 40 | } 41 | 42 | main() 43 | .then(() => process.exit(0)) 44 | .catch(error => { 45 | console.error(error) 46 | process.exit(1) 47 | }) 48 | -------------------------------------------------------------------------------- /contracts/amm/UniNftManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | pragma experimental ABIEncoderV2; 5 | 6 | contract UniNftManager { 7 | struct CollectParams { 8 | uint256 tokenId; 9 | address recipient; 10 | uint128 amount0Max; 11 | uint128 amount1Max; 12 | } 13 | 14 | function positions(uint256 /* tokenId */) 15 | external 16 | pure 17 | returns ( 18 | uint96 nonce, 19 | address operator, 20 | address token0, 21 | address token1, 22 | uint24 fee, 23 | int24 tickLower, 24 | int24 tickUpper, 25 | uint128 liquidity, 26 | uint256 feeGrowthInside0LastX128, 27 | uint256 feeGrowthInside1LastX128, 28 | uint128 tokensOwed0, 29 | uint128 tokensOwed1 30 | ) 31 | { 32 | return ( 33 | 0, 34 | address(0), 35 | address(0), 36 | address(0), 37 | 0, 38 | 0, 39 | 0, 40 | 0, 41 | 0, 42 | 0, 43 | 0, 44 | 0 45 | ); 46 | } 47 | 48 | function collect(CollectParams calldata params) external returns (uint256 amount0, uint256 amount1) {} 49 | 50 | function ownerOf(uint256 tokenId) external view returns (address) {} 51 | } 52 | -------------------------------------------------------------------------------- /scripts/core/deployGlpManager.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt , sendTxn, writeTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function main() { 9 | const { 10 | nativeToken 11 | } = tokens 12 | 13 | const vault = await contractAt("Vault", "0xDE3590067c811b6F023b557ed45E4f1067859663") 14 | const usdg = await contractAt("USDG", "0x45096e7aA921f27590f8F19e457794EB09678141") 15 | const glp = await contractAt("GLP", "0x4277f8F2c384827B5273592FF7CeBd9f2C1ac258") 16 | 17 | const glpManager = await deployContract("GlpManager", [vault.address, usdg.address, glp.address, 15 * 60]) 18 | 19 | await sendTxn(glpManager.setInPrivateMode(true), "glpManager.setInPrivateMode") 20 | 21 | await sendTxn(glp.setMinter(glpManager.address, true), "glp.setMinter") 22 | await sendTxn(usdg.addVault(glpManager.address), "usdg.addVault") 23 | await sendTxn(vault.setManager(glpManager.address, true), "vault.setManager") 24 | 25 | writeTmpAddresses({ 26 | glpManager: glpManager.address 27 | }) 28 | } 29 | 30 | main() 31 | .then(() => process.exit(0)) 32 | .catch(error => { 33 | console.error(error) 34 | process.exit(1) 35 | }) 36 | -------------------------------------------------------------------------------- /scripts/core/updatePositionRouterFee.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn, readTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { bigNumberify, expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | const tokens = require('./tokens')[network]; 6 | 7 | async function getArbValues() { 8 | const positionRouter = await contractAt("PositionRouter", "0x3D6bA331e3D9702C5e8A8d254e5d8a285F223aba") 9 | const minExecutionFee = "0.0003" 10 | 11 | return { positionRouter, minExecutionFee } 12 | } 13 | 14 | async function getAvaxValues() { 15 | const positionRouter = await contractAt("PositionRouter", "0x3D6bA331e3D9702C5e8A8d254e5d8a285F223aba") 16 | const minExecutionFee = "0.02" 17 | 18 | return { positionRouter, minExecutionFee } 19 | } 20 | 21 | async function getValues() { 22 | if (network === "arbitrum") { 23 | return getArbValues() 24 | } 25 | 26 | if (network === "avax") { 27 | return getAvaxValues() 28 | } 29 | } 30 | 31 | async function main() { 32 | const { positionRouter, minExecutionFee } = await getValues() 33 | 34 | await sendTxn(positionRouter.setMinExecutionFee(ethers.utils.parseEther(minExecutionFee)), "positionRouter.setMinExecutionFee") 35 | } 36 | 37 | main() 38 | .then(() => process.exit(0)) 39 | .catch(error => { 40 | console.error(error) 41 | process.exit(1) 42 | }) 43 | -------------------------------------------------------------------------------- /scripts/peripherals/printFeeCalculations.js: -------------------------------------------------------------------------------- 1 | const { getArbValues, getAvaxValues, getGmxPrice } = require("./feeCalculations") 2 | const { formatAmount } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const values = { 6 | arbitrum: await getArbValues(), 7 | avax: await getAvaxValues() 8 | } 9 | 10 | const ethPrice = values.arbitrum.nativeTokenPrice 11 | const avaxPrice = values.avax.nativeTokenPrice 12 | const gmxPrice = await getGmxPrice(ethPrice) 13 | 14 | const data = [ 15 | ["ETH Price", formatAmount(ethPrice, 30, 2)], 16 | ["AVAX Price", formatAmount(avaxPrice, 30, 2)], 17 | ["GMX Price", formatAmount(gmxPrice, 30, 2)], 18 | ["ARB Fees", formatAmount(values.arbitrum.feesUsd, 30, 2)], 19 | ["AVAX Fees", formatAmount(values.avax.feesUsd, 30, 2)], 20 | ["ARB sbfGMX", formatAmount(values.arbitrum.stakedGmxSupply, 18, 2)], 21 | ["AVAX sbfGMX", formatAmount(values.avax.stakedGmxSupply, 18, 2)], 22 | ["ARB Keeper Costs", formatAmount(values.arbitrum.keeperCosts, 18, 2)], 23 | ["AVAX Keeper Costs", formatAmount(values.avax.keeperCosts, 18, 2)], 24 | ["GLP AUM (ARB)", formatAmount(values.arbitrum.glpAum, 30, 2)], 25 | ["GLP AUM (AVAX)", formatAmount(values.avax.glpAum, 30, 2)], 26 | ] 27 | 28 | for (let i = 0; i < data.length; i++) { 29 | const item = data[i] 30 | console.log([item[0], item[1]].join(",")) 31 | } 32 | } 33 | 34 | main() 35 | -------------------------------------------------------------------------------- /scripts/core/setFees.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt , sendTxn, writeTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function main() { 9 | const signer = await getFrameSigner() 10 | 11 | let vault 12 | if (network === "avax") { 13 | vault = await contractAt("Vault", "0x9ab2De34A33fB459b538c43f251eB825645e8595") 14 | } 15 | if (network === "arbitrum") { 16 | vault = await contractAt("Vault", "0x489ee077994B6658eAfA855C308275EAd8097C4A") 17 | } 18 | 19 | const timelock = await contractAt("Timelock", await vault.gov(), signer) 20 | console.log("timelock", timelock.address) 21 | 22 | await sendTxn(timelock.setFees( 23 | vault.address, 24 | 50, // _taxBasisPoints 25 | 5, // _stableTaxBasisPoints 26 | 25, // _mintBurnFeeBasisPoints 27 | 30, // _swapFeeBasisPoints 28 | 1, // _stableSwapFeeBasisPoints 29 | 10, // _marginFeeBasisPoints 30 | toUsd(5), // _liquidationFeeUsd 31 | 3 * 60 * 60, // _minProfitTime 32 | true // _hasDynamicFees 33 | ), "vault.setFees") 34 | } 35 | 36 | main() 37 | .then(() => process.exit(0)) 38 | .catch(error => { 39 | console.error(error) 40 | process.exit(1) 41 | }) 42 | -------------------------------------------------------------------------------- /scripts/peripherals/getList.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const holderList = require("../../data/holders/gmxHolders.json") 4 | 5 | async function main() { 6 | const feeGmxTracker = await contractAt("RewardTracker", "0xd2D1162512F927a7e282Ef43a362659E4F2a728F") 7 | const bonusGmxTracker = await contractAt("RewardTracker", "0x4d268a7d4C16ceB5a606c173Bd974984343fea13") 8 | const bnGmx = { address: "0x35247165119B69A40edD5304969560D0ef486921" } 9 | 10 | const data = [] 11 | 12 | console.log("holderList", holderList.length) 13 | for (let i = 3490; i < holderList.length; i++) { 14 | const account = holderList[i] 15 | const bnGmxBalance = await feeGmxTracker.depositBalances(account, bnGmx.address) 16 | const pendingRewards = await bonusGmxTracker.claimable(account) 17 | const totalRewards = bnGmxBalance.add(pendingRewards) 18 | console.log(`${i+1},${account},${ethers.utils.formatUnits(bnGmxBalance, 18)},${ethers.utils.formatUnits(pendingRewards, 18)},${ethers.utils.formatUnits(totalRewards)}`) 19 | data.push([account, ethers.utils.formatUnits(totalRewards)]) 20 | } 21 | 22 | // console.log("final data:") 23 | // console.log(data.map((i) => i.join(",")).join("\n")) 24 | } 25 | 26 | main() 27 | .then(() => process.exit(0)) 28 | .catch(error => { 29 | console.error(error) 30 | process.exit(1) 31 | }) 32 | -------------------------------------------------------------------------------- /scripts/gambit-token/deployTreasury.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const PRECISION = 1000000 5 | 6 | async function main() { 7 | const treasury = await contractAt("Treasury", "0xa44E7252a0C137748F523F112644042E5987FfC7") 8 | const gmt = await contractAt("GMT", "0x99e92123eB77Bc8f999316f622e5222498438784") 9 | const busd = await contractAt("Token", "0xe9e7cea3dedca5984780bafc599bd69add087d56") 10 | const router = { address: "0x05ff2b0db69458a0750badebc4f9e13add608c7f" } 11 | const fund = { address: "0x58CAaCa45a213e9218C5fFd605d5B953da9b9a91" } 12 | const gmtPresalePrice = 4.5 * PRECISION 13 | const gmtListingPrice = 5 * PRECISION 14 | const busdSlotCap = expandDecimals(2000, 18) 15 | const busdHardCap = expandDecimals(900 * 1000, 18) 16 | const busdBasisPoints = 5000 // 50% 17 | const unlockTime = 1615291200 // Tuesday, 9 March 2021 12:00:00 (GMT+0) 18 | 19 | await sendTxn(treasury.initialize( 20 | [ 21 | gmt.address, 22 | busd.address, 23 | router.address, 24 | fund.address 25 | ], 26 | [ 27 | gmtPresalePrice, 28 | gmtListingPrice, 29 | busdSlotCap, 30 | busdHardCap, 31 | busdBasisPoints, 32 | unlockTime 33 | ] 34 | ), "treasury.initialize") 35 | 36 | return { treasury } 37 | } 38 | 39 | main() 40 | .then(() => process.exit(0)) 41 | .catch(error => { 42 | console.error(error) 43 | process.exit(1) 44 | }) 45 | -------------------------------------------------------------------------------- /contracts/core/interfaces/IOrderBook.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IOrderBook { 6 | function getSwapOrder(address _account, uint256 _orderIndex) external view returns ( 7 | address path0, 8 | address path1, 9 | address path2, 10 | uint256 amountIn, 11 | uint256 minOut, 12 | uint256 triggerRatio, 13 | bool triggerAboveThreshold, 14 | bool shouldUnwrap, 15 | uint256 executionFee 16 | ); 17 | 18 | function getIncreaseOrder(address _account, uint256 _orderIndex) external view returns ( 19 | address purchaseToken, 20 | uint256 purchaseTokenAmount, 21 | address collateralToken, 22 | address indexToken, 23 | uint256 sizeDelta, 24 | bool isLong, 25 | uint256 triggerPrice, 26 | bool triggerAboveThreshold, 27 | uint256 executionFee 28 | ); 29 | 30 | function getDecreaseOrder(address _account, uint256 _orderIndex) external view returns ( 31 | address collateralToken, 32 | uint256 collateralDelta, 33 | address indexToken, 34 | uint256 sizeDelta, 35 | bool isLong, 36 | uint256 triggerPrice, 37 | bool triggerAboveThreshold, 38 | uint256 executionFee 39 | ); 40 | 41 | function executeSwapOrder(address, uint256, address payable) external; 42 | function executeDecreaseOrder(address, uint256, address payable) external; 43 | function executeIncreaseOrder(address, uint256, address payable) external; 44 | } 45 | -------------------------------------------------------------------------------- /scripts/peripherals/getPairAmount.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const path = require('path') 5 | const fs = require('fs') 6 | const parse = require('csv-parse') 7 | 8 | const inputFile = path.resolve(__dirname, "../..") + "/data/holders/vestedGmxHolders.csv" 9 | 10 | const processFile = async (file) => { 11 | records = [] 12 | const parser = fs 13 | .createReadStream(file) 14 | .pipe(parse({ columns: true, delimiter: ',' })) 15 | parser.on('error', function(err){ 16 | console.error(err.message) 17 | }) 18 | for await (const record of parser) { 19 | records.push(record) 20 | } 21 | return records 22 | } 23 | 24 | async function main() { 25 | const holderList = await processFile(inputFile) 26 | const gmxVester = await contractAt("Vester", "0x199070DDfd1CFb69173aa2F7e20906F26B363004") 27 | const data = [] 28 | 29 | console.log("holderList", holderList.length) 30 | for (let i = 0; i < holderList.length; i++) { 31 | const account = holderList[i].HolderAddress 32 | const pairAmount = await gmxVester.pairAmounts(account) 33 | console.log(`${i+1},${account},${ethers.utils.formatUnits(pairAmount, 18)}`) 34 | data.push([account, ethers.utils.formatUnits(pairAmount, 18)]) 35 | } 36 | 37 | console.log("final data:") 38 | console.log(data.map((i) => i.join(",")).join("\n")) 39 | } 40 | 41 | main() 42 | .then(() => process.exit(0)) 43 | .catch(error => { 44 | console.error(error) 45 | process.exit(1) 46 | }) 47 | -------------------------------------------------------------------------------- /contracts/core/interfaces/IVaultPriceFeed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IVaultPriceFeed { 6 | function adjustmentBasisPoints(address _token) external view returns (uint256); 7 | function isAdjustmentAdditive(address _token) external view returns (bool); 8 | function setAdjustment(address _token, bool _isAdditive, uint256 _adjustmentBps) external; 9 | function setUseV2Pricing(bool _useV2Pricing) external; 10 | function setIsAmmEnabled(bool _isEnabled) external; 11 | function setIsSecondaryPriceEnabled(bool _isEnabled) external; 12 | function setSpreadBasisPoints(address _token, uint256 _spreadBasisPoints) external; 13 | function setSpreadThresholdBasisPoints(uint256 _spreadThresholdBasisPoints) external; 14 | function setFavorPrimaryPrice(bool _favorPrimaryPrice) external; 15 | function setPriceSampleSpace(uint256 _priceSampleSpace) external; 16 | function setMaxStrictPriceDeviation(uint256 _maxStrictPriceDeviation) external; 17 | function getPrice(address _token, bool _maximise, bool _includeAmmPrice, bool _useSwapPricing) external view returns (uint256); 18 | function getAmmPrice(address _token) external view returns (uint256); 19 | function getLatestPrimaryPrice(address _token) external view returns (uint256); 20 | function getPrimaryPrice(address _token, bool _maximise) external view returns (uint256); 21 | function setTokenConfig( 22 | address _token, 23 | address _priceFeed, 24 | uint256 _priceDecimals, 25 | bool _isStrictStable 26 | ) external; 27 | } 28 | -------------------------------------------------------------------------------- /contracts/oracle/PriceFeed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "./interfaces/IPriceFeed.sol"; 6 | 7 | contract PriceFeed is IPriceFeed { 8 | int256 public answer; 9 | uint80 public roundId; 10 | string public override description = "PriceFeed"; 11 | address public override aggregator; 12 | 13 | uint256 public decimals; 14 | 15 | address public gov; 16 | 17 | mapping (uint80 => int256) public answers; 18 | mapping (address => bool) public isAdmin; 19 | 20 | constructor() public { 21 | gov = msg.sender; 22 | isAdmin[msg.sender] = true; 23 | } 24 | 25 | function setAdmin(address _account, bool _isAdmin) public { 26 | require(msg.sender == gov, "PriceFeed: forbidden"); 27 | isAdmin[_account] = _isAdmin; 28 | } 29 | 30 | function latestAnswer() public override view returns (int256) { 31 | return answer; 32 | } 33 | 34 | function latestRound() public override view returns (uint80) { 35 | return roundId; 36 | } 37 | 38 | function setLatestAnswer(int256 _answer) public { 39 | require(isAdmin[msg.sender], "PriceFeed: forbidden"); 40 | roundId = roundId + 1; 41 | answer = _answer; 42 | answers[roundId] = _answer; 43 | } 44 | 45 | // returns roundId, answer, startedAt, updatedAt, answeredInRound 46 | function getRoundData(uint80 _roundId) public override view 47 | returns (uint80, int256, uint256, uint256, uint80) 48 | { 49 | return (_roundId, answers[_roundId], 0, 0, 0); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /contracts/peripherals/PositionRouterReader.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../core/PositionRouter.sol"; 6 | 7 | contract PositionRouterReader { 8 | function getTransferTokenOfIncreasePositionRequests( 9 | address _positionRouter, 10 | uint256 _endIndex 11 | ) external view returns (uint256[] memory, address[] memory) { 12 | IPositionRouter positionRouter = IPositionRouter(_positionRouter); 13 | 14 | // increasePositionRequestKeysStart, 15 | // increasePositionRequestKeys.length, 16 | // decreasePositionRequestKeysStart, 17 | // decreasePositionRequestKeys.length 18 | (uint256 index, uint256 length, ,) = positionRouter.getRequestQueueLengths(); 19 | 20 | if (_endIndex > length) { _endIndex = length; } 21 | 22 | uint256[] memory requestIndexes = new uint256[](_endIndex - index); 23 | address[] memory transferTokens = new address[](_endIndex - index); 24 | 25 | uint256 transferTokenIndex = 0; 26 | 27 | while (index < _endIndex) { 28 | bytes32 key = positionRouter.increasePositionRequestKeys(index); 29 | address[] memory path = positionRouter.getIncreasePositionRequestPath(key); 30 | if (path.length > 0) { 31 | transferTokens[transferTokenIndex] = path[0]; 32 | } 33 | 34 | requestIndexes[transferTokenIndex] = index; 35 | 36 | transferTokenIndex++; 37 | index++; 38 | } 39 | 40 | return (requestIndexes, transferTokens); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /audits/Quantstamp_Audit_Review.txt: -------------------------------------------------------------------------------- 1 | This review clarifies the medium risk issue highlighted by Quantstamp regarding the Timelock contracts. 2 | 3 | High impact functions require two transactions to execute: 4 | 5 | 1. Signal transaction 6 | 2. 24 hour delay 7 | 3. Finalize transaction 8 | 9 | The signal transactions can be initiated by the admin of the Timelock. 10 | 11 | If the admin signals a malicious transaction, during the 24 hour delay, the multi-sig of the Timelock can change the admin, which will prevent the malicious transaction from being finalized. 12 | 13 | The current multi-sig holders: https://github.com/gmx-io/gmx-contracts/blob/master/scripts/access/deployTokenManager.js. 14 | 15 | Timelocks can be monitored by anyone, reporting of a malicious timelock transaction is covered under the GMX Immunefi bounty: https://immunefi.com/bounty/gmx/. 16 | 17 | Docs on this and on setting up monitoring https://gmx-io.notion.site/GMX-Technical-Overview-47fc5ed832e243afb9e97e8a4a036353. 18 | 19 | The Timelock contracts allow some configuration to be changed without a two step process, for example, setting of open interest caps and token weights. 20 | 21 | This is to allow the platform to adapt quickly if needed, ideally the need for active adjustments should be minimized and the contracts have since been improved towards that goal. 22 | 23 | These improvements are in https://github.com/gmx-io/gmx-synthetics. 24 | 25 | The improved contracts automate most processes, isolate risks for LPs, provide better protection against price manipulation, allowing active adjustments to no longer be needed for things like weights and caps 26 | -------------------------------------------------------------------------------- /scripts/core/deployShortsTracker.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt , sendTxn, readTmpAddresses, writeTmpAddresses } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units"); 4 | const { getArgumentForSignature } = require("typechain"); 5 | 6 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 7 | const tokens = require('./tokens')[network]; 8 | 9 | async function getArbTestnetValues() { 10 | return { vaultAddress: "0xBc9BC47A7aB63db1E0030dC7B60DDcDe29CF4Ffb", gasLimit: 12500000 } 11 | } 12 | 13 | async function getArbValues() { 14 | return { vaultAddress: "0x489ee077994B6658eAfA855C308275EAd8097C4A", gasLimit: 12500000 } 15 | } 16 | 17 | async function getAvaxValues() { 18 | return { vaultAddress: "0x9ab2De34A33fB459b538c43f251eB825645e8595" } 19 | } 20 | 21 | async function getValues() { 22 | if (network === "avax") { 23 | return await getAvaxValues() 24 | } else if (network === "arbitrumTestnet") { 25 | return await getArbTestnetValues() 26 | } else { 27 | return await getArbValues() 28 | } 29 | } 30 | 31 | async function main() { 32 | const { vaultAddress, gasLimit } = await getValues() 33 | const gov = { address: "0x49B373D422BdA4C6BfCdd5eC1E48A9a26fdA2F8b" } 34 | const shortsTracker = await deployContract("ShortsTracker", [vaultAddress], "ShortsTracker", { gasLimit }) 35 | await sendTxn(shortsTracker.setGov(gov.address), "shortsTracker.setGov") 36 | } 37 | 38 | main() 39 | .then(() => process.exit(0)) 40 | .catch(error => { 41 | console.error(error) 42 | process.exit(1) 43 | }) 44 | -------------------------------------------------------------------------------- /scripts/peripherals/setGov.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn, getFrameSigner } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | 6 | async function getArbValues(signer) { 7 | const target = await contractAt("Vault", "0x489ee077994B6658eAfA855C308275EAd8097C4A") 8 | const nextTimelock = await contractAt("Timelock", "0x6A9215C9c148ca68E11aA8534A413B099fd6798f", signer) 9 | return { target, nextTimelock } 10 | } 11 | 12 | async function getAvaxValues(signer) { 13 | const target = await contractAt("Vault", "0x9ab2De34A33fB459b538c43f251eB825645e8595") 14 | const nextTimelock = await contractAt("Timelock", "0x5aeCDD22cDA7D2010631D71b268D5479e1d2B8f4", signer) 15 | return { target, nextTimelock } 16 | } 17 | 18 | async function getValues(signer) { 19 | if (network === "arbitrum") { 20 | return getArbValues(signer) 21 | } 22 | 23 | if (network === "avax") { 24 | return getAvaxValues(signer) 25 | } 26 | } 27 | 28 | async function main() { 29 | const signer = await getFrameSigner() 30 | 31 | const { target, nextTimelock } = await getValues(signer) 32 | const prevTimelock = await contractAt("Timelock", await target.gov(), signer) 33 | 34 | await sendTxn(prevTimelock.signalSetGov(target.address, nextTimelock.address), "prevTimelock.signalSetGov(nextTimelock)") 35 | await sendTxn(nextTimelock.signalSetGov(target.address, prevTimelock.address), "nextTimelock.signalSetGov(prevTimelock)") 36 | } 37 | 38 | main() 39 | .then(() => process.exit(0)) 40 | .catch(error => { 41 | console.error(error) 42 | process.exit(1) 43 | }) 44 | -------------------------------------------------------------------------------- /scripts/core/setTiersReferralStorage.js: -------------------------------------------------------------------------------- 1 | const { contractAt , sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function getArbValues() { 9 | const referralStorage = await contractAt("ReferralStorage", "0xe6fab3F0c7199b0d34d7FbE83394fc0e0D06e99d") 10 | 11 | return { referralStorage } 12 | } 13 | 14 | async function getAvaxValues() { 15 | const referralStorage = await contractAt("ReferralStorage", "0x827ED045002eCdAbEb6e2b0d1604cf5fC3d322F8") 16 | 17 | return { referralStorage } 18 | } 19 | 20 | async function getValues() { 21 | if (network === "arbitrum") { 22 | return getArbValues() 23 | } 24 | 25 | if (network === "avax") { 26 | return getAvaxValues() 27 | } 28 | } 29 | 30 | async function main() { 31 | const { referralStorage } = await getValues() 32 | 33 | await sendTxn(referralStorage.setTier(0, 1000, 5000), "referralStorage.setTier 0") 34 | await sendTxn(referralStorage.setTier(1, 2000, 5000), "referralStorage.setTier 1") 35 | await sendTxn(referralStorage.setTier(2, 2500, 4000), "referralStorage.setTier 2") 36 | 37 | await sendTxn(referralStorage.setReferrerTier("0xbb00f2E53888E60974110d68F1060e5eAAB34790", 1), "referralStorage.setReferrerTier 1") 38 | await sendTxn(referralStorage.setReferrerTier("0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8", 2), "referralStorage.setReferrerTier 2") 39 | } 40 | 41 | main() 42 | .then(() => process.exit(0)) 43 | .catch(error => { 44 | console.error(error) 45 | process.exit(1) 46 | }) 47 | -------------------------------------------------------------------------------- /contracts/staking/interfaces/IVester.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IVester { 6 | function rewardTracker() external view returns (address); 7 | 8 | function claimForAccount(address _account, address _receiver) external returns (uint256); 9 | 10 | function claimable(address _account) external view returns (uint256); 11 | function cumulativeClaimAmounts(address _account) external view returns (uint256); 12 | function claimedAmounts(address _account) external view returns (uint256); 13 | function pairAmounts(address _account) external view returns (uint256); 14 | function getVestedAmount(address _account) external view returns (uint256); 15 | function transferredAverageStakedAmounts(address _account) external view returns (uint256); 16 | function transferredCumulativeRewards(address _account) external view returns (uint256); 17 | function cumulativeRewardDeductions(address _account) external view returns (uint256); 18 | function bonusRewards(address _account) external view returns (uint256); 19 | 20 | function transferStakeValues(address _sender, address _receiver) external; 21 | function setTransferredAverageStakedAmounts(address _account, uint256 _amount) external; 22 | function setTransferredCumulativeRewards(address _account, uint256 _amount) external; 23 | function setCumulativeRewardDeductions(address _account, uint256 _amount) external; 24 | function setBonusRewards(address _account, uint256 _amount) external; 25 | 26 | function getMaxVestableAmount(address _account) external view returns (uint256); 27 | function getCombinedAverageStakedAmount(address _account) external view returns (uint256); 28 | } 29 | -------------------------------------------------------------------------------- /scripts/peripherals/referralBatchSend.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | 6 | async function getArbValues() { 7 | const batchSender = await contractAt("BatchSender", "0x1070f775e8eb466154BBa8FA0076C4Adc7FE17e8") 8 | const token = await contractAt("Token", "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1") 9 | const tokenDecimals = 18 10 | 11 | return { batchSender, token, tokenDecimals } 12 | } 13 | 14 | async function getAvaxValues() { 15 | const batchSender = await contractAt("BatchSender", "0xF0f929162751DD723fBa5b86A9B3C88Dc1D4957b") 16 | const token = await contractAt("Token", "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7") 17 | const tokenDecimals = 18 18 | 19 | return { batchSender, token, tokenDecimals } 20 | } 21 | 22 | async function getValues() { 23 | if (network === "arbitrum") { 24 | return getArbValues() 25 | } 26 | 27 | if (network === "avax") { 28 | return getAvaxValues() 29 | } 30 | } 31 | 32 | async function main() { 33 | const wallet = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 34 | const { batchSender, token, tokenDecimals } = await getValues() 35 | 36 | const totalAmount = "10000000000000000" 37 | const typeId = 1 38 | 39 | await sendTxn(token.approve(batchSender.address, totalAmount), "token.approve") 40 | await sendTxn(batchSender.sendAndEmit(token.address, [wallet.address], [totalAmount], typeId), "batchSender.sendAndEmit") 41 | } 42 | 43 | main() 44 | .then(() => process.exit(0)) 45 | .catch(error => { 46 | console.error(error) 47 | process.exit(1) 48 | }) 49 | -------------------------------------------------------------------------------- /scripts/peripherals/printFeeValues.js: -------------------------------------------------------------------------------- 1 | const { formatAmount, expandDecimals, bigNumberify } = require("../../test/shared/utilities") 2 | 3 | const feeReference = require("../../fee-reference.json") 4 | const uniswapFeeReference = require("../../uniswap-fee-reference.json") 5 | 6 | async function main() { 7 | if (feeReference.refTimestamp !== uniswapFeeReference.refTimestamp) { 8 | throw new Error("feeReference.refTimestamp !== uniswapFeeReference.refTimestamp") 9 | } 10 | 11 | if (feeReference.refTimestamp > Date.now()) { 12 | throw new Error(`refTimestamp is later than current time ${feeReference.refTimestamp}`) 13 | } 14 | 15 | const allowedDelay = 10 * 60 * 60 * 1000 16 | if (feeReference.refTimestamp < Date.now() - allowedDelay) { 17 | throw new Error(`refTimestamp is older than the allowed delay`) 18 | } 19 | 20 | const uniswapFees = bigNumberify(uniswapFeeReference.delta).mul(feeReference.nativeTokenPrice.arbitrum).div(expandDecimals(1, 18)) 21 | 22 | const text = `\n` + 23 | `Weekly Rewards Info 🔹\n` + 24 | `\n` + 25 | `$${formatAmount(feeReference.totalFees, 30, 2, true)} collected in the past 7 days\n` + 26 | `\n` + 27 | `$${formatAmount(feeReference.arbFees, 30, 2, true)} (ARB), $${formatAmount(feeReference.avaxFees, 30, 2, true)} (AVAX), $${formatAmount(uniswapFees, 30, 2, true)} (GMX-ETH)\n` + 28 | `\n` + 29 | `To buy and stake $GMX / $GLP: https://gmx.io\n` + 30 | `\n` 31 | 32 | console.info(text) 33 | 34 | const referralText = `Trader Rebates: $${formatAmount(feeReference.traderRebates, 30, 2, true)}\n` + 35 | `Affiliate Rewards: $${formatAmount(feeReference.affiliateRewards, 30, 2, true)}\n` 36 | 37 | console.info(referralText) 38 | } 39 | 40 | main() 41 | -------------------------------------------------------------------------------- /scripts/peripherals/serverFees.js: -------------------------------------------------------------------------------- 1 | const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); 2 | 3 | const { 4 | ARBITRUM_SERVER_ADMIN_API_KEY, 5 | ARBITRUM_FEE_URL, 6 | AVAX_SERVER_ADMIN_API_KEY, 7 | AVAX_FEE_URL, 8 | } = require("../../env.json") 9 | 10 | const SECONDS_PER_DAY = 24 * 60 * 60 11 | 12 | async function getArbValues() { 13 | const apiKey = ARBITRUM_SERVER_ADMIN_API_KEY 14 | const feeUrl = ARBITRUM_FEE_URL 15 | const feeUsd = "2,048,125.75" 16 | 17 | return { apiKey, feeUrl, feeUsd } 18 | } 19 | 20 | async function getAvaxValues() { 21 | const apiKey = AVAX_SERVER_ADMIN_API_KEY 22 | const feeUrl = AVAX_FEE_URL 23 | const feeUsd = "243,246.15" 24 | 25 | return { apiKey, feeUrl, feeUsd } 26 | } 27 | 28 | async function postFees({ apiKey, feeUrl, feeUsd, timestamp }) { 29 | timestamp = parseInt(timestamp) 30 | 31 | if (isNaN(timestamp)) { 32 | throw new Error("Invalid timestamp") 33 | } 34 | 35 | const id = (parseInt(timestamp / SECONDS_PER_DAY) * SECONDS_PER_DAY).toString() 36 | feeUsd = parseInt(feeUsd.replaceAll(",", "")) 37 | 38 | if (isNaN(feeUsd)) { 39 | throw new Error("Invalid feeUsd") 40 | } 41 | 42 | const body = JSON.stringify({ 43 | key: apiKey, 44 | id, 45 | timestamp, 46 | feeUsd 47 | }) 48 | 49 | console.log("sending update", { id, timestamp, feeUsd }) 50 | const result = await fetch(feeUrl, { 51 | method: 'POST', 52 | headers: {'Content-Type': 'application/json'}, 53 | body 54 | }) 55 | 56 | const resultContent = await result.text() 57 | console.log("result", result.status, resultContent) 58 | } 59 | 60 | module.exports = { 61 | getArbValues, 62 | getAvaxValues, 63 | postFees 64 | } 65 | -------------------------------------------------------------------------------- /scripts/core/setReferralCodeOwner.js: -------------------------------------------------------------------------------- 1 | const { contractAt , sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function getArbValues() { 9 | const referralStorage = await contractAt("ReferralStorage", "0xe6fab3F0c7199b0d34d7FbE83394fc0e0D06e99d") 10 | 11 | return { referralStorage } 12 | } 13 | 14 | async function getAvaxValues() { 15 | const referralStorage = await contractAt("ReferralStorage", "0x827ED045002eCdAbEb6e2b0d1604cf5fC3d322F8") 16 | 17 | return { referralStorage } 18 | } 19 | 20 | async function getValues() { 21 | if (network === "arbitrum") { 22 | return getArbValues() 23 | } 24 | 25 | if (network === "avax") { 26 | return getAvaxValues() 27 | } 28 | } 29 | 30 | async function main() { 31 | const { referralStorage } = await getValues() 32 | const timelock = await contractAt("Timelock", await referralStorage.gov()) 33 | 34 | const code = "lotto" 35 | const encodedCode = ethers.utils.formatBytes32String(code) 36 | const account = await referralStorage.codeOwners(encodedCode) 37 | console.log("current account", account) 38 | 39 | if (account !== ethers.constants.AddressZero) { 40 | throw new Error("Code already taken") 41 | } 42 | 43 | const newAccount = "
" 44 | await sendTxn(timelock.govSetCodeOwner(referralStorage.address, encodedCode, newAccount), "referralStorage.govSetCodeOwner") 45 | } 46 | 47 | main() 48 | .then(() => process.exit(0)) 49 | .catch(error => { 50 | console.error(error) 51 | process.exit(1) 52 | }) 53 | -------------------------------------------------------------------------------- /contracts/core/test/ShortsTrackerTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | import "../ShortsTracker.sol"; 4 | 5 | pragma solidity 0.6.12; 6 | 7 | contract ShortsTrackerTest is ShortsTracker { 8 | constructor(address _vault) public ShortsTracker(_vault) {} 9 | 10 | function getNextGlobalShortDataWithRealisedPnl( 11 | address _indexToken, 12 | uint256 _nextPrice, 13 | uint256 _sizeDelta, 14 | int256 _realisedPnl, 15 | bool _isIncrease 16 | ) public view returns (uint256, uint256) { 17 | uint256 averagePrice = globalShortAveragePrices[_indexToken]; 18 | uint256 priceDelta = averagePrice > _nextPrice ? averagePrice.sub(_nextPrice) : _nextPrice.sub(averagePrice); 19 | 20 | uint256 nextSize; 21 | uint256 delta; 22 | // avoid stack to deep 23 | { 24 | uint256 size = vault.globalShortSizes(_indexToken); 25 | nextSize = _isIncrease ? size.add(_sizeDelta) : size.sub(_sizeDelta); 26 | 27 | if (nextSize == 0) { 28 | return (0, 0); 29 | } 30 | 31 | if (averagePrice == 0) { 32 | return (nextSize, _nextPrice); 33 | } 34 | 35 | delta = size.mul(priceDelta).div(averagePrice); 36 | } 37 | 38 | uint256 nextAveragePrice = _getNextGlobalAveragePrice( 39 | averagePrice, 40 | _nextPrice, 41 | nextSize, 42 | delta, 43 | _realisedPnl 44 | ); 45 | 46 | return (nextSize, nextAveragePrice); 47 | } 48 | 49 | function setGlobalShortAveragePrice(address _token, uint256 _averagePrice) public { 50 | globalShortAveragePrices[_token] = _averagePrice; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /contracts/core/interfaces/IVaultUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | interface IVaultUtils { 6 | function updateCumulativeFundingRate(address _collateralToken, address _indexToken) external returns (bool); 7 | function validateIncreasePosition(address _account, address _collateralToken, address _indexToken, uint256 _sizeDelta, bool _isLong) external view; 8 | function validateDecreasePosition(address _account, address _collateralToken, address _indexToken, uint256 _collateralDelta, uint256 _sizeDelta, bool _isLong, address _receiver) external view; 9 | function validateLiquidation(address _account, address _collateralToken, address _indexToken, bool _isLong, bool _raise) external view returns (uint256, uint256); 10 | function getEntryFundingRate(address _collateralToken, address _indexToken, bool _isLong) external view returns (uint256); 11 | function getPositionFee(address _account, address _collateralToken, address _indexToken, bool _isLong, uint256 _sizeDelta) external view returns (uint256); 12 | function getFundingFee(address _account, address _collateralToken, address _indexToken, bool _isLong, uint256 _size, uint256 _entryFundingRate) external view returns (uint256); 13 | function getBuyUsdgFeeBasisPoints(address _token, uint256 _usdgAmount) external view returns (uint256); 14 | function getSellUsdgFeeBasisPoints(address _token, uint256 _usdgAmount) external view returns (uint256); 15 | function getSwapFeeBasisPoints(address _tokenIn, address _tokenOut, uint256 _usdgAmount) external view returns (uint256); 16 | function getFeeBasisPoints(address _token, uint256 _usdgDelta, uint256 _feeBasisPoints, uint256 _taxBasisPoints, bool _increment) external view returns (uint256); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/peripherals/BatchSender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../libraries/token/IERC20.sol"; 6 | import "../libraries/math/SafeMath.sol"; 7 | 8 | import "../access/Governable.sol"; 9 | 10 | contract BatchSender is Governable { 11 | using SafeMath for uint256; 12 | 13 | mapping (address => bool) public isHandler; 14 | 15 | event BatchSend( 16 | uint256 indexed typeId, 17 | address indexed token, 18 | address[] accounts, 19 | uint256[] amounts 20 | ); 21 | 22 | modifier onlyHandler() { 23 | require(isHandler[msg.sender], "BatchSender: forbidden"); 24 | _; 25 | } 26 | 27 | constructor() public { 28 | isHandler[msg.sender] = true; 29 | } 30 | 31 | function setHandler(address _handler, bool _isActive) external onlyGov { 32 | isHandler[_handler] = _isActive; 33 | } 34 | 35 | function send(IERC20 _token, address[] memory _accounts, uint256[] memory _amounts) public onlyHandler { 36 | _send(_token, _accounts, _amounts, 0); 37 | } 38 | 39 | function sendAndEmit(IERC20 _token, address[] memory _accounts, uint256[] memory _amounts, uint256 _typeId) public onlyHandler { 40 | _send(_token, _accounts, _amounts, _typeId); 41 | } 42 | 43 | function _send(IERC20 _token, address[] memory _accounts, uint256[] memory _amounts, uint256 _typeId) private { 44 | for (uint256 i = 0; i < _accounts.length; i++) { 45 | address account = _accounts[i]; 46 | uint256 amount = _amounts[i]; 47 | _token.transferFrom(msg.sender, account, amount); 48 | } 49 | 50 | emit BatchSend(_typeId, address(_token), _accounts, _amounts); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /scripts/core/whitelistTokens.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toChainlinkPrice } = require("../../test/shared/chainlink") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function main() { 9 | const vault = await contractAt("Vault", "0x9ab2De34A33fB459b538c43f251eB825645e8595") 10 | const vaultPriceFeed = await contractAt("VaultPriceFeed", "0x131238112aa25c0D8CD237a6c384d1A86D2BB152") 11 | console.log("vault", vault.address) 12 | console.log("vaultPriceFeed", vaultPriceFeed.address) 13 | 14 | const { avax, btc, eth, mim, usdce, usdc } = tokens 15 | const tokenArr = [mim, usdce, usdc] 16 | 17 | for (const token of tokenArr) { 18 | await sendTxn(vaultPriceFeed.setTokenConfig( 19 | token.address, // _token 20 | token.priceFeed, // _priceFeed 21 | token.priceDecimals, // _priceDecimals 22 | token.isStrictStable // _isStrictStable 23 | ), `vaultPriceFeed.setTokenConfig(${token.name}) ${token.address} ${token.priceFeed}`) 24 | 25 | await sendTxn(vault.setTokenConfig( 26 | token.address, // _token 27 | token.decimals, // _tokenDecimals 28 | token.tokenWeight, // _tokenWeight 29 | token.minProfitBps, // _minProfitBps 30 | expandDecimals(token.maxUsdgAmount, 18), // _maxUsdgAmount 31 | token.isStable, // _isStable 32 | token.isShortable // _isShortable 33 | ), `vault.setTokenConfig(${token.name}) ${token.address}`) 34 | } 35 | } 36 | 37 | main() 38 | .then(() => process.exit(0)) 39 | .catch(error => { 40 | console.error(error) 41 | process.exit(1) 42 | }) 43 | -------------------------------------------------------------------------------- /scripts/core/priceFeedSetTokenConfig.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt, sendTxn, readTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toChainlinkPrice } = require("../../test/shared/chainlink") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function main() { 9 | const signer = await getFrameSigner() 10 | 11 | const vault = await contractAt("Vault", "0x489ee077994B6658eAfA855C308275EAd8097C4A") 12 | 13 | const priceFeed = await contractAt("VaultPriceFeed", await vault.priceFeed()) 14 | const priceFeedGov = await priceFeed.gov() 15 | const priceFeedTimelock = await contractAt("PriceFeedTimelock", priceFeedGov, signer) 16 | 17 | const priceFeedMethod = "signalPriceFeedSetTokenConfig" 18 | // const priceFeedMethod = "priceFeedSetTokenConfig" 19 | 20 | console.log("vault", vault.address) 21 | console.log("priceFeed", priceFeed.address) 22 | console.log("priceFeedTimelock", priceFeedTimelock.address) 23 | console.log("priceFeedMethod", priceFeedMethod) 24 | 25 | const { usdc } = tokens 26 | const tokenArr = [usdc] 27 | 28 | for (const token of tokenArr) { 29 | await sendTxn(priceFeedTimelock[priceFeedMethod]( 30 | priceFeed.address, // _vaultPriceFeed 31 | token.address, // _token 32 | token.priceFeed, // _priceFeed 33 | token.priceDecimals, // _priceDecimals 34 | token.isStrictStable // _isStrictStable 35 | ), `priceFeed.${priceFeedMethod}(${token.name}) ${token.address}`) 36 | } 37 | } 38 | 39 | main() 40 | .then(() => process.exit(0)) 41 | .catch(error => { 42 | console.error(error) 43 | process.exit(1) 44 | }) 45 | -------------------------------------------------------------------------------- /scripts/staking/batchSendEsGmx.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { DISTRIBUTION_LIST } = require("../../data/esGmxDistribution/distributionList1") 4 | 5 | async function main() { 6 | const wallet = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 7 | const esGmx = await contractAt("EsGMX", "0xf42Ae1D54fd613C9bb14810b0588FaAa09a426cA") 8 | const batchSender = await contractAt("BatchSender", "0x401Ab96410BcdCA81b79c68D0D664D478906C184") 9 | const distributionList = DISTRIBUTION_LIST 10 | 11 | await sendTxn(esGmx.approve(batchSender.address, expandDecimals(100 * 1000, 18)), "esGmx.approve") 12 | console.log("processing list", distributionList.length) 13 | 14 | const batchSize = 30 15 | let accounts = [] 16 | let amounts = [] 17 | 18 | for (let i = 0; i < distributionList.length; i++) { 19 | const [account, amount] = distributionList[i] 20 | accounts.push(account) 21 | amounts.push(ethers.utils.parseUnits(amount, 18)) 22 | 23 | if (accounts.length === batchSize) { 24 | console.log("accounts", accounts) 25 | console.log("amounts", amounts.map(amount => amount.toString())) 26 | console.log("sending batch", i, accounts.length, amounts.length) 27 | await sendTxn(batchSender.send(esGmx.address, accounts, amounts), "batchSender.send") 28 | 29 | accounts = [] 30 | amounts = [] 31 | } 32 | } 33 | 34 | if (accounts.length > 0) { 35 | console.log("sending final batch", distributionList.length, accounts.length, amounts.length) 36 | await sendTxn(batchSender.send(esGmx.address, accounts, amounts), "batchSender.send") 37 | } 38 | } 39 | 40 | main() 41 | .then(() => process.exit(0)) 42 | .catch(error => { 43 | console.error(error) 44 | process.exit(1) 45 | }) 46 | -------------------------------------------------------------------------------- /scripts/core/claimTokens.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const receiver = { address: "0x9f169c2189A2d975C18965DE985936361b4a9De9" } 6 | const usdg = await contractAt("YieldToken", "0x85E76cbf4893c1fbcB34dCF1239A91CE2A4CF5a7") 7 | const xgmt = await contractAt("YieldToken", "0xe304ff0983922787Fd84BC9170CD21bF78B16B10") 8 | const usdgYieldTracker = await contractAt("YieldTracker", "0x0EF0Cf825B8e9F89A43FfD392664131cFB4cfA89") 9 | const xgmtYieldTracker = await contractAt("YieldTracker", "0x82A012A9b3003b18B6bCd6052cbbef7Fa4892e80") 10 | const gmtUsdgPair = { address: "0xa41e57459f09a126F358E118b693789d088eA8A0" } 11 | const xgmtUsdgPair = { address: "0x0b622208fc0691C2486A3AE6B7C875b4A174b317" } 12 | const busdgUsdgPair = { address: "0x7Fea0c6022D81EE17146324E4F55f6A02E138Dab" } 13 | const autoUsdgPair = { address: "0x0523FD5C53ea5419B4DAF656BC1b157dDFE3ce50" } 14 | 15 | const wbnbClaimableForXgmtPair = await xgmtYieldTracker.claimable(xgmtUsdgPair.address) 16 | console.log(`claimable: ${ethers.utils.formatUnits(wbnbClaimableForXgmtPair, 18)} WBNB`) 17 | await sendTxn(xgmt.recoverClaim(xgmtUsdgPair.address, receiver.address), "recoverClaim") 18 | 19 | const accounts = [gmtUsdgPair, xgmtUsdgPair, busdgUsdgPair, autoUsdgPair] 20 | 21 | for (let i = 0; i < accounts.length; i++) { 22 | const account = accounts[i] 23 | const claimable = await usdgYieldTracker.claimable(account.address) 24 | console.log(`claimable ${i}: ${ethers.utils.formatUnits(claimable, 18)} WBNB`) 25 | await sendTxn(usdg.recoverClaim(account.address, receiver.address), `recoverClaim ${i}`) 26 | } 27 | } 28 | 29 | main() 30 | .then(() => process.exit(0)) 31 | .catch(error => { 32 | console.error(error) 33 | process.exit(1) 34 | }) 35 | -------------------------------------------------------------------------------- /scripts/core/write.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const signer = await getFrameSigner() 6 | 7 | // const glpManager = await contractAt("GlpManager", "0x14fB4767dc9E10F96faaF37Ad24DE3E498cC344B") 8 | // await sendTxn(glpManager.setCooldownDuration(10 * 60), "glpManager.setCooldownDuration") 9 | // const gmx = await contractAt("GMX", "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a", signer) 10 | // const esGmx = await contractAt("EsGMX", "0xf42Ae1D54fd613C9bb14810b0588FaAa09a426cA") 11 | 12 | // const stakedGmxTracker = await contractAt("RewardTracker", "0x908C4D94D34924765f1eDc22A1DD098397c59dD4") 13 | // await sendTxn(gmx.approve(stakedGmxTracker.address, 0), "gmx.approve(stakedGmxTracker)") 14 | 15 | // const rewardRouter = await contractAt("RewardRouter", "0x67b789D48c926006F5132BFCe4e976F0A7A63d5D") 16 | // await sendTxn(rewardRouter.stakeEsGmx(expandDecimals(1, 18)), "rewardRouter.stakeEsGmx") 17 | 18 | // const vaultPriceFeed = await contractAt("VaultPriceFeed", "0x30333ce00AC3025276927672aAeFd80f22E89E54") 19 | // await sendTxn(vaultPriceFeed.setPriceSampleSpace(2), "vaultPriceFeed.setPriceSampleSpace") 20 | 21 | // const gmx = await contractAt("GMX", "0x62edc0692BD897D2295872a9FFCac5425011c661") 22 | // await sendTxn(gmx.approve("0x62edc0692BD897D2295872a9FFCac5425011c661", 100, { nonce: 714 }), "gmx.approve") 23 | 24 | const timelock = await contractAt("Timelock", "0xe7e740fa40ca16b15b621b49de8e9f0d69cf4858", signer) 25 | await sendTxn(timelock.signalApprove("0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a", "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a", 1), "approve") 26 | } 27 | 28 | main() 29 | .then(() => process.exit(0)) 30 | .catch(error => { 31 | console.error(error) 32 | process.exit(1) 33 | }) 34 | -------------------------------------------------------------------------------- /scripts/staking/checkStakedAmounts.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const stakeGmxList = require("../../data/stakeGmxList.json") 4 | 5 | function sleep(ms) { 6 | return new Promise(resolve => setTimeout(resolve, ms)); 7 | } 8 | 9 | async function main() { 10 | const { formatEther } = ethers.utils 11 | const wallet = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 12 | const gmx = await contractAt("GMX", "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a"); 13 | const rewardRouter = await contractAt("RewardRouter", "0x7B01aCf6e7e9CC276e644ac65D770c1131583453") 14 | const stakedGmxTracker = await contractAt("RewardTracker", "0x908C4D94D34924765f1eDc22A1DD098397c59dD4") 15 | const bonusGmxTracker = await contractAt("RewardTracker", "0x4d268a7d4C16ceB5a606c173Bd974984343fea13") 16 | 17 | const batchSize = 20 18 | 19 | for (let i = 0; i < stakeGmxList.length; i++) { 20 | const { address, balance } = stakeGmxList[i] 21 | 22 | const stakedAmount = await stakedGmxTracker.stakedAmounts(address) 23 | console.log(`${i} ${address}: ${formatEther(balance)}, ${formatEther(stakedAmount)}`) 24 | 25 | if (!stakedAmount.eq(balance)) { 26 | throw new Error(`Invalid stakedAmount: ${address}, ${formatEther(balance)}, ${formatEther(stakedAmount).toString()}`) 27 | } 28 | 29 | const pendingRewards = await stakedGmxTracker.claimable(address) 30 | const pendingBonus = await bonusGmxTracker.claimable(address) 31 | 32 | console.log(`${address}: ${formatEther(pendingRewards).toString()}, ${formatEther(pendingBonus).toString()}`) 33 | 34 | if (i % batchSize === 0) { 35 | await sleep(1) 36 | } 37 | } 38 | } 39 | 40 | main() 41 | .then(() => process.exit(0)) 42 | .catch(error => { 43 | console.error(error) 44 | process.exit(1) 45 | }) 46 | -------------------------------------------------------------------------------- /scripts/peripherals/batchSend.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { DISTRIBUTION_LIST } = require("../../data/batchSend/competitionNovBatch2") 4 | 5 | async function main() { 6 | const wallet = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 7 | const batchSender = await contractAt("BatchSender", "0x401Ab96410BcdCA81b79c68D0D664D478906C184") 8 | const distributionList = DISTRIBUTION_LIST 9 | const token = await contractAt("Token", "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8") 10 | const tokenDecimals = 6 11 | 12 | await sendTxn(token.approve(batchSender.address, expandDecimals(125 * 1000, tokenDecimals)), "token.approve") 13 | console.log("processing list", distributionList.length) 14 | 15 | const batchSize = 20 16 | let accounts = [] 17 | let amounts = [] 18 | 19 | for (let i = 0; i < distributionList.length; i++) { 20 | const [account, amount] = distributionList[i] 21 | accounts.push(account) 22 | amounts.push(ethers.utils.parseUnits(amount, tokenDecimals)) 23 | 24 | if (accounts.length === batchSize) { 25 | console.log("accounts", accounts) 26 | console.log("amounts", amounts.map(amount => amount.toString())) 27 | console.log("sending batch", i, accounts.length, amounts.length) 28 | await sendTxn(batchSender.send(token.address, accounts, amounts), "batchSender.send") 29 | 30 | accounts = [] 31 | amounts = [] 32 | } 33 | } 34 | 35 | if (accounts.length > 0) { 36 | console.log("sending final batch", distributionList.length, accounts.length, amounts.length) 37 | await sendTxn(batchSender.send(token.address, accounts, amounts), "batchSender.send") 38 | } 39 | } 40 | 41 | main() 42 | .then(() => process.exit(0)) 43 | .catch(error => { 44 | console.error(error) 45 | process.exit(1) 46 | }) 47 | -------------------------------------------------------------------------------- /scripts/staking/batchSetBonusRewards.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { DISTRIBUTION_LIST } = require("../../data/esGmxDistribution/distributionList1") 4 | 5 | async function main() { 6 | const signer = await getFrameSigner() 7 | 8 | const wallet = { address: "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" } 9 | const timelock = await contractAt("Timelock", "0x3F3E77421E30271568eF7A0ab5c5F2667675341e", signer) 10 | const esGmx = await contractAt("EsGMX", "0xf42Ae1D54fd613C9bb14810b0588FaAa09a426cA") 11 | const glpVester = await contractAt("Vester", "0xA75287d2f8b217273E7FCD7E86eF07D33972042E") 12 | const distributionList = DISTRIBUTION_LIST 13 | 14 | const batchSize = 30 15 | let accounts = [] 16 | let amounts = [] 17 | 18 | for (let i = 0; i < distributionList.length; i++) { 19 | const [account, amount] = distributionList[i] 20 | accounts.push(account) 21 | amounts.push(ethers.utils.parseUnits(amount, 18)) 22 | 23 | if (accounts.length === batchSize) { 24 | console.log("accounts", accounts) 25 | console.log("amounts", amounts.map(amount => amount.toString())) 26 | console.log("sending batch", i, accounts.length, amounts.length) 27 | await sendTxn(timelock.batchSetBonusRewards(glpVester.address, accounts, amounts), "timelock.batchSetBonusRewards") 28 | 29 | accounts = [] 30 | amounts = [] 31 | } 32 | } 33 | 34 | if (accounts.length > 0) { 35 | console.log("sending final batch", distributionList.length, accounts.length, amounts.length) 36 | await sendTxn(timelock.batchSetBonusRewards(glpVester.address, accounts, amounts), "timelock.batchSetBonusRewards") 37 | } 38 | } 39 | 40 | main() 41 | .then(() => process.exit(0)) 42 | .catch(error => { 43 | console.error(error) 44 | process.exit(1) 45 | }) 46 | -------------------------------------------------------------------------------- /contracts/libraries/introspection/ERC165.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.0; 4 | 5 | import "./IERC165.sol"; 6 | 7 | /** 8 | * @dev Implementation of the {IERC165} interface. 9 | * 10 | * Contracts may inherit from this and call {_registerInterface} to declare 11 | * their support of an interface. 12 | */ 13 | contract ERC165 is IERC165 { 14 | /* 15 | * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 16 | */ 17 | bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; 18 | 19 | /** 20 | * @dev Mapping of interface ids to whether or not it's supported. 21 | */ 22 | mapping(bytes4 => bool) private _supportedInterfaces; 23 | 24 | constructor () internal { 25 | // Derived contracts need only register support for their own interfaces, 26 | // we register support for ERC165 itself here 27 | _registerInterface(_INTERFACE_ID_ERC165); 28 | } 29 | 30 | /** 31 | * @dev See {IERC165-supportsInterface}. 32 | * 33 | * Time complexity O(1), guaranteed to always use less than 30 000 gas. 34 | */ 35 | function supportsInterface(bytes4 interfaceId) public view override returns (bool) { 36 | return _supportedInterfaces[interfaceId]; 37 | } 38 | 39 | /** 40 | * @dev Registers the contract as an implementer of the interface defined by 41 | * `interfaceId`. Support of the actual ERC165 interface is automatic and 42 | * registering its interface id is not required. 43 | * 44 | * See {IERC165-supportsInterface}. 45 | * 46 | * Requirements: 47 | * 48 | * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). 49 | */ 50 | function _registerInterface(bytes4 interfaceId) internal virtual { 51 | require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); 52 | _supportedInterfaces[interfaceId] = true; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /scripts/referrals/saveDistributionData.js: -------------------------------------------------------------------------------- 1 | const { ArgumentParser } = require('argparse'); 2 | const { saveDistributionData } = require("./distributionData") 3 | 4 | async function main() { 5 | const parser = new ArgumentParser({ 6 | description: 'Get distribution data' 7 | }); 8 | parser.add_argument('-n', '--network', { 9 | help: 'Network: arbitrum, avalanche', 10 | required: true 11 | }); 12 | parser.add_argument('-f', '--from-date', { 13 | help: 'Date from. E.g. 2022-04-20', 14 | default: "2022-04-20" 15 | }); 16 | parser.add_argument('-t', '--to-date', { 17 | help: 'Date to. Exclusive. E.g. 2022-04-27', 18 | default: "2022-04-27" 19 | }); 20 | parser.add_argument('-a', '--account', { help: 'Account address' }) 21 | parser.add_argument('-g', '--gmx-price', { help: 'GMX TWAP price' }) 22 | parser.add_argument('-e', '--esgmx-rewards', { 23 | help: 'Amount of EsGMX to distribute to Tier 3', 24 | default: "5000" 25 | }) 26 | 27 | const args = parser.parse_args() 28 | 29 | const fromDate = new Date(args.from_date) 30 | const fromTimestamp = parseInt(+fromDate / 1000) 31 | const toDate = new Date(args.to_date) 32 | const toTimestamp = parseInt(+toDate / 1000) 33 | 34 | console.log("Running script to get distribution data") 35 | console.log("Network: %s", args.network) 36 | console.log("From: %s (timestamp %s)", fromDate.toISOString().substring(0, 10), fromTimestamp) 37 | console.log("To (exclusively): %s (timestamp %s)", toDate.toISOString().substring(0, 10), toTimestamp) 38 | if (args.account) { 39 | console.log("Account: %s", args.account) 40 | } 41 | 42 | await saveDistributionData( 43 | args.network, 44 | fromTimestamp, 45 | toTimestamp, 46 | args.account, 47 | args.gmx_price, 48 | args.esgmx_rewards 49 | ) 50 | } 51 | 52 | main() 53 | .then(() => process.exit(0)) 54 | .catch(error => { 55 | console.error(error) 56 | process.exit(1) 57 | }) 58 | -------------------------------------------------------------------------------- /scripts/tokens/mintSnapshotToken.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const parse = require('csv-parse') 3 | const { contractAt, sendTxn } = require("../shared/helpers") 4 | 5 | const processFile = async (dir, file) => { 6 | records = [] 7 | const parser = fs 8 | .createReadStream(dir + "/" + file) 9 | .pipe(parse({ columns: true, delimiter: ',' })) 10 | parser.on('error', function(err){ 11 | console.error(err.message) 12 | }) 13 | for await (const record of parser) { 14 | records.push(record) 15 | } 16 | return records 17 | } 18 | 19 | async function main() { 20 | const token = await contractAt("SnapshotToken", "0xf3674f065301e0866715dd094bc7a51397e457f3") 21 | const snapshotFile = "snapshotBalance1.csv" 22 | const dir = "./data/snapshotBalance" 23 | 24 | const records = await processFile(dir, snapshotFile) 25 | console.log("records", records.length) 26 | 27 | const batchSize = 100 28 | let accounts = [] 29 | let amounts = [] 30 | 31 | for (let i = 0; i < records.length; i++) { 32 | const item = records[i] 33 | try { 34 | const amount = ethers.utils.parseEther(item.Balance) 35 | accounts.push(item.HolderAddress) 36 | amounts.push(amount.toString()) 37 | } catch (e) { 38 | console.log(e) 39 | continue 40 | } 41 | 42 | if (accounts.length === batchSize) { 43 | console.log("accounts", accounts) 44 | console.log("amounts", amounts) 45 | console.log("sending batch", i, accounts.length, amounts.length) 46 | await sendTxn(token.batchMint(accounts, amounts), "token.batchMint") 47 | 48 | accounts = [] 49 | amounts = [] 50 | } 51 | } 52 | 53 | if (accounts.length > 0) { 54 | console.log("sending final batch", records.length, accounts.length, amounts.length) 55 | await sendTxn(token.batchMint(accounts, amounts), "token.batchMint") 56 | } 57 | } 58 | 59 | main() 60 | .then(() => process.exit(0)) 61 | .catch(error => { 62 | console.error(error) 63 | process.exit(1) 64 | }) 65 | -------------------------------------------------------------------------------- /contracts/core/test/MaliciousTraderTest.sol: -------------------------------------------------------------------------------- 1 | 2 | // SPDX-License-Identifier: MIT 3 | 4 | import "hardhat/console.sol"; 5 | 6 | pragma solidity ^0.6.0; 7 | 8 | contract MaliciousTraderTest { 9 | event Received(); 10 | 11 | address public positionRouter; 12 | 13 | constructor(address _positionRouter) public { 14 | positionRouter = _positionRouter; 15 | } 16 | 17 | receive() external payable { 18 | // just consume lot of gas 19 | uint256 a; 20 | for (uint i = 0; i < 1000000; i++) { 21 | a = a * i; 22 | } 23 | emit Received(); 24 | } 25 | 26 | function createIncreasePositionETH( 27 | address[] memory _path, 28 | address _indexToken, 29 | uint256 _minOut, 30 | uint256 _sizeDelta, 31 | bool _isLong, 32 | uint256 _acceptablePrice, 33 | uint256 _executionFee, 34 | bytes32 _referralCode, 35 | address _callbackTarget 36 | ) external payable { 37 | console.log("path.length %s indexToken %s minOut %s", _path.length, _indexToken, _minOut); 38 | console.log("sizeDelta %s isLong %s acceptablePrice %s", _sizeDelta, _isLong, _acceptablePrice); 39 | console.log("executionFee %s callbackTarget %s", _executionFee, _callbackTarget); 40 | (bool success, bytes memory reason) = positionRouter.call{value: msg.value}( 41 | abi.encodeWithSignature( 42 | "createIncreasePositionETH(address[],address,uint256,uint256,bool,uint256,uint256,bytes32,address)", 43 | _path, 44 | _indexToken, 45 | _minOut, 46 | _sizeDelta, 47 | _isLong, 48 | _acceptablePrice, 49 | _executionFee, 50 | _referralCode, 51 | _callbackTarget 52 | ) 53 | ); 54 | console.log("success: %s reason: '%s'", success, string(reason)); 55 | require(success, string(reason)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /scripts/peripherals/deployGmxTimelock.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | 6 | const { AddressZero } = ethers.constants 7 | 8 | async function runForArbitrum() { 9 | const admin = "0x49B373D422BdA4C6BfCdd5eC1E48A9a26fdA2F8b" 10 | const rewardManager = { address: AddressZero } 11 | const buffer = 24 * 60 * 60 12 | const longBuffer = 7 * 24 * 60 * 60 13 | const tokenManager = { address: "0xddDc546e07f1374A07b270b7d863371e575EA96A" } 14 | const mintReceiver = { address: AddressZero } 15 | const maxTokenSupply = expandDecimals("13250000", 18) 16 | 17 | const timelock = await deployContract("GmxTimelock", [ 18 | admin, 19 | buffer, 20 | longBuffer, 21 | rewardManager.address, 22 | tokenManager.address, 23 | mintReceiver.address, 24 | maxTokenSupply 25 | ], "GmxTimelock", { gasLimit: 100000000 }) 26 | } 27 | 28 | async function runForAvax() { 29 | const admin = "0x49B373D422BdA4C6BfCdd5eC1E48A9a26fdA2F8b" 30 | const rewardManager = { address: ethers.constants.AddressZero } 31 | const buffer = 24 * 60 * 60 32 | const longBuffer = 7 * 24 * 60 * 60 33 | const tokenManager = { address: "0x8b25Ba1cAEAFaB8e9926fabCfB6123782e3B4BC2" } 34 | const mintReceiver = { address: AddressZero } 35 | const maxTokenSupply = expandDecimals("13250000", 18) 36 | 37 | const timelock = await deployContract("GmxTimelock", [ 38 | admin, 39 | buffer, 40 | longBuffer, 41 | rewardManager.address, 42 | tokenManager.address, 43 | mintReceiver.address, 44 | maxTokenSupply 45 | ]) 46 | } 47 | 48 | async function main() { 49 | if (network === "avax") { 50 | await runForAvax() 51 | return 52 | } 53 | 54 | await runForArbitrum() 55 | } 56 | 57 | main() 58 | .then(() => process.exit(0)) 59 | .catch(error => { 60 | console.error(error) 61 | process.exit(1) 62 | }) 63 | -------------------------------------------------------------------------------- /scripts/core/deployGlpManagerV2.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt , sendTxn, writeTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function getArbValues() { 9 | const vault = { address: "0x489ee077994B6658eAfA855C308275EAd8097C4A" } 10 | const usdg = { address: "0x45096e7aA921f27590f8F19e457794EB09678141" } 11 | const glp = { address: "0x4277f8F2c384827B5273592FF7CeBd9f2C1ac258" } 12 | const shortsTracker = { address: "0xf58eEc83Ba28ddd79390B9e90C4d3EbfF1d434da" } 13 | 14 | return { vault, usdg, glp, shortsTracker } 15 | } 16 | 17 | async function getAvaxValues() { 18 | const vault = { address: "0x9ab2De34A33fB459b538c43f251eB825645e8595" } 19 | const usdg = { address: "0xc0253c3cC6aa5Ab407b5795a04c28fB063273894" } 20 | const glp = { address: "0x01234181085565ed162a948b6a5e88758CD7c7b8" } 21 | const shortsTracker = { address: "0x9234252975484D75Fd05f3e4f7BdbEc61956D73a" } 22 | 23 | return { vault, usdg, glp, shortsTracker } 24 | } 25 | 26 | async function getValues() { 27 | if (network === "arbitrum") { 28 | return getArbValues() 29 | } 30 | 31 | if (network === "avax") { 32 | return getAvaxValues() 33 | } 34 | } 35 | 36 | async function main() { 37 | const { vault, usdg, glp, shortsTracker } = await getValues() 38 | 39 | const cooldownDuration = 0 40 | const glpManager = await deployContract("GlpManager", [vault.address, usdg.address, glp.address, shortsTracker.address, cooldownDuration]) 41 | 42 | await sendTxn(glpManager.setInPrivateMode(true), "glpManager.setInPrivateMode") 43 | 44 | writeTmpAddresses({ 45 | glpManager: glpManager.address 46 | }) 47 | } 48 | 49 | main() 50 | .then(() => process.exit(0)) 51 | .catch(error => { 52 | console.error(error) 53 | process.exit(1) 54 | }) 55 | -------------------------------------------------------------------------------- /scripts/core/deployReferralStorage.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt , sendTxn, readTmpAddresses, writeTmpAddresses } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function getArbValues() { 9 | const positionRouter = await contractAt("PositionRouter", "0x3D6bA331e3D9702C5e8A8d254e5d8a285F223aba") 10 | const positionManager = await contractAt("PositionManager", "0x87a4088Bd721F83b6c2E5102e2FA47022Cb1c831") 11 | 12 | return { positionRouter, positionManager } 13 | } 14 | 15 | async function getAvaxValues() { 16 | const positionRouter = await contractAt("PositionRouter", "0x195256074192170d1530527abC9943759c7167d8") 17 | const positionManager = await contractAt("PositionManager", "0xF2ec2e52c3b5F8b8bd5A3f93945d05628A233216") 18 | 19 | return { positionRouter, positionManager } 20 | } 21 | 22 | async function getValues() { 23 | if (network === "arbitrum") { 24 | return getArbValues() 25 | } 26 | 27 | if (network === "avax") { 28 | return getAvaxValues() 29 | } 30 | } 31 | 32 | async function main() { 33 | const { positionRouter, positionManager } = await getValues() 34 | // const referralStorage = await deployContract("ReferralStorage", []) 35 | const referralStorage = await contractAt("ReferralStorage", await positionRouter.referralStorage()) 36 | 37 | // await sendTxn(positionRouter.setReferralStorage(referralStorage.address), "positionRouter.setReferralStorage") 38 | // await sendTxn(positionManager.setReferralStorage(referralStorage.address), "positionManager.setReferralStorage") 39 | 40 | await sendTxn(referralStorage.setHandler(positionRouter.address, true), "referralStorage.setHandler(positionRouter)") 41 | } 42 | 43 | main() 44 | .then(() => process.exit(0)) 45 | .catch(error => { 46 | console.error(error) 47 | process.exit(1) 48 | }) 49 | -------------------------------------------------------------------------------- /scripts/peripherals/deployShortsTrackerTimelock.js: -------------------------------------------------------------------------------- 1 | const { 2 | deployContract, 3 | contractAt, 4 | sendTxn, 5 | getFrameSigner 6 | } = require("../shared/helpers") 7 | const { expandDecimals } = require("../../test/shared/utilities") 8 | const { toUsd } = require("../../test/shared/units"); 9 | const { getArgumentForSignature } = require("typechain"); 10 | 11 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 12 | 13 | async function getAvaxValues() { 14 | return { 15 | handlers: [ 16 | "0x02270A816FCca45cE078C8b3De0346Eebc90B227", // X Shorts Tracker Keeper 17 | ] 18 | } 19 | } 20 | 21 | async function getArbValues() { 22 | return { 23 | handlers: [ 24 | "0x75f6250b9CeED446b2F25385832dF08DB45a90b0", // X Shorts Tracker Keeper 25 | ] 26 | } 27 | } 28 | 29 | async function getValues() { 30 | if (network === "localhost") { 31 | return await getLocalhostValues() 32 | } 33 | 34 | if (network === "avax") { 35 | return await getAvaxValues() 36 | } 37 | 38 | if (network === "arbitrum") { 39 | return await getArbValues() 40 | } 41 | 42 | throw new Error("No values for network " + network) 43 | } 44 | 45 | async function main() { 46 | const signer = await getFrameSigner() 47 | 48 | const admin = "0x49B373D422BdA4C6BfCdd5eC1E48A9a26fdA2F8b" 49 | const { handlers } = await getValues() 50 | 51 | const buffer = 60 // 60 seconds 52 | const updateDelay = 300 // 300 seconds, 5 minutes 53 | const maxAveragePriceChange = 20 // 0.2% 54 | let shortsTrackerTimelock = await deployContract("ShortsTrackerTimelock", [admin, buffer, updateDelay, maxAveragePriceChange]) 55 | shortsTrackerTimelock = await contractAt("ShortsTrackerTimelock", shortsTrackerTimelock.address, signer) 56 | 57 | console.log("Setting handlers") 58 | for (const handler of handlers) { 59 | await sendTxn( 60 | shortsTrackerTimelock.setContractHandler(handler, true), 61 | `shortsTrackerTimelock.setContractHandler ${handler}` 62 | ) 63 | } 64 | } 65 | 66 | main() 67 | .then(() => process.exit(0)) 68 | .catch(error => { 69 | console.error(error) 70 | process.exit(1) 71 | }) 72 | -------------------------------------------------------------------------------- /scripts/tokens/deployAutoFarm.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const usdg = await contractAt("USDG", "0x85E76cbf4893c1fbcB34dCF1239A91CE2A4CF5a7") 6 | const wbnb = await contractAt("WETH", "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c") 7 | const xgmt = await contractAt("YieldToken", "0xe304ff0983922787Fd84BC9170CD21bF78B16B10") 8 | 9 | const autoUsdgPair = { address: "0x0523FD5C53ea5419B4DAF656BC1b157dDFE3ce50" } 10 | const autoUsdgFarm = await deployContract("YieldFarm", ["AUTO-USDG Farm", "AUTO-USDG:FARM", autoUsdgPair.address], "autoUsdgFarm") 11 | 12 | const autoUsdgFarmYieldTrackerXgmt = await deployContract("YieldTracker", [autoUsdgFarm.address], "autoUsdgFarmYieldTrackerXgmt") 13 | const autoUsdgFarmDistributorXgmt = await deployContract("TimeDistributor", [], "autoUsdgFarmDistributorXgmt") 14 | 15 | await sendTxn(autoUsdgFarmYieldTrackerXgmt.setDistributor(autoUsdgFarmDistributorXgmt.address), "autoUsdgFarmYieldTrackerXgmt.setDistributor") 16 | await sendTxn(autoUsdgFarmDistributorXgmt.setDistribution([autoUsdgFarmYieldTrackerXgmt.address], ["0"], [xgmt.address]), "autoUsdgFarmDistributorXgmt.setDistribution") 17 | 18 | const autoUsdgFarmYieldTrackerWbnb = await deployContract("YieldTracker", [autoUsdgFarm.address], "autoUsdgFarmYieldTrackerWbnb") 19 | const autoUsdgFarmDistributorWbnb = await deployContract("TimeDistributor", [], "autoUsdgFarmDistributorWbnb") 20 | 21 | await sendTxn(autoUsdgFarmYieldTrackerWbnb.setDistributor(autoUsdgFarmDistributorWbnb.address), "autoUsdgFarmYieldTrackerWbnb.setDistributor") 22 | await sendTxn(autoUsdgFarmDistributorWbnb.setDistribution([autoUsdgFarmYieldTrackerWbnb.address], ["0"], [wbnb.address]), "autoUsdgFarmDistributorWbnb.setDistribution") 23 | 24 | await sendTxn(autoUsdgFarm.setYieldTrackers([autoUsdgFarmYieldTrackerXgmt.address, autoUsdgFarmYieldTrackerWbnb.address]), "autoUsdgFarm.setYieldTrackers") 25 | } 26 | 27 | main() 28 | .then(() => process.exit(0)) 29 | .catch(error => { 30 | console.error(error) 31 | process.exit(1) 32 | }) 33 | -------------------------------------------------------------------------------- /scripts/peripherals/setPriceFeed.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn, getFrameSigner } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | 6 | async function getArbValues() { 7 | const vault = await contractAt("Vault", "0x489ee077994B6658eAfA855C308275EAd8097C4A") 8 | const nextPriceFeed = await contractAt("VaultPriceFeed", "0x2d68011bcA022ed0E474264145F46CC4de96a002") 9 | return { vault, nextPriceFeed } 10 | } 11 | 12 | async function getAvaxValues() { 13 | const vault = await contractAt("Vault", "0x9ab2De34A33fB459b538c43f251eB825645e8595") 14 | const nextPriceFeed = await contractAt("VaultPriceFeed", "0x27e99387af40e5CA9CE21418552f15F02C8C57E7") 15 | return { vault, nextPriceFeed } 16 | } 17 | 18 | async function getValues() { 19 | if (network === "arbitrum") { 20 | return getArbValues() 21 | } 22 | 23 | if (network === "avax") { 24 | return getAvaxValues() 25 | } 26 | } 27 | 28 | async function main() { 29 | const signer = await getFrameSigner() 30 | 31 | const { vault, nextPriceFeed } = await getValues(signer) 32 | const timelock = await contractAt("Timelock", await vault.gov(), signer) 33 | const prevPriceFeed = await contractAt("VaultPriceFeed", await vault.priceFeed()) 34 | 35 | // basic check to verify that the contract is a VaultPriceFeed contract 36 | if ((await prevPriceFeed.isSecondaryPriceEnabled()) !== true) { 37 | throw new Error("Invalid prevPriceFeed") 38 | } 39 | 40 | // basic check to verify that the contract is a VaultPriceFeed contract 41 | if ((await nextPriceFeed.isSecondaryPriceEnabled()) !== true) { 42 | throw new Error("Invalid nextPriceFeed") 43 | } 44 | 45 | await sendTxn(timelock.signalSetPriceFeed(vault.address, nextPriceFeed.address), "timelock.signalSetPriceFeed(nextPriceFeed)") 46 | await sendTxn(timelock.signalSetPriceFeed(vault.address, prevPriceFeed.address), "timelock.signalSetPriceFeed(prevPriceFeed)") 47 | } 48 | 49 | main() 50 | .then(() => process.exit(0)) 51 | .catch(error => { 52 | console.error(error) 53 | process.exit(1) 54 | }) 55 | -------------------------------------------------------------------------------- /scripts/core/checkAmounts.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const router = await contractAt("Router", "0xD46B23D042E976F8666F554E928e0Dc7478a8E1f") 6 | const vault = await contractAt("Vault", "0xc73A8DcAc88498FD4b4B1b2AaA37b0a2614Ff67B") 7 | const gov = await contractAt("Timelock", "0x330EeF6b9B1ea6EDd620C825c9919DC8b611d5d5") 8 | 9 | const tokenDecimals = 18 10 | 11 | const btc = { 12 | symbol: "BTC", 13 | address: "0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c" 14 | } 15 | const eth = { 16 | symbol: "ETH", 17 | address: "0x2170ed0880ac9a755fd29b2688956bd959f933f8" 18 | } 19 | const bnb = { 20 | symbol: "BNB", 21 | address: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c" 22 | } 23 | const busd = { 24 | symbol: "BUSD", 25 | address: "0xe9e7cea3dedca5984780bafc599bd69add087d56" 26 | } 27 | const usdc = { 28 | symbol: "USDC", 29 | address: "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d" 30 | } 31 | const usdt = { 32 | symbol: "USDT", 33 | address: "0x55d398326f99059fF775485246999027B3197955" 34 | } 35 | 36 | const tokens = [btc, eth, bnb, busd, usdc, usdt] 37 | 38 | for (let i = 0; i < tokens.length; i++) { 39 | const token = await contractAt("YieldToken", tokens[i].address) 40 | const poolAmount = await vault.poolAmounts(token.address) 41 | const feeReserve = await vault.feeReserves(token.address) 42 | const balance = await token.balanceOf(vault.address) 43 | const vaultAmount = poolAmount.add(feeReserve) 44 | if (vaultAmount.gt(balance)) { 45 | const diff = vaultAmount.sub(balance) 46 | console.log(`${token.address}: vaultAmount.gt(balance): ${ethers.utils.formatUnits(diff, 18)} ${tokens[i].symbol}`) 47 | } else { 48 | const diff = balance.sub(vaultAmount) 49 | console.log(`${token.address}: vaultAmount.lt(balance): ${ethers.utils.formatUnits(diff, 18)} ${tokens[i].symbol}`) 50 | } 51 | } 52 | } 53 | 54 | main() 55 | .then(() => process.exit(0)) 56 | .catch(error => { 57 | console.error(error) 58 | process.exit(1) 59 | }) 60 | -------------------------------------------------------------------------------- /scripts/core/setFastPriceEvents.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt , sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toUsd } = require("../../test/shared/units") 4 | const { errors } = require("../../test/core/Vault/helpers") 5 | 6 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 7 | const tokens = require('./tokens')[network]; 8 | 9 | async function getArbValues() { 10 | const vaultPriceFeed1 = await contractAt("VaultPriceFeed", "0xEFF37c0969DcBf69B0b142dAc4e56A0930AECBa8") 11 | const vaultPriceFeed2 = await contractAt("VaultPriceFeed", "0xa18BB1003686d0854EF989BB936211c59EB6e363") 12 | 13 | return { vaultPriceFeed1, vaultPriceFeed2 } 14 | } 15 | 16 | async function getAvaxValues() { 17 | const vaultPriceFeed1 = await contractAt("VaultPriceFeed", "0x131238112aa25c0D8CD237a6c384d1A86D2BB152") 18 | const vaultPriceFeed2 = await contractAt("VaultPriceFeed", "0x81b7e71A1D9E08a6Ca016A0F4D6Fa50DBCE89Ee3") 19 | 20 | return { vaultPriceFeed1, vaultPriceFeed2 } 21 | } 22 | 23 | async function getValues() { 24 | if (network === "arbitrum") { 25 | return getArbValues() 26 | } 27 | 28 | if (network === "avax") { 29 | return getAvaxValues() 30 | } 31 | } 32 | 33 | async function main() { 34 | const signer = await getFrameSigner() 35 | 36 | const { vaultPriceFeed1, vaultPriceFeed2 } = await getValues(signer) 37 | const fastPriceFeed1 = await contractAt("FastPriceFeed", await vaultPriceFeed1.secondaryPriceFeed()) 38 | const fastPriceFeed2 = await contractAt("FastPriceFeed", await vaultPriceFeed2.secondaryPriceFeed(), signer) 39 | const fastPriceEvents = await contractAt("FastPriceEvents", await fastPriceFeed1.fastPriceEvents(), signer) 40 | 41 | console.log("fastPriceEvents", fastPriceEvents.address) 42 | console.log("fastPriceFeed2", fastPriceFeed2.address) 43 | 44 | await sendTxn(fastPriceEvents.setIsPriceFeed(fastPriceFeed2.address, true), "fastPriceEvents.setIsPriceFeed") 45 | await sendTxn(fastPriceFeed2.setFastPriceEvents(fastPriceEvents.address), "fastPriceFeed2.setFastPriceEvents") 46 | } 47 | 48 | main() 49 | .then(() => process.exit(0)) 50 | .catch(error => { 51 | console.error(error) 52 | process.exit(1) 53 | }) 54 | -------------------------------------------------------------------------------- /contracts/staking/StakedGlpMigrator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../libraries/math/SafeMath.sol"; 6 | import "../libraries/token/IERC20.sol"; 7 | 8 | import "../core/interfaces/IGlpManager.sol"; 9 | 10 | import "./interfaces/IRewardTracker.sol"; 11 | import "./interfaces/IRewardTracker.sol"; 12 | 13 | import "../access/Governable.sol"; 14 | 15 | // provide a way to migrate staked GLP tokens by unstaking from the sender 16 | // and staking for the receiver 17 | // meant for a one-time use for a specified sender 18 | // requires the contract to be added as a handler for stakedGlpTracker and feeGlpTracker 19 | contract StakedGlpMigrator is Governable { 20 | using SafeMath for uint256; 21 | 22 | address public sender; 23 | address public glp; 24 | address public stakedGlpTracker; 25 | address public feeGlpTracker; 26 | bool public isEnabled = true; 27 | 28 | constructor( 29 | address _sender, 30 | address _glp, 31 | address _stakedGlpTracker, 32 | address _feeGlpTracker 33 | ) public { 34 | sender = _sender; 35 | glp = _glp; 36 | stakedGlpTracker = _stakedGlpTracker; 37 | feeGlpTracker = _feeGlpTracker; 38 | } 39 | 40 | function disable() external onlyGov { 41 | isEnabled = false; 42 | } 43 | 44 | function transfer(address _recipient, uint256 _amount) external onlyGov { 45 | _transfer(sender, _recipient, _amount); 46 | } 47 | 48 | function _transfer(address _sender, address _recipient, uint256 _amount) private { 49 | require(isEnabled, "StakedGlpMigrator: not enabled"); 50 | require(_sender != address(0), "StakedGlpMigrator: transfer from the zero address"); 51 | require(_recipient != address(0), "StakedGlpMigrator: transfer to the zero address"); 52 | 53 | IRewardTracker(stakedGlpTracker).unstakeForAccount(_sender, feeGlpTracker, _amount, _sender); 54 | IRewardTracker(feeGlpTracker).unstakeForAccount(_sender, glp, _amount, _sender); 55 | 56 | IRewardTracker(feeGlpTracker).stakeForAccount(_sender, _recipient, glp, _amount); 57 | IRewardTracker(stakedGlpTracker).stakeForAccount(_recipient, _recipient, feeGlpTracker, _amount); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /scripts/core/vaultSetTokenConfig.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt, sendTxn, readTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | const { toChainlinkPrice } = require("../../test/shared/chainlink") 4 | 5 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 6 | const tokens = require('./tokens')[network]; 7 | 8 | async function getArbValues() { 9 | const vault = await contractAt("Vault", "0x489ee077994B6658eAfA855C308275EAd8097C4A") 10 | 11 | const { usdc } = tokens 12 | const tokenArr = [usdc] 13 | 14 | return { vault, tokenArr } 15 | } 16 | 17 | async function getAvaxValues() { 18 | const vault = await contractAt("Vault", "0x9ab2De34A33fB459b538c43f251eB825645e8595") 19 | 20 | const { btcb } = tokens 21 | const tokenArr = [btcb] 22 | 23 | return { vault, tokenArr } 24 | } 25 | 26 | async function getValues() { 27 | if (network === "arbitrum") { 28 | return getArbValues() 29 | } 30 | 31 | if (network === "avax") { 32 | return getAvaxValues() 33 | } 34 | } 35 | 36 | async function main() { 37 | const signer = await getFrameSigner() 38 | 39 | const { vault, tokenArr } = await getValues() 40 | const vaultGov = await vault.gov() 41 | 42 | const vaultTimelock = await contractAt("Timelock", vaultGov, signer) 43 | const vaultMethod = "signalVaultSetTokenConfig" 44 | // const vaultMethod = "vaultSetTokenConfig" 45 | 46 | console.log("vault", vault.address) 47 | console.log("vaultTimelock", vaultTimelock.address) 48 | console.log("vaultMethod", vaultMethod) 49 | 50 | for (const token of tokenArr) { 51 | await sendTxn(vaultTimelock[vaultMethod]( 52 | vault.address, 53 | token.address, // _token 54 | token.decimals, // _tokenDecimals 55 | token.tokenWeight, // _tokenWeight 56 | token.minProfitBps, // _minProfitBps 57 | expandDecimals(token.maxUsdgAmount, 18), // _maxUsdgAmount 58 | token.isStable, // _isStable 59 | token.isShortable // _isShortable 60 | ), `vault.${vaultMethod}(${token.name}) ${token.address}`) 61 | } 62 | } 63 | 64 | main() 65 | .then(() => process.exit(0)) 66 | .catch(error => { 67 | console.error(error) 68 | process.exit(1) 69 | }) 70 | -------------------------------------------------------------------------------- /scripts/peripherals/deployPriceFeedTimelock.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn, getFrameSigner } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | 6 | async function getArbValues() { 7 | const tokenManager = { address: "0xddDc546e07f1374A07b270b7d863371e575EA96A" } 8 | 9 | return { tokenManager } 10 | } 11 | 12 | async function getAvaxValues() { 13 | const tokenManager = { address: "0x8b25Ba1cAEAFaB8e9926fabCfB6123782e3B4BC2" } 14 | 15 | return { tokenManager } 16 | } 17 | 18 | async function getValues() { 19 | if (network === "arbitrum") { 20 | return getArbValues() 21 | } 22 | 23 | if (network === "avax") { 24 | return getAvaxValues() 25 | } 26 | } 27 | 28 | async function main() { 29 | const signer = await getFrameSigner() 30 | 31 | const admin = "0x49B373D422BdA4C6BfCdd5eC1E48A9a26fdA2F8b" 32 | const buffer = 24 * 60 * 60 33 | 34 | const { tokenManager } = await getValues() 35 | 36 | const timelock = await deployContract("PriceFeedTimelock", [ 37 | admin, 38 | buffer, 39 | tokenManager.address 40 | ], "Timelock") 41 | 42 | const deployedTimelock = await contractAt("PriceFeedTimelock", timelock.address, signer) 43 | 44 | const signers = [ 45 | "0x82429089e7c86B7047b793A9E7E7311C93d2b7a6", // coinflipcanada 46 | "0xD7941C4Ca57a511F21853Bbc7FBF8149d5eCb398", // G 47 | "0xfb481D70f8d987c1AE3ADc90B7046e39eb6Ad64B", // kr 48 | "0x99Aa3D1b3259039E8cB4f0B33d0Cfd736e1Bf49E", // quat 49 | "0x6091646D0354b03DD1e9697D33A7341d8C93a6F5" // xhiroz 50 | ] 51 | 52 | for (let i = 0; i < signers.length; i++) { 53 | const signer = signers[i] 54 | await sendTxn(deployedTimelock.setContractHandler(signer, true), `deployedTimelock.setContractHandler(${signer})`) 55 | } 56 | 57 | const keepers = [ 58 | "0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8" // X 59 | ] 60 | 61 | for (let i = 0; i < keepers.length; i++) { 62 | const keeper = keepers[i] 63 | await sendTxn(deployedTimelock.setKeeper(keeper, true), `deployedTimelock.setKeeper(${keeper})`) 64 | } 65 | } 66 | 67 | main() 68 | .then(() => process.exit(0)) 69 | .catch(error => { 70 | console.error(error) 71 | process.exit(1) 72 | }) 73 | -------------------------------------------------------------------------------- /test/tokens/YieldFarm.js: -------------------------------------------------------------------------------- 1 | const { expect, use } = require("chai") 2 | const { solidity } = require("ethereum-waffle") 3 | const { deployContract } = require("../shared/fixtures") 4 | const { expandDecimals, getBlockTime, increaseTime, mineBlock, reportGasUsed } = require("../shared/utilities") 5 | 6 | use(solidity) 7 | 8 | describe("YieldFarm", function () { 9 | const provider = waffle.provider 10 | const [wallet, user0, user1, user2, user3] = provider.getWallets() 11 | let farm 12 | let token 13 | 14 | beforeEach(async () => { 15 | token = await deployContract("Token", []) 16 | await token.mint(wallet.address, 1000) 17 | farm = await deployContract("YieldFarm", ["Yield Farm", "FARM", token.address]) 18 | }) 19 | 20 | it("stake", async () => { 21 | await expect(farm.stake(1000)) 22 | .to.be.revertedWith("ERC20: transfer amount exceeds allowance") 23 | 24 | await token.connect(wallet).approve(farm.address, 2000) 25 | await expect(farm.stake(2000)) 26 | .to.be.revertedWith("ERC20: transfer amount exceeds balance") 27 | 28 | expect(await farm.balanceOf(wallet.address)).eq(0) 29 | expect(await token.balanceOf(wallet.address)).eq(1000) 30 | expect(await token.balanceOf(farm.address)).eq(0) 31 | await farm.stake(1000) 32 | expect(await farm.balanceOf(wallet.address)).eq(1000) 33 | expect(await token.balanceOf(wallet.address)).eq(0) 34 | expect(await token.balanceOf(farm.address)).eq(1000) 35 | }) 36 | 37 | it("unstake", async () => { 38 | await token.connect(wallet).approve(farm.address, 2000) 39 | expect(await farm.balanceOf(wallet.address)).eq(0) 40 | expect(await token.balanceOf(wallet.address)).eq(1000) 41 | expect(await token.balanceOf(farm.address)).eq(0) 42 | await farm.stake(1000) 43 | expect(await farm.balanceOf(wallet.address)).eq(1000) 44 | expect(await token.balanceOf(wallet.address)).eq(0) 45 | expect(await token.balanceOf(farm.address)).eq(1000) 46 | 47 | await expect(farm.unstake(1001)) 48 | .to.be.revertedWith("YieldToken: burn amount exceeds balance") 49 | 50 | await farm.unstake(1000) 51 | 52 | expect(await farm.balanceOf(wallet.address)).eq(0) 53 | expect(await token.balanceOf(wallet.address)).eq(1000) 54 | expect(await token.balanceOf(farm.address)).eq(0) 55 | }) 56 | }) 57 | -------------------------------------------------------------------------------- /scripts/peripherals/printUniswapLiquidity.js: -------------------------------------------------------------------------------- 1 | const { contractAt } = require("../shared/helpers") 2 | const { expandDecimals, bigNumberify } = require("../../test/shared/utilities") 3 | const { Token } = require('@uniswap/sdk-core') 4 | const { tickToPrice, Pool, Position } = require('@uniswap/v3-sdk') 5 | 6 | const UniNftManager = require("../../artifacts/contracts/amm/UniNftManager.sol/UniNftManager.json") 7 | 8 | async function main() { 9 | const MAX_UINT128 = bigNumberify(2).pow(128).sub(1) 10 | const nftManager = await contractAt("UniNftManager", "0xC36442b4a4522E871399CD717aBDD847Ab11FE88") 11 | 12 | const uniPool = await contractAt("UniPool", "0x80A9ae39310abf666A87C743d6ebBD0E8C42158E") 13 | const weth = new Token(42161, "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", 18, "SYMBOL", "NAME") 14 | const gmx = new Token(42161, "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a", 18, "SYMBOL", "NAME") 15 | 16 | const poolInfo = await uniPool.slot0() 17 | 18 | const pool = new Pool( 19 | weth, // weth 20 | gmx, // gmx 21 | 10000, // fee 22 | poolInfo.sqrtPriceX96, // sqrtRatioX96 23 | 1, // liquidity 24 | poolInfo.tick, // tickCurrent 25 | [] 26 | ) 27 | 28 | const nftIds = [33985, 566, 16, 17, 18, 19, 20, 21, 22, 2726, 16797, 16809, 16810, 17079, 17080, 24729, 25035, 25921, 31374, 69112, 69115, 69119, 69120, 34143] 29 | 30 | console.log("NFT ID,Start (ETH),End (ETH),ETH Liquidity, GMX Liquidity") 31 | for (let i = 0; i < nftIds.length; i++) { 32 | const nftId = nftIds[i] 33 | const owner = await nftManager.ownerOf(nftId) 34 | const positionInfo = await nftManager.positions(nftId) 35 | const position = new Position({ pool, liquidity: positionInfo.liquidity.toString(), tickLower: positionInfo.tickLower, tickUpper: positionInfo.tickUpper }) 36 | const start = tickToPrice(gmx, weth, positionInfo.tickUpper).toSignificant(6) 37 | const end = tickToPrice(gmx, weth, positionInfo.tickLower).toSignificant(6) 38 | const ethLiquidity = position.amount0.toSignificant(6) 39 | const gmxLiquidity = position.amount1.toSignificant(6) 40 | 41 | console.log(`${nftId},${start},${end},${ethLiquidity},${gmxLiquidity}`) 42 | } 43 | } 44 | 45 | main() 46 | .then(() => process.exit(0)) 47 | .catch(error => { 48 | console.error(error) 49 | process.exit(1) 50 | }) 51 | -------------------------------------------------------------------------------- /scripts/core/setPriceFeedConfig.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt, sendTxn, readTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { bigNumberify, expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | const tokens = require('./tokens')[network]; 6 | 7 | async function getArbValues() { 8 | const vault = await contractAt("Vault", "0x489ee077994B6658eAfA855C308275EAd8097C4A") 9 | const vaultPriceFeed = await contractAt("VaultPriceFeed", await vault.priceFeed()) 10 | // const vaultPriceFeed = await contractAt("VaultPriceFeed", "0xfe661cbf27Da0656B7A1151a761ff194849C387A") 11 | 12 | const { btc, eth, usdce, usdc, link, uni, usdt, mim, frax, dai } = tokens 13 | const fastPriceTokens = [btc, eth, link, uni] 14 | 15 | return { vaultPriceFeed, fastPriceTokens } 16 | } 17 | 18 | async function getAvaxValues() { 19 | const vault = await contractAt("Vault", "0x9ab2De34A33fB459b538c43f251eB825645e8595") 20 | const vaultPriceFeed = await contractAt("VaultPriceFeed", await vault.priceFeed()) 21 | // const vaultPriceFeed = await contractAt("VaultPriceFeed", "0x205646B93B9D8070e15bc113449586875Ed7288E") 22 | 23 | const { avax, btc, btcb, eth, mim, usdce, usdc } = tokens 24 | const fastPriceTokens = [avax, btc, btcb, eth] 25 | 26 | return { vaultPriceFeed, fastPriceTokens } 27 | } 28 | 29 | async function getValues() { 30 | if (network === "arbitrum") { 31 | return getArbValues() 32 | } 33 | 34 | if (network === "avax") { 35 | return getAvaxValues() 36 | } 37 | } 38 | 39 | async function main() { 40 | const { vaultPriceFeed, fastPriceTokens } = await getValues() 41 | const secondaryPriceFeed = await contractAt("FastPriceFeed", await vaultPriceFeed.secondaryPriceFeed()) 42 | 43 | console.log("secondaryPriceFeed", secondaryPriceFeed.address) 44 | console.log("setMaxDeviationBasisPoints", 1000) 45 | console.log("setPriceDataInterval", 1 * 60) 46 | console.log("setMaxCumulativeDeltaDiffs") 47 | console.log("[", fastPriceTokens.map(t => `"${t.address}"`).join(",\n"), "]") 48 | console.log("[", fastPriceTokens.map(t => t.maxCumulativeDeltaDiff).join(",\n"), "]") 49 | } 50 | 51 | main() 52 | .then(() => process.exit(0)) 53 | .catch(error => { 54 | console.error(error) 55 | process.exit(1) 56 | }) 57 | -------------------------------------------------------------------------------- /scripts/peripherals/listSend.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals, bigNumberify } = require("../../test/shared/utilities") 3 | const { LIST } = require("../../data/batchSend/list") 4 | 5 | const { 6 | ARBITRUM_URL, 7 | ARBITRUM_PAYMENTS_KEY, 8 | AVAX_URL, 9 | AVAX_PAYMENTS_KEY, 10 | } = require("../../env.json") 11 | 12 | async function main() { 13 | const arbProvider = new ethers.providers.JsonRpcProvider(ARBITRUM_URL) 14 | const arbWallet = new ethers.Wallet(ARBITRUM_PAYMENTS_KEY).connect(arbProvider) 15 | 16 | const avaxProvider = new ethers.providers.JsonRpcProvider(AVAX_URL) 17 | const avaxWallet = new ethers.Wallet(AVAX_PAYMENTS_KEY).connect(avaxProvider) 18 | 19 | const list = LIST 20 | const usdc = await contractAt("Token", "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", avaxWallet) 21 | const usdcDecimals = 6 22 | const gmx = await contractAt("Token", "0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a", arbWallet) 23 | const gmxDecimals = 18 24 | const shouldSendTxn = false 25 | 26 | const minCount = 0 27 | let count = 0 28 | 29 | let totalUsdc = bigNumberify(0) 30 | let totalGmx = bigNumberify(0) 31 | 32 | for (let i = 0; i < list.length; i++) { 33 | const item = list[i] 34 | if (item.usdc && parseFloat(item.usdc) !== 0) { 35 | count++ 36 | const amount = ethers.utils.parseUnits(item.usdc, usdcDecimals) 37 | totalUsdc = totalUsdc.add(amount) 38 | if (shouldSendTxn && count >= minCount) { 39 | await sendTxn(usdc.transfer(item.account, amount), `${count}: usdc.transfer(${item.account}, ${amount})`) 40 | } 41 | } 42 | if (item.gmx && parseFloat(item.gmx) !== 0) { 43 | count++ 44 | const amount = ethers.utils.parseUnits(item.gmx, gmxDecimals) 45 | totalGmx = totalGmx.add(amount) 46 | if (shouldSendTxn && count >= minCount) { 47 | await sendTxn(gmx.transfer(item.account, amount), `${count}: gmx.transfer(${item.account}, ${amount})`) 48 | } 49 | } 50 | } 51 | 52 | console.log("total USDC", ethers.utils.formatUnits(totalUsdc, usdcDecimals)) 53 | console.log("total GMX", ethers.utils.formatUnits(totalGmx, gmxDecimals)) 54 | } 55 | 56 | main() 57 | .then(() => process.exit(0)) 58 | .catch(error => { 59 | console.error(error) 60 | process.exit(1) 61 | }) 62 | -------------------------------------------------------------------------------- /scripts/staking/deployGlpWrappers.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt, sendTxn, writeTmpAddresses } = require("../shared/helpers") 2 | 3 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 4 | 5 | async function getArbValues() { 6 | const glp = { address: "0x4277f8F2c384827B5273592FF7CeBd9f2C1ac258" } 7 | const glpManager = { address: "0x321F653eED006AD1C29D174e17d96351BDe22649" } 8 | const stakedGlpTracker = await contractAt("RewardTracker", "0x1aDDD80E6039594eE970E5872D247bf0414C8903") 9 | const feeGlpTracker = await contractAt("RewardTracker", "0x4e971a87900b931fF39d1Aad67697F49835400b6") 10 | 11 | return { glp, glpManager, stakedGlpTracker, feeGlpTracker } 12 | } 13 | 14 | async function getAvaxValues() { 15 | const glp = { address: "0x01234181085565ed162a948b6a5e88758CD7c7b8" } 16 | const glpManager = { address: "0xe1ae4d4b06A5Fe1fc288f6B4CD72f9F8323B107F" } 17 | const stakedGlpTracker = await contractAt("RewardTracker", "0x9e295B5B976a184B14aD8cd72413aD846C299660") 18 | const feeGlpTracker = await contractAt("RewardTracker", "0xd2D1162512F927a7e282Ef43a362659E4F2a728F") 19 | 20 | return { glp, glpManager, stakedGlpTracker, feeGlpTracker } 21 | } 22 | 23 | async function getValues() { 24 | if (network === "arbitrum") { 25 | return getArbValues() 26 | } 27 | 28 | if (network === "avax") { 29 | return getAvaxValues() 30 | } 31 | } 32 | 33 | async function main() { 34 | const signer = await getFrameSigner() 35 | const { glp, glpManager, stakedGlpTracker, feeGlpTracker } = await getValues() 36 | 37 | const timelock = await contractAt("Timelock", await stakedGlpTracker.gov(), signer) 38 | 39 | const stakedGlp = await deployContract("StakedGlp", [ 40 | glp.address, 41 | glpManager.address, 42 | stakedGlpTracker.address, 43 | feeGlpTracker.address 44 | ]) 45 | 46 | await sendTxn(timelock.signalSetHandler(stakedGlpTracker.address, stakedGlp.address, true), "timelock.signalSetHandler(stakedGlpTracker)") 47 | await sendTxn(timelock.signalSetHandler(feeGlpTracker.address, stakedGlp.address, true), "timelock.signalSetHandler(stakedGlpTracker)") 48 | 49 | // await deployContract("GlpBalance", [glpManager.address, stakedGlpTracker.address]) 50 | } 51 | 52 | main() 53 | .then(() => process.exit(0)) 54 | .catch(error => { 55 | console.error(error) 56 | process.exit(1) 57 | }) 58 | -------------------------------------------------------------------------------- /scripts/referrals/getReferralRewards.js: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | 3 | const { bigNumberify } = require("../../test/shared/utilities") 4 | 5 | let arbitrumFile 6 | if (process.env.ARBITRUM_FILE) { 7 | arbitrumFile = path.join(process.env.PWD, process.env.ARBITRUM_FILE) 8 | } else { 9 | arbitrumFile = path.join(__dirname, "../../distribution-data-arbitrum.json") 10 | } 11 | console.log("Arbitrum file: %s", arbitrumFile) 12 | 13 | let avalancheFile 14 | if (process.env.AVALANCHE_FILE) { 15 | avalancheFile = path.join(process.env.PWD, process.env.AVALANCHE_FILE) 16 | } else { 17 | avalancheFile = path.join(__dirname, "../../distribution-data-avalanche.json") 18 | } 19 | console.log("Avalanche file: %s", avalancheFile) 20 | 21 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 22 | const tokens = require('../core/tokens')[network]; 23 | 24 | const { AddressZero } = ethers.constants 25 | 26 | async function getArbValues() { 27 | const data = require(arbitrumFile) 28 | 29 | return { data } 30 | } 31 | 32 | async function getAvaxValues() { 33 | const data = require(avalancheFile) 34 | 35 | return { data } 36 | } 37 | 38 | async function getNetworkValues() { 39 | return [ 40 | await getArbValues(), 41 | await getAvaxValues() 42 | ] 43 | } 44 | 45 | function getReferralRewardsInfo(data) { 46 | console.log("data", data) 47 | const affiliatesData = data.affiliates 48 | const discountsData = data.referrals 49 | 50 | console.log("affiliates", affiliatesData.length) 51 | console.log("trader discounts", discountsData.length) 52 | 53 | let allAffiliateUsd = bigNumberify(0) 54 | let allDiscountUsd = bigNumberify(0) 55 | 56 | for (let i = 0; i < affiliatesData.length; i++) { 57 | const { rebateUsd } = affiliatesData[i] 58 | allAffiliateUsd = allAffiliateUsd.add(rebateUsd) 59 | } 60 | 61 | for (let i = 0; i < discountsData.length; i++) { 62 | const { discountUsd } = discountsData[i] 63 | allDiscountUsd = allDiscountUsd.add(discountUsd) 64 | } 65 | 66 | console.log("all affiliate rewards (USD)", ethers.utils.formatUnits(allAffiliateUsd, 30)) 67 | console.log("all trader rebates (USD)", ethers.utils.formatUnits(allDiscountUsd, 30)) 68 | 69 | return { 70 | allAffiliateUsd, 71 | allDiscountUsd 72 | } 73 | } 74 | 75 | module.exports = { 76 | getArbValues, 77 | getAvaxValues, 78 | getReferralRewardsInfo 79 | } 80 | -------------------------------------------------------------------------------- /scripts/staking/removeRewardRouter.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const rewardRouter = await contractAt("RewardRouter", "0xEa7fCb85802713Cb03291311C66d6012b23402ea") 6 | const bnGmx = await contractAt("MintableBaseToken", "0x35247165119B69A40edD5304969560D0ef486921") 7 | const glpManager = await contractAt("GlpManager", "0x91425Ac4431d068980d497924DD540Ae274f3270") 8 | 9 | const stakedGmxTracker = await contractAt("RewardTracker", "0x908C4D94D34924765f1eDc22A1DD098397c59dD4") 10 | const bonusGmxTracker = await contractAt("RewardTracker", "0x4d268a7d4C16ceB5a606c173Bd974984343fea13") 11 | const feeGmxTracker = await contractAt("RewardTracker", "0xd2D1162512F927a7e282Ef43a362659E4F2a728F") 12 | 13 | const feeGlpTracker = await contractAt("RewardTracker", "0x4e971a87900b931fF39d1Aad67697F49835400b6") 14 | const stakedGlpTracker = await contractAt("RewardTracker", "0x1aDDD80E6039594eE970E5872D247bf0414C8903") 15 | 16 | // allow rewardRouter to stake in stakedGmxTracker 17 | await sendTxn(stakedGmxTracker.setHandler(rewardRouter.address, false), "stakedGmxTracker.setHandler(rewardRouter)") 18 | // allow rewardRouter to stake in bonusGmxTracker 19 | await sendTxn(bonusGmxTracker.setHandler(rewardRouter.address, false), "bonusGmxTracker.setHandler(rewardRouter)") 20 | // allow rewardRouter to stake in feeGmxTracker 21 | await sendTxn(feeGmxTracker.setHandler(rewardRouter.address, false), "feeGmxTracker.setHandler(rewardRouter)") 22 | // allow rewardRouter to burn bnGmx 23 | await sendTxn(bnGmx.setMinter(rewardRouter.address, false), "bnGmx.setMinter(rewardRouter)") 24 | 25 | // allow rewardRouter to mint in glpManager 26 | await sendTxn(glpManager.setHandler(rewardRouter.address, false), "glpManager.setHandler(rewardRouter)") 27 | // allow rewardRouter to stake in feeGlpTracker 28 | await sendTxn(feeGlpTracker.setHandler(rewardRouter.address, false), "feeGlpTracker.setHandler(rewardRouter)") 29 | // allow rewardRouter to stake in stakedGlpTracker 30 | await sendTxn(stakedGlpTracker.setHandler(rewardRouter.address, false), "stakedGlpTracker.setHandler(rewardRouter)") 31 | } 32 | 33 | main() 34 | .then(() => process.exit(0)) 35 | .catch(error => { 36 | console.error(error) 37 | process.exit(1) 38 | }) 39 | -------------------------------------------------------------------------------- /contracts/peripherals/EsGmxBatchSender.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../libraries/token/IERC20.sol"; 6 | import "../libraries/math/SafeMath.sol"; 7 | 8 | import "../staking/interfaces/IVester.sol"; 9 | import "../staking/interfaces/IRewardTracker.sol"; 10 | 11 | contract EsGmxBatchSender { 12 | using SafeMath for uint256; 13 | 14 | address public admin; 15 | address public esGmx; 16 | 17 | constructor(address _esGmx) public { 18 | admin = msg.sender; 19 | esGmx = _esGmx; 20 | } 21 | 22 | modifier onlyAdmin() { 23 | require(msg.sender == admin, "EsGmxBatchSender: forbidden"); 24 | _; 25 | } 26 | 27 | function send( 28 | IVester _vester, 29 | uint256 _minRatio, 30 | address[] memory _accounts, 31 | uint256[] memory _amounts 32 | ) external onlyAdmin { 33 | IRewardTracker rewardTracker = IRewardTracker(_vester.rewardTracker()); 34 | 35 | for (uint256 i = 0; i < _accounts.length; i++) { 36 | IERC20(esGmx).transferFrom(msg.sender, _accounts[i], _amounts[i]); 37 | 38 | uint256 nextTransferredCumulativeReward = _vester.transferredCumulativeRewards(_accounts[i]).add(_amounts[i]); 39 | _vester.setTransferredCumulativeRewards(_accounts[i], nextTransferredCumulativeReward); 40 | 41 | uint256 cumulativeReward = rewardTracker.cumulativeRewards(_accounts[i]); 42 | uint256 totalCumulativeReward = cumulativeReward.add(nextTransferredCumulativeReward); 43 | 44 | uint256 combinedAverageStakedAmount = _vester.getCombinedAverageStakedAmount(_accounts[i]); 45 | 46 | if (combinedAverageStakedAmount > totalCumulativeReward.mul(_minRatio)) { 47 | continue; 48 | } 49 | 50 | uint256 nextTransferredAverageStakedAmount = _minRatio.mul(totalCumulativeReward); 51 | nextTransferredAverageStakedAmount = nextTransferredAverageStakedAmount.sub( 52 | rewardTracker.averageStakedAmounts(_accounts[i]).mul(cumulativeReward).div(totalCumulativeReward) 53 | ); 54 | 55 | nextTransferredAverageStakedAmount = nextTransferredAverageStakedAmount.mul(totalCumulativeReward).div(nextTransferredCumulativeReward); 56 | 57 | _vester.setTransferredAverageStakedAmounts(_accounts[i], nextTransferredAverageStakedAmount); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /contracts/gmx/GmxIou.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../libraries/token/IERC20.sol"; 6 | import "../libraries/math/SafeMath.sol"; 7 | 8 | import "./interfaces/IGmxIou.sol"; 9 | 10 | contract GmxIou is IERC20, IGmxIou { 11 | using SafeMath for uint256; 12 | 13 | mapping (address => uint256) private _balances; 14 | uint256 public override totalSupply; 15 | 16 | string public name; 17 | string public symbol; 18 | uint8 public decimals; 19 | 20 | address public minter; 21 | 22 | constructor (address _minter, string memory _name, string memory _symbol) public { 23 | name = _name; 24 | symbol = _symbol; 25 | minter = _minter; 26 | decimals = 18; 27 | } 28 | 29 | function mint(address account, uint256 amount) public override returns (bool) { 30 | require(msg.sender == minter, "GmxIou: forbidden"); 31 | _mint(account, amount); 32 | return true; 33 | } 34 | 35 | function balanceOf(address account) public view override returns (uint256) { 36 | return _balances[account]; 37 | } 38 | 39 | // empty implementation, GmxIou tokens are non-transferrable 40 | function transfer(address /* recipient */, uint256 /* amount */) public override returns (bool) { 41 | revert("GmxIou: non-transferrable"); 42 | } 43 | 44 | // empty implementation, GmxIou tokens are non-transferrable 45 | function allowance(address /* owner */, address /* spender */) public view virtual override returns (uint256) { 46 | return 0; 47 | } 48 | 49 | // empty implementation, GmxIou tokens are non-transferrable 50 | function approve(address /* spender */, uint256 /* amount */) public virtual override returns (bool) { 51 | revert("GmxIou: non-transferrable"); 52 | } 53 | 54 | // empty implementation, GmxIou tokens are non-transferrable 55 | function transferFrom(address /* sender */, address /* recipient */, uint256 /* amount */) public virtual override returns (bool) { 56 | revert("GmxIou: non-transferrable"); 57 | } 58 | 59 | function _mint(address account, uint256 amount) internal virtual { 60 | require(account != address(0), "GmxIou: mint to the zero address"); 61 | 62 | totalSupply = totalSupply.add(amount); 63 | _balances[account] = _balances[account].add(amount); 64 | emit Transfer(address(0), account, amount); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /scripts/core/checkTokenConfigs.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | const tokens = require('./tokens')[network]; 6 | 7 | async function checkTokenConfig(tokenArr) { 8 | for (let i = 0; i < tokenArr.length; i++) { 9 | const tokenInfo = tokenArr[i] 10 | const token = await contractAt("Token", tokenInfo.address) 11 | const name = await token.name() 12 | const symbol = await token.symbol() 13 | const decimals = await token.decimals() 14 | const priceFeed = await contractAt("PriceFeed", tokenInfo.priceFeed) 15 | const priceDecimals = await priceFeed.decimals() 16 | 17 | if (tokenInfo.decimals.toString() !== decimals.toString()) { 18 | throw new Error(`Invalid decimals, ${tokenInfo.decimals.toString()}, ${decimals.toString()}`) 19 | } 20 | 21 | if (tokenInfo.priceDecimals.toString() !== priceDecimals.toString()) { 22 | throw new Error(`Invalid price decimals, ${tokenInfo.priceDecimals.toString()}, ${priceDecimals.toString()}`) 23 | } 24 | 25 | console.log(`${tokenInfo.name}, ${name}, ${symbol}, ${token.address}`) 26 | console.log(`token decimals: ${tokenInfo.decimals}, ${decimals.toString()}`) 27 | console.log(`price decimals: ${tokenInfo.priceDecimals}, ${priceDecimals.toString()}`) 28 | console.log(`price feed: ${await priceFeed.description()}`) 29 | console.log(`isShortable: ${tokenInfo.isShortable}, isStable: ${tokenInfo.isStable}, isStrictStable: ${tokenInfo.isStrictStable}`) 30 | console.log("\n-------\n") 31 | } 32 | } 33 | 34 | async function checkTokenConfigAvax() { 35 | const { avax, btc, btcb, eth, mim, usdce, usdc } = tokens 36 | const tokenArr = [avax, btc, btcb, eth, mim, usdce, usdc] 37 | 38 | await checkTokenConfig(tokenArr) 39 | } 40 | 41 | async function checkTokenConfigArb() { 42 | const { btc, eth, usdce, usdc, link, uni, usdt, mim, frax, dai } = tokens 43 | const tokenArr = [btc, eth, usdce, usdc, link, uni, usdt, mim, frax, dai] 44 | 45 | await checkTokenConfig(tokenArr) 46 | } 47 | 48 | async function main() { 49 | if (network === "avax") { 50 | await checkTokenConfigAvax() 51 | return 52 | } 53 | 54 | await checkTokenConfigArb() 55 | } 56 | 57 | main() 58 | .then(() => process.exit(0)) 59 | .catch(error => { 60 | console.error(error) 61 | process.exit(1) 62 | }) 63 | -------------------------------------------------------------------------------- /scripts/staking/deployGlpRewardRouter.js: -------------------------------------------------------------------------------- 1 | const { deployContract, contractAt, sendTxn, getFrameSigner } = require("../shared/helpers") 2 | const { expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | const tokens = require('../core/tokens')[network]; 6 | 7 | const { AddressZero } = ethers.constants 8 | 9 | async function getArbValues() { 10 | const { nativeToken } = tokens 11 | const glp = { address: "0x4277f8F2c384827B5273592FF7CeBd9f2C1ac258" } 12 | const feeGlpTracker = { address: "0x4e971a87900b931fF39d1Aad67697F49835400b6" } 13 | const stakedGlpTracker = { address: "0x1aDDD80E6039594eE970E5872D247bf0414C8903" } 14 | const glpManager = { address: "0x3963FfC9dff443c2A94f21b129D429891E32ec18" } 15 | 16 | return { nativeToken, glp, feeGlpTracker, stakedGlpTracker, glpManager } 17 | } 18 | 19 | async function getAvaxValues() { 20 | const { nativeToken } = tokens 21 | const glp = { address: "0x01234181085565ed162a948b6a5e88758CD7c7b8" } 22 | const feeGlpTracker = { address: "0xd2D1162512F927a7e282Ef43a362659E4F2a728F" } 23 | const stakedGlpTracker = { address: "0x9e295B5B976a184B14aD8cd72413aD846C299660" } 24 | const glpManager = { address: "0xD152c7F25db7F4B95b7658323c5F33d176818EE4" } 25 | 26 | return { nativeToken, glp, feeGlpTracker, stakedGlpTracker, glpManager } 27 | } 28 | 29 | async function getValues() { 30 | if (network === "arbitrum") { 31 | return getArbValues() 32 | } 33 | 34 | if (network === "avax") { 35 | return getAvaxValues() 36 | } 37 | } 38 | 39 | async function main() { 40 | const { nativeToken, glp, feeGlpTracker, stakedGlpTracker, glpManager } = await getValues() 41 | 42 | const rewardRouter = await deployContract("RewardRouterV2", []) 43 | await sendTxn(rewardRouter.initialize( 44 | nativeToken.address, // _weth 45 | AddressZero, // _gmx 46 | AddressZero, // _esGmx 47 | AddressZero, // _bnGmx 48 | glp.address, // _glp 49 | AddressZero, // _stakedGmxTracker 50 | AddressZero, // _bonusGmxTracker 51 | AddressZero, // _feeGmxTracker 52 | feeGlpTracker.address, // _feeGlpTracker 53 | stakedGlpTracker.address, // _stakedGlpTracker 54 | glpManager.address, // _glpManager 55 | AddressZero, // _gmxVester 56 | AddressZero // glpVester 57 | ), "rewardRouter.initialize") 58 | } 59 | 60 | main() 61 | .then(() => process.exit(0)) 62 | .catch(error => { 63 | console.error(error) 64 | process.exit(1) 65 | }) 66 | -------------------------------------------------------------------------------- /scripts/core/setSpread.js: -------------------------------------------------------------------------------- 1 | const { getFrameSigner, deployContract, contractAt, sendTxn, readTmpAddresses, callWithRetries } = require("../shared/helpers") 2 | const { bigNumberify, expandDecimals } = require("../../test/shared/utilities") 3 | 4 | const network = (process.env.HARDHAT_NETWORK || 'mainnet'); 5 | const tokens = require('./tokens')[network]; 6 | 7 | async function getArbValues() { 8 | const vault = await contractAt("Vault", "0x489ee077994B6658eAfA855C308275EAd8097C4A") 9 | const vaultPriceFeed = await contractAt("VaultPriceFeed", await vault.priceFeed()) 10 | // const vaultPriceFeed = await contractAt("VaultPriceFeed", "0xfe661cbf27Da0656B7A1151a761ff194849C387A") 11 | const timelock = await contractAt("PriceFeedTimelock", await vaultPriceFeed.gov()) 12 | 13 | const { link, uni } = tokens 14 | const tokenArr = [link, uni] 15 | 16 | return { vault, vaultPriceFeed, timelock, tokenArr } 17 | } 18 | 19 | async function getAvaxValues() { 20 | const vault = await contractAt("Vault", "0x9ab2De34A33fB459b538c43f251eB825645e8595") 21 | const vaultPriceFeed = await contractAt("VaultPriceFeed", await vault.priceFeed()) 22 | // const vaultPriceFeed = await contractAt("VaultPriceFeed", "0x205646B93B9D8070e15bc113449586875Ed7288E") 23 | const timelock = await contractAt("PriceFeedTimelock", await vaultPriceFeed.gov()) 24 | 25 | const { avax } = tokens 26 | const tokenArr = [avax] 27 | 28 | return { vault, vaultPriceFeed, timelock, tokenArr } 29 | } 30 | 31 | async function getValues() { 32 | if (network === "arbitrum") { 33 | return getArbValues() 34 | } 35 | 36 | if (network === "avax") { 37 | return getAvaxValues() 38 | } 39 | } 40 | 41 | async function main() { 42 | // const signer = await getFrameSigner() 43 | 44 | const { vault, vaultPriceFeed, timelock, tokenArr } = await getValues() 45 | 46 | console.log("vault", vault.address) 47 | console.log("timelock", timelock.address) 48 | 49 | const shouldSendTxn = true 50 | 51 | for (const [i, tokenItem] of tokenArr.entries()) { 52 | if (shouldSendTxn) { 53 | await sendTxn(timelock.setSpreadBasisPoints( 54 | vaultPriceFeed.address, 55 | tokenItem.address, // _token 56 | tokenItem.spreadBasisPoints // _spreadBasisPoints 57 | ), `vaultPriceFeed.setSpreadBasisPoints(${tokenItem.name}) ${tokenItem.spreadBasisPoints}`) 58 | } 59 | } 60 | } 61 | 62 | main() 63 | .then(() => process.exit(0)) 64 | .catch(error => { 65 | console.error(error) 66 | process.exit(1) 67 | }) 68 | -------------------------------------------------------------------------------- /scripts/tokens/addLiquidity.js: -------------------------------------------------------------------------------- 1 | const { contractAt, sendTxn } = require("../shared/helpers") 2 | const { expandDecimals, maxUint256 } = require("../../test/shared/utilities") 3 | 4 | async function main() { 5 | const wallet = { address: "0x56a2a358d687a40E3bFd2BE28E69aB229e0b444e" } 6 | const router = await contractAt("PancakeRouter", "0xD99D1c33F9fC3444f8101754aBC46c52416550D1") 7 | const gmt = await contractAt("GMT", "0xedba0360a44f885ed390fad01aa34d00d2532817") 8 | const xgmt = await contractAt("YieldToken", "0x28cba798eca1a3128ffd1b734afb93870f22e613") 9 | const usdg = await contractAt("USDG", "0xE14F46Ee1e23B68003bCED6D85465455a309dffF") 10 | const wbnb = await contractAt("WETH", "0x6A2345E019DB2aCC6007DCD3A69731F51D7Dca52") 11 | const busd = await contractAt("FaucetToken", "0xae7486c680720159130b71e0f9EF7AFd8f413227") 12 | 13 | await sendTxn(gmt.approve(router.address, maxUint256), "gmt.approve(router)") 14 | await sendTxn(xgmt.approve(router.address, maxUint256), "xgmt.approve(router)") 15 | await sendTxn(usdg.approve(router.address, maxUint256), "usdg.approve(router)") 16 | await sendTxn(wbnb.approve(router.address, maxUint256), "wbnb.approve(router)") 17 | await sendTxn(busd.approve(router.address, maxUint256), "busd.approve(router)") 18 | 19 | await sendTxn(router.addLiquidity( 20 | gmt.address, // tokenA 21 | usdg.address, // tokenB 22 | expandDecimals(1000, 18), // amountADesired 23 | expandDecimals(120 * 1000, 18), // amountBDesired 24 | 0, // amountAMin 25 | 0, // amountBMin 26 | wallet.address, // to 27 | maxUint256 // deadline 28 | ), "router.addLiquidity(gmt, usdg)") 29 | 30 | await sendTxn(router.addLiquidity( 31 | xgmt.address, // tokenA 32 | usdg.address, // tokenB 33 | expandDecimals(100, 18), // amountADesired 34 | expandDecimals(60 * 1000, 18), // amountBDesired 35 | 0, // amountAMin 36 | 0, // amountBMin 37 | wallet.address, // to 38 | maxUint256 // deadline 39 | ), "router.addLiquidity(xgmt, usdg)") 40 | 41 | await sendTxn(router.addLiquidity( 42 | wbnb.address, // tokenA 43 | busd.address, // tokenB 44 | expandDecimals(10, 18), // amountADesired 45 | expandDecimals(5250, 18), // amountBDesired 46 | 0, // amountAMin 47 | 0, // amountBMin 48 | wallet.address, // to 49 | maxUint256 // deadline 50 | ), "router.addLiquidity(bnb, busd)") 51 | } 52 | 53 | main() 54 | .then(() => process.exit(0)) 55 | .catch(error => { 56 | console.error(error) 57 | process.exit(1) 58 | }) 59 | -------------------------------------------------------------------------------- /contracts/libraries/access/Ownable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "../GSN/Context.sol"; 6 | /** 7 | * @dev Contract module which provides a basic access control mechanism, where 8 | * there is an account (an owner) that can be granted exclusive access to 9 | * specific functions. 10 | * 11 | * By default, the owner account will be the one that deploys the contract. This 12 | * can later be changed with {transferOwnership}. 13 | * 14 | * This module is used through inheritance. It will make available the modifier 15 | * `onlyOwner`, which can be applied to your functions to restrict their use to 16 | * the owner. 17 | */ 18 | contract Ownable is Context { 19 | address private _owner; 20 | 21 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 22 | 23 | /** 24 | * @dev Initializes the contract setting the deployer as the initial owner. 25 | */ 26 | constructor () internal { 27 | address msgSender = _msgSender(); 28 | _owner = msgSender; 29 | emit OwnershipTransferred(address(0), msgSender); 30 | } 31 | 32 | /** 33 | * @dev Returns the address of the current owner. 34 | */ 35 | function owner() public view returns (address) { 36 | return _owner; 37 | } 38 | 39 | /** 40 | * @dev Throws if called by any account other than the owner. 41 | */ 42 | modifier onlyOwner() { 43 | require(_owner == _msgSender(), "Ownable: caller is not the owner"); 44 | _; 45 | } 46 | 47 | /** 48 | * @dev Leaves the contract without owner. It will not be possible to call 49 | * `onlyOwner` functions anymore. Can only be called by the current owner. 50 | * 51 | * NOTE: Renouncing ownership will leave the contract without an owner, 52 | * thereby removing any functionality that is only available to the owner. 53 | */ 54 | function renounceOwnership() public virtual onlyOwner { 55 | emit OwnershipTransferred(_owner, address(0)); 56 | _owner = address(0); 57 | } 58 | 59 | /** 60 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 61 | * Can only be called by the current owner. 62 | */ 63 | function transferOwnership(address newOwner) public virtual onlyOwner { 64 | require(newOwner != address(0), "Ownable: new owner is the zero address"); 65 | emit OwnershipTransferred(_owner, newOwner); 66 | _owner = newOwner; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /scripts/core/setReferralTier.js: -------------------------------------------------------------------------------- 1 | const { contractAt, sendTxn } = require("../shared/helpers"); 2 | const { expandDecimals } = require("../../test/shared/utilities"); 3 | const { toUsd } = require("../../test/shared/units"); 4 | 5 | const { 6 | ARBITRUM_URL, 7 | ARBITRUM_DEPLOY_KEY, 8 | AVAX_URL, 9 | AVAX_DEPLOY_KEY, 10 | } = require("../../env.json"); 11 | 12 | async function getArbValues() { 13 | const provider = new ethers.providers.JsonRpcProvider(ARBITRUM_URL); 14 | const wallet = new ethers.Wallet(ARBITRUM_DEPLOY_KEY).connect(provider); 15 | const referralStorage = await contractAt( 16 | "ReferralStorage", 17 | "0xe6fab3F0c7199b0d34d7FbE83394fc0e0D06e99d", 18 | wallet 19 | ); 20 | 21 | return { referralStorage, wallet }; 22 | } 23 | 24 | async function getAvaxValues() { 25 | const provider = new ethers.providers.JsonRpcProvider(AVAX_URL); 26 | const wallet = new ethers.Wallet(AVAX_DEPLOY_KEY).connect(provider); 27 | const referralStorage = await contractAt( 28 | "ReferralStorage", 29 | "0x827ED045002eCdAbEb6e2b0d1604cf5fC3d322F8", 30 | wallet 31 | ); 32 | 33 | return { referralStorage, wallet }; 34 | } 35 | 36 | async function getNetworkValues() { 37 | return [await getArbValues(), await getAvaxValues()]; 38 | } 39 | 40 | async function updateAccount(account) { 41 | const networkValues = await getNetworkValues(); 42 | for (let i = 0; i < networkValues.length; i++) { 43 | const { referralStorage, wallet } = networkValues[i]; 44 | const timelock = await contractAt( 45 | "Timelock", 46 | await referralStorage.gov(), 47 | wallet 48 | ); 49 | const tier = 2; // tier 1, 2, 3 50 | 51 | console.log("account", account); 52 | 53 | const currentTier = (await referralStorage.referrerTiers(account)).add(1); 54 | console.log("currentTier", currentTier.toString()); 55 | 56 | if (!currentTier.eq(1)) { 57 | throw new Error("Current tier is more than 1"); 58 | } 59 | 60 | console.log("updating to tier", tier); 61 | await sendTxn( 62 | timelock.setReferrerTier(referralStorage.address, account, tier - 1), 63 | "timelock.setReferrerTier" 64 | ); 65 | } 66 | } 67 | 68 | async function main() { 69 | const accounts = ["0x5C0e0be35F0e5503Bd0ca781E12edae6FAbD3284"]; 70 | 71 | for (let i = 0; i < accounts.length; i++) { 72 | await updateAccount(accounts[i]); 73 | } 74 | } 75 | 76 | main() 77 | .then(() => process.exit(0)) 78 | .catch((error) => { 79 | console.error(error); 80 | process.exit(1); 81 | }); 82 | --------------------------------------------------------------------------------