Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 252 additions & 0 deletions src/abis/OapRouter.json

Large diffs are not rendered by default.

43 changes: 41 additions & 2 deletions src/abis/RewardRouter.json

Large diffs are not rendered by default.

797 changes: 797 additions & 0 deletions src/abis/RewardRouterV2.json

Large diffs are not rendered by default.

8 changes: 0 additions & 8 deletions src/components/Exchange/SwapBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,6 @@ export default function SwapBox(props) {
minExecutionFeeErrorMessage,
} = props;

const [{ wallet, connecting }] = useConnectWallet();

let ethersProvider;

if (wallet) {
ethersProvider = new ethers.providers.Web3Provider(wallet.provider, "any");
}

const [fromValue, setFromValue] = useState("");
const [toValue, setToValue] = useState("");
const [anchorOnFromAmount, setAnchorOnFromAmount] = useState(true);
Expand Down
199 changes: 152 additions & 47 deletions src/components/Glp/GlpSwap.js
Original file line number Diff line number Diff line change
@@ -1,67 +1,69 @@
import React, { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
import { Trans, t } from "@lingui/macro";
import { t, Trans } from "@lingui/macro";
import { useWeb3React } from "@web3-react/core";
import useSWR from "swr";
import { ethers } from "ethers";
import Tab from "../Tab/Tab";
import cx from "classnames";
import { getContract } from "config/contracts";
import { BigNumber, ethers } from "ethers";
import {
getBuyGlpToAmount,
adjustForDecimals,
BASIS_POINTS_DIVISOR,
getBuyGlpFromAmount,
getBuyGlpToAmount,
getSellGlpFromAmount,
getSellGlpToAmount,
adjustForDecimals,
GLP_DECIMALS,
USD_DECIMALS,
BASIS_POINTS_DIVISOR,
GLP_COOLDOWN_DURATION,
GLP_DECIMALS,
PLACEHOLDER_ACCOUNT,
SECONDS_PER_YEAR,
USDG_DECIMALS,
PLACEHOLDER_ACCOUNT,
importImage,
USD_DECIMALS,
} from "lib/legacy";
import { useEffect, useState } from "react";
import { useHistory } from "react-router-dom";
import useSWR from "swr";
import Tab from "../Tab/Tab";

import { useGmxPrice } from "domain/legacy";

import TokenSelector from "../Exchange/TokenSelector";
import BuyInputSection from "../BuyInputSection/BuyInputSection";
import TokenSelector from "../Exchange/TokenSelector";
import Tooltip from "../Tooltip/Tooltip";

import GlpManager from "abis/GlpManager.json";
import OapRouter from "abis/OapRouter.json";
import ReaderV2 from "abis/ReaderV2.json";
import RewardReader from "abis/RewardReader.json";
import VaultV2 from "abis/VaultV2.json";
import GlpManager from "abis/GlpManager.json";
import RewardTracker from "abis/RewardTracker.json";
import Vester from "abis/Vester.json";
import RewardRouter from "abis/RewardRouter.json";
import RewardTracker from "abis/RewardTracker.json";
import Token from "abis/Token.json";
import VaultV2 from "abis/VaultV2.json";
import Vester from "abis/Vester.json";

import glp24Icon from "img/ic_gmx_24.svg";
import logoOAP from "img/logo_oap_white.svg";
import arrowIcon from "img/ic_convert_down.svg";

import avalanche16Icon from "img/ic_avalanche_16.svg";
import arbitrum16Icon from "img/ic_arbitrum_16.svg";

import bnbIcon from "img/ic_binance_logo.svg";

import "./GlpSwap.css";
import AssetDropdown from "pages/Dashboard/AssetDropdown";
import SwapErrorModal from "./SwapErrorModal";
import StatsTooltipRow from "../StatsTooltip/StatsTooltipRow";
import { ARBITRUM, getChainName, HARMONY, IS_NETWORK_DISABLED } from "config/chains";
import { callContract, contractFetcher } from "lib/contracts";
import ExternalLink from "components/ExternalLink/ExternalLink";
import { ARBITRUM, getChainName, IS_NETWORK_DISABLED, TESTNET } from "config/chains";
import {
getNativeToken,
getToken,
getTokenBySymbol,
getTokens,
getWhitelistedTokens,
getWrappedToken,
} from "config/tokens";
import { approveTokens, useInfoTokens } from "domain/tokens";
import { useLocalStorageByChainId } from "lib/localStorage";
import { helperToast } from "lib/helperToast";
import { getTokenInfo, getUsd } from "domain/tokens/utils";
import { bigNumberify, expandDecimals, formatAmount, formatAmountFree, formatKeyAmount, parseValue } from "lib/numbers";
import { getNativeToken, getToken, getTokens, getWhitelistedTokens, getWrappedToken } from "config/tokens";
import { parseEther } from "ethers/lib/utils";
import { useChainId } from "lib/chains";
import ExternalLink from "components/ExternalLink/ExternalLink";
import { callContract, contractFetcher } from "lib/contracts";
import { helperToast } from "lib/helperToast";
import { useLocalStorageByChainId } from "lib/localStorage";
import { bigNumberify, expandDecimals, formatAmount, formatAmountFree, formatKeyAmount, parseValue } from "lib/numbers";
import AssetDropdown from "pages/Dashboard/AssetDropdown";
import { IoMdSwap } from "react-icons/io";
import StatsTooltipRow from "../StatsTooltip/StatsTooltipRow";
import "./GlpSwap.css";
import SwapErrorModal from "./SwapErrorModal";

const { AddressZero } = ethers.constants;

Expand Down Expand Up @@ -145,6 +147,7 @@ export default function GlpSwap(props) {
const usdgAddress = getContract(chainId, "USDG");
const glpManagerAddress = getContract(chainId, "GlpManager");
const rewardRouterAddress = getContract(chainId, "RewardRouter");
const oapRouterAddress = getContract(chainId, "OAPRouter");
const tokensForBalanceAndSupplyQuery = [stakedGlpTrackerAddress, usdgAddress];

const tokenAddresses = tokens.map((token) => token.address);
Expand Down Expand Up @@ -187,6 +190,13 @@ export default function GlpSwap(props) {
}
);

const { data: tokenAllowanceOap } = useSWR(
[active, chainId, tokenAllowanceAddress, "allowance", account || PLACEHOLDER_ACCOUNT, oapRouterAddress],
{
fetcher: contractFetcher(library, Token),
}
);

const { data: lastPurchaseTime } = useSWR(
[`GlpSwap:lastPurchaseTime:${active}`, chainId, glpManagerAddress, "lastAddedAt", account || PLACEHOLDER_ACCOUNT],
{
Expand Down Expand Up @@ -278,8 +288,18 @@ export default function GlpSwap(props) {
const swapAmount = parseValue(swapValue, swapToken && swapToken.decimals);
const glpAmount = parseValue(glpValue, GLP_DECIMALS);

const needApproval =
isBuying && swapTokenAddress !== AddressZero && tokenAllowance && swapAmount && swapAmount.gt(tokenAllowance);
let needApproval = false;
if (swapTokenAddress === AddressZero) {
needApproval =
isBuying && tokenAllowance && swapAmount && (swapAmount.gt(tokenAllowance) || swapAmount.gt(tokenAllowanceOap));
} else {
needApproval =
isBuying &&
swapTokenAddress !== AddressZero &&
tokenAllowance &&
swapAmount &&
(swapAmount.gt(tokenAllowance) || swapAmount.gt(tokenAllowanceOap));
}

const swapUsdMin = getUsd(swapAmount, swapTokenAddress, false, infoTokens);
const glpUsdMax = glpAmount && glpPrice ? glpAmount.mul(glpPrice).div(expandDecimals(1, GLP_DECIMALS)) : undefined;
Expand Down Expand Up @@ -568,6 +588,32 @@ export default function GlpSwap(props) {
};

const approveFromToken = () => {
if (swapToken.address === AddressZero) {
approveTokens({
setIsApproving,
library,
tokenAddress: getTokenBySymbol(chainId, "WBNB").address,
spender: glpManagerAddress,
chainId: chainId,
onApproveSubmitted: () => {
setIsWaitingForApproval(true);
},
infoTokens,
getTokenInfo,
});
approveTokens({
setIsApproving,
library,
tokenAddress: getTokenBySymbol(chainId, "WBNB").address,
spender: oapRouterAddress,
chainId: chainId,
onApproveSubmitted: () => {
setIsWaitingForApproval(true);
},
infoTokens,
getTokenInfo,
});
}
approveTokens({
setIsApproving,
library,
Expand All @@ -580,19 +626,82 @@ export default function GlpSwap(props) {
infoTokens,
getTokenInfo,
});
approveTokens({
setIsApproving,
library,
tokenAddress: swapToken.address,
spender: oapRouterAddress,
chainId: chainId,
onApproveSubmitted: () => {
setIsWaitingForApproval(true);
},
infoTokens,
getTokenInfo,
});
};

const buyGlp = () => {
setIsSubmitting(true);
let minGlp = 0;
if (chainId === TESTNET) {
minGlp = glpAmount.mul(BASIS_POINTS_DIVISOR - savedSlippageAmount).div(BASIS_POINTS_DIVISOR * 2);
} else {
minGlp = glpAmount.mul(BASIS_POINTS_DIVISOR - savedSlippageAmount).div(BASIS_POINTS_DIVISOR);
}

const minGlp = glpAmount.mul(BASIS_POINTS_DIVISOR - savedSlippageAmount).div(BASIS_POINTS_DIVISOR);
const contractOapRouter = new ethers.Contract(oapRouterAddress, OapRouter.abi, library.getSigner());
const contractRewardRouter = new ethers.Contract(rewardRouterAddress, RewardRouter.abi, library.getSigner());
const method = swapTokenAddress === AddressZero ? "swapAndStakeETH" : "swapAndStake";
const methodRewardRouter = swapTokenAddress === AddressZero ? "mintAndStakeOapETH" : "mintAndStakeOap";

const contract = new ethers.Contract(rewardRouterAddress, RewardRouter.abi, library.getSigner());
const method = swapTokenAddress === AddressZero ? "mintAndStakeOapETH" : "mintAndStakeOap";
const params = swapTokenAddress === AddressZero ? [0, minGlp] : [swapTokenAddress, swapAmount, 0, minGlp];
const value = swapTokenAddress === AddressZero ? swapAmount : 0;
let adjustedUsdgSupply = bigNumberify(0);
for (let i = 0; i < tokenList.length; i++) {
const token = tokenList[i];
const tokenInfo = infoTokens[token.address];
if (tokenInfo && tokenInfo.usdgAmount) {
adjustedUsdgSupply = adjustedUsdgSupply.add(tokenInfo.usdgAmount);
}
}
let minWeightToken = infoTokens[visibleTokens[0].address];

callContract(chainId, contract, method, params, {
let minWeight = infoTokens[visibleTokens[0].address].usdgAmount.mul(BASIS_POINTS_DIVISOR).div(adjustedUsdgSupply);
visibleTokens.forEach((token) => {
// console.log("hahaha", formatEther(infoTokens[token?.address].weight));
const currentWeightBps = infoTokens[token?.address].usdgAmount.mul(BASIS_POINTS_DIVISOR).div(adjustedUsdgSupply);

if (currentWeightBps < minWeight) {
minWeightToken = token;
}
});

if (minWeightToken.address === swapTokenAddress) {
const params = [swapTokenAddress, swapAmount.toString(), "0", "0"];
callContract(chainId, contractRewardRouter, methodRewardRouter, params, {
value,
sentMsg: t`Buy submitted.`,
failMsg: t`Buy failed.`,
successMsg: t`${formatAmount(glpAmount, 18, 4, true)} OAP bought with ${formatAmount(
swapAmount,
swapTokenInfo.decimals,
4,
true
)} ${swapTokenInfo.symbol}!`,
setPendingTxns,
})
.then(async () => {})
.finally(() => {
setIsSubmitting(false);
});
return;
}
let _minGlp = chainId === TESTNET ? 0 : minGlp;
const params =
swapTokenAddress === AddressZero
? [minWeightToken.address, _minGlp, 0, 0]
: [swapTokenAddress, minWeightToken.address, parseEther(swapValue).toString(), 0, 0, 0];

callContract(chainId, contractOapRouter, method, params, {
value,
sentMsg: t`Buy submitted.`,
failMsg: t`Buy failed.`,
Expand Down Expand Up @@ -1190,9 +1299,7 @@ export default function GlpSwap(props) {
<tr key={token.symbol}>
<td>
<div className="App-card-title-info">
<div className="App-card-title-info-icon">
{/* <img src={tokenImage} alt={token.symbol} width="40px" /> */}
</div>
<div className="App-card-title-info-icon"></div>
<div className="App-card-title-info-text">
<div className="App-card-info-title">{token.name}</div>
<div className="App-card-info-subtitle">{token.symbol}</div>
Expand Down Expand Up @@ -1325,7 +1432,6 @@ export default function GlpSwap(props) {
return "";
}
}
// const tokenImage = importImage("ic_" + token.symbol.toLowerCase() + "_24.svg");
return (
<div className="App-card" key={token.symbol}>
<div className="App-card-title">
Expand All @@ -1337,7 +1443,6 @@ export default function GlpSwap(props) {
</div>
</div>
</div>
{/* <div className="App-card-divider" /> */}
<div className="App-card-content">
<div className="App-card-row">
<div className="label">
Expand Down
8 changes: 5 additions & 3 deletions src/config/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const CONTRACTS = {
OpenStaking: "0x214cEc9402F81622Ee97837Ced73C43f4f7f4a89",
OapRewardRouter: "0x0a27866A7943E90d3c65A60151ecfB0f79212BbA",
FeeSwap: "0x62b03139c01eE27f5CF046391D3c7AB4498cD363",
OAPRouter: "0x00F8f46081192F4F5a28239F3dd3212257362810",
},
[TESTNET]: {
// bsc testnet
Expand Down Expand Up @@ -124,7 +125,7 @@ const CONTRACTS = {
VaultReader: "0xedd72c61c4cDB7DD27a80d0E9759ae0B29f57DB4",
Reader: "0x63CFA7667eD8DeC340c4c8C174f86B7D6c2a2E54",
GlpManager: "0x5b7a04b9f5f88f215920fdcc704084349530dcc7",
RewardRouter: "0xdb49dE9C4812A36b724dcd82F7a3433bAd01b9D5",
RewardRouter: "0x26E8F916643fbfF603f2DD7348bA50b63A11b6b7",
RewardReader: "0x5A53FBfBc993f5dF1B2af6c41C7935e2Ef84f85e",
NATIVE_TOKEN: "0x612777Eea37a44F7a95E3B101C39e1E2695fa6C2",
OAP: "0xC6012955CEF9137FE9B1C01361c41FBf7E8dFfD9",
Expand All @@ -137,7 +138,7 @@ const CONTRACTS = {
BonusGmxTracker: "0x4e30C59431681800A23CD0E4dcdA651A92ef247e",
FeeGmxTracker: "0x710F155CCA8df2DC653356272d8186b5fAF406cc",
StakedGlpTracker: "0xb71493222f5899407e01b840a428c33b9c03211d",
FeeGlpTracker: "0xa5c9f9deebaafcf46836c20105aeece58057634b",
FeeGlpTracker: "0xAa36DA9a236181052EB0c10d36e9459f9cEB641D",

StakedGmxDistributor: "0x4980dF9955868fBB580b6c2D7D68Cbf61E00850c",
StakedGlpDistributor: "0xf9063fBC9481C13EB23883473E8B435857039d88",
Expand Down Expand Up @@ -169,8 +170,9 @@ const CONTRACTS = {
FastPriceFeed: "0xAE11B05Bf243b234F850E745327B06CAf08af4Cb",
VaultPriceFeed: "0xeaE0398FBD233f8b50bCC3Ba9e81F92598B77dd0",
OpenStaking: "0x52c0bf0C0bF20377A478d7DD88B9c08358D9f1Fd",
OapRewardRouter: "0xdb49dE9C4812A36b724dcd82F7a3433bAd01b9D5",
OapRewardRouter: "0xc12c23162d0D9Cb956E42dB3d90f512E9f3F4A33",
FeeSwap: "0xE94bC997f8Ad62f29683BA6dd1cE7d3B8C5fd315",
OAPRouter: "0xC1aFE17a22520C5ee89d4A644C447BDe86C377fF",
},
[ARBITRUM_TESTNET]: {
// arbitrum testnet
Expand Down
1 change: 1 addition & 0 deletions src/config/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export const TOKENS: { [chainId: number]: Token[] } = {
decimals: 18,
address: "0x612777Eea37a44F7a95E3B101C39e1E2695fa6C2",
imageUrl: "https://assets.coingecko.com/coins/images/279/small/ethereum.png?1595348880",
isTempHidden: true,
},
{
name: "Binance Coin",
Expand Down
7 changes: 1 addition & 6 deletions src/lib/contracts/callContract.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export async function callContract(
if (opts.value) {
txnOpts.value = opts.value;
}

// txnOpts.gasLimit = 1000000;
txnOpts.gasLimit = opts.gasLimit ? opts.gasLimit : await getGasLimit(contract, method, params, opts.value);

await setGasPrice(txnOpts, contract.provider, chainId);
Expand Down Expand Up @@ -73,11 +73,6 @@ export async function callContract(

const [message, type, errorData] = extractError(e);

console.log("message", message);
console.log("========");
console.log("type", type);
console.log("========");
console.log("error data", errorData);
switch (type) {
case NOT_ENOUGH_FUNDS:
failMsg = (
Expand Down
Loading