ethers#Contract JavaScript Examples

The following examples show how to use ethers#Contract. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ethereumFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 6 votes vote down vote up
// This function calls the pair contract to fetch the reserves stored in a the liquidity pool between the token of address1 and the token
// of address2. Some extra logic was needed to make sure that the results were returned in the correct order, as
// `pair.getReserves()` would always return the reserves in the same order regardless of which order the addresses were.
//    `address1` - An Ethereum address of the token to trade from (either a ERC20 token or AUT)
//    `address2` - An Ethereum address of the token to trade to (either a ERC20 token or AUT)
//    `pair` - The pair contract for the two tokens
export async function fetchReserves(address1, address2, pair, signer) {
  try {

    // Get decimals for each coin
    const coin1 = new Contract(address1, ERC20.abi, signer);
    const coin2 = new Contract(address2, ERC20.abi, signer);

    const coin1Decimals = await getDecimals(coin1);
    const coin2Decimals = await getDecimals(coin2);

    // Get reserves
    const reservesRaw = await pair.getReserves();

    // Put the results in the right order
    const results =  [
      (await pair.token0()) === address1 ? reservesRaw[0] : reservesRaw[1],
      (await pair.token1()) === address2 ? reservesRaw[1] : reservesRaw[0],
    ];

    // Scale each to the right decimal place
    return [
      (results[0]*10**(-coin1Decimals)),
      (results[1]*10**(-coin2Decimals))
    ]
  } catch (err) {
    console.log("error!");
    console.log(err);
    return [0, 0];
  }
}
Example #2
Source File: ethereumFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 6 votes vote down vote up
//This function checks if a ERC20 token exists for a given address
//    `address` - The Ethereum address to be checked
//    `signer` - The current signer
export function doesTokenExist(address, signer) {
  try {
    return new Contract(address, ERC20.abi, signer);
  } catch (err) {
    return false;
  }
}
Example #3
Source File: ethereumFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 6 votes vote down vote up
// This function returns an object with 2 fields: `balance` which container's the account's balance in the particular token,
// and `symbol` which is the abbreviation of the token name. To work correctly it must be provided with 4 arguments:
//    `accountAddress` - An Ethereum address of the current user's account
//    `address` - An Ethereum address of the token to check for (either a token or AUT)
//    `provider` - The current provider
//    `signer` - The current signer
export async function getBalanceAndSymbol(
  accountAddress,
  address,
  provider,
  signer,
  weth_address,
  coins
) {
  try {
    if (address === weth_address) {
      const balanceRaw = await provider.getBalance(accountAddress);

      return {
        balance: ethers.utils.formatEther(balanceRaw),
        symbol: coins[0].abbr,
      };
    } else {
      const token = new Contract(address, ERC20.abi, signer);
      const tokenDecimals = await getDecimals(token);
      const balanceRaw = await token.balanceOf(accountAddress);
      const symbol = await token.symbol();

      return {
        balance: balanceRaw*10**(-tokenDecimals),
        symbol: symbol,
      };
    }
  } catch (error) {
    console.log ('The getBalanceAndSymbol function had an error!');
    console.log (error)
    return false;
  }
}
Example #4
Source File: ethereumFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 6 votes vote down vote up
//This function returns the conversion rate between two token addresses
//    `address1` - An Ethereum address of the token to swaped from (either a token or AUT)
//    `address2` - An Ethereum address of the token to swaped to (either a token or AUT)
//    `amountIn` - Amount of the token at address 1 to be swaped from
//    `routerContract` - The router contract to carry out this swap
export async function getAmountOut(
  address1,
  address2,
  amountIn,
  routerContract,
  signer
) {
  try {
    const token1 = new Contract(address1, ERC20.abi, signer);
    const token1Decimals = await getDecimals(token1);

    const token2 = new Contract(address2, ERC20.abi, signer);
    const token2Decimals = await getDecimals(token2);

    const values_out = await routerContract.getAmountsOut(
      ethers.utils.parseUnits(String(amountIn), token1Decimals),
      [address1, address2]
    );
    const amount_out = values_out[1]*10**(-token2Decimals);
    console.log('amount out: ', amount_out)
    return Number(amount_out);
  } catch {
    return false;
  }
}
Example #5
Source File: Mkr__factory.js    From eth-sdk with MIT License 5 votes vote down vote up
static connect(address, signerOrProvider) {
        return new Contract(address, _abi, signerOrProvider);
    }
Example #6
Source File: Dai__factory.js    From eth-sdk with MIT License 5 votes vote down vote up
static connect(address, signerOrProvider) {
        return new Contract(address, _abi, signerOrProvider);
    }
Example #7
Source File: ProxyStandardStorageSlot__factory.js    From eth-sdk with MIT License 5 votes vote down vote up
static connect(address, signerOrProvider) {
        return new Contract(address, _abi, signerOrProvider);
    }
Example #8
Source File: ProxyCustomImplementation__factory.js    From eth-sdk with MIT License 5 votes vote down vote up
static connect(address, signerOrProvider) {
        return new Contract(address, _abi, signerOrProvider);
    }
Example #9
Source File: Uniswap__factory.js    From eth-sdk with MIT License 5 votes vote down vote up
static connect(address, signerOrProvider) {
        return new Contract(address, _abi, signerOrProvider);
    }
Example #10
Source File: index.js    From eth-sdk with MIT License 5 votes vote down vote up
export function getContract(address, abi, defaultSignerOrProvider) {
    return new Contract(address, abi, defaultSignerOrProvider);
}
Example #11
Source File: ethereumFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
// This function returns the reserves stored in a the liquidity pool between the token of address1 and the token
// of address2, as well as the liquidity tokens owned by accountAddress for that pair.
//    `address1` - An Ethereum address of the token to trade from (either a token or AUT)
//    `address2` - An Ethereum address of the token to trade to (either a token or AUT)
//    `factory` - The current factory
//    `signer` - The current signer
export async function getReserves(
  address1,
  address2,
  factory,
  signer,
  accountAddress
) {
  try {
    const pairAddress = await factory.getPair(address1, address2);
    const pair = new Contract(pairAddress, PAIR.abi, signer);
  
    if (pairAddress !== '0x0000000000000000000000000000000000000000'){
  
      const reservesRaw = await fetchReserves(address1, address2, pair, signer);
      const liquidityTokens_BN = await pair.balanceOf(accountAddress);
      const liquidityTokens = Number(
        ethers.utils.formatEther(liquidityTokens_BN)
      );
    
      return [
        reservesRaw[0].toPrecision(6),
        reservesRaw[1].toPrecision(6),
        liquidityTokens,
      ];
    } else {
      console.log("no reserves yet");
      return [0,0,0];
    }
  }catch (err) {
    console.log("error!");
    console.log(err);
    return [0, 0, 0];
  }
}
Example #12
Source File: ethereumFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
// This function swaps two particular tokens / AUT, it can handle switching from AUT to ERC20 token, ERC20 token to AUT, and ERC20 token to ERC20 token.
// No error handling is done, so any issues can be caught with the use of .catch()
// To work correctly, there needs to be 7 arguments:
//    `address1` - An Ethereum address of the token to trade from (either a token or AUT)
//    `address2` - An Ethereum address of the token to trade to (either a token or AUT)
//    `amount` - A float or similar number representing the value of address1's token to trade
//    `routerContract` - The router contract to carry out this trade
//    `accountAddress` - An Ethereum address of the current user's account
//    `signer` - The current signer
export async function swapTokens(
  address1,
  address2,
  amount,
  routerContract,
  accountAddress,
  signer
) {
  const tokens = [address1, address2];
  const time = Math.floor(Date.now() / 1000) + 200000;
  const deadline = ethers.BigNumber.from(time);

  const token1 = new Contract(address1, ERC20.abi, signer);
  const tokenDecimals = await getDecimals(token1);
  
  const amountIn = ethers.utils.parseUnits(amount, tokenDecimals);
  const amountOut = await routerContract.callStatic.getAmountsOut(
    amountIn,
    tokens
  );

  await token1.approve(routerContract.address, amountIn);
  const wethAddress = await routerContract.WETH();

  if (address1 === wethAddress) {
    // Eth -> Token
    await routerContract.swapExactETHForTokens(
      amountOut[1],
      tokens,
      accountAddress,
      deadline,
      { value: amountIn }
    );
  } else if (address2 === wethAddress) {
    // Token -> Eth
    await routerContract.swapExactTokensForETH(
      amountIn,
      amountOut[1],
      tokens,
      accountAddress,
      deadline
    );
  } else {
    await routerContract.swapExactTokensForTokens(
      amountIn,
      amountOut[1],
      tokens,
      accountAddress,
      deadline
    );
  }
}
Example #13
Source File: ethereumFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
export function getFactory(address, signer) {
  return new Contract(address, FACTORY.abi, signer);
}
Example #14
Source File: ethereumFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
export function getWeth(address, signer) {
  return new Contract(address, ERC20.abi, signer);
}
Example #15
Source File: ethereumFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
export function getRouter(address, signer) {
  return new Contract(address, ROUTER.abi, signer);
}
Example #16
Source File: LiquidityFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
// Function used to get a quote of the liquidity removal
//    `address1` - An Ethereum address of the coin to recieve (either a token or AUT)
//    `address2` - An Ethereum address of the coin to recieve (either a token or AUT)
//    `liquidity` - The amount of liquidity tokens the user will burn to get their tokens back
//    `factory` - The current factory
//    `signer` - The current signer

export async function quoteRemoveLiquidity(
  address1,
  address2,
  liquidity,
  factory,
  signer
) {
  const pairAddress = await factory.getPair(address1, address2);
  console.log("pair address", pairAddress);
  const pair = new Contract(pairAddress, PAIR.abi, signer);

  const reservesRaw = await fetchReserves(address1, address2, pair, signer); // Returns the reserves already formated as ethers
  const reserveA = reservesRaw[0];
  const reserveB = reservesRaw[1];

  const feeOn =
    (await factory.feeTo()) !== 0x0000000000000000000000000000000000000000;

  const _kLast = await pair.kLast();
  const kLast = Number(ethers.utils.formatEther(_kLast));

  const _totalSupply = await pair.totalSupply();
  let totalSupply = Number(ethers.utils.formatEther(_totalSupply));

  if (feeOn && kLast > 0) {
    const feeLiquidity =
      (totalSupply * (Math.sqrt(reserveA * reserveB) - Math.sqrt(kLast))) /
      (5 * Math.sqrt(reserveA * reserveB) + Math.sqrt(kLast));
    totalSupply = totalSupply + feeLiquidity;
  }

  const Aout = (reserveA * liquidity) / totalSupply;
  const Bout = (reserveB * liquidity) / totalSupply;

  return [liquidity, Aout, Bout];
}
Example #17
Source File: LiquidityFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
export async function quoteAddLiquidity(
  address1,
  address2,
  amountADesired,
  amountBDesired,
  factory,
  signer
) {

  const pairAddress = await factory.getPair(address1, address2);
  const pair = new Contract(pairAddress, PAIR.abi, signer);

  const reservesRaw = await fetchReserves(address1, address2, pair, signer); // Returns the reserves already formated as ethers
  const reserveA = reservesRaw[0];
  const reserveB = reservesRaw[1];

  if (reserveA === 0 && reserveB === 0) {
    const amountOut = await quoteMintLiquidity(
      address1,
      address2,
      amountADesired,
      amountBDesired,
      factory,
      signer);
    return [
      amountADesired,
      amountBDesired,
      amountOut.toPrecision(8),
    ];
  } else {
    const amountBOptimal = quote(amountADesired, reserveA, reserveB);
    if (amountBOptimal <= amountBDesired) {
      const amountOut = await quoteMintLiquidity(
        address1,
        address2,
        amountADesired,
        amountBOptimal,
        factory,
        signer);
      return [
        amountADesired,
        amountBOptimal,
        amountOut.toPrecision(8),
      ];
    } else {
      const amountAOptimal = quote(
        amountBDesired,
        reserveB,
        reserveA
      );
      const amountOut = await quoteMintLiquidity(
        address1,
        address2,
        amountAOptimal,
        amountBDesired,
        factory,
        signer);
      return [
        amountAOptimal,
        amountBDesired,
        amountOut.toPrecision(8),
      ];
    }
  }
}
Example #18
Source File: LiquidityFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 5 votes vote down vote up
// Function used to get a quote of the liquidity addition
//    `address1` - An Ethereum address of the coin to recieve (either a token or AUT)
//    `address2` - An Ethereum address of the coin to recieve (either a token or AUT)
//    `amountA_desired` - The prefered value of the first token that the user would like to deploy as liquidity
//    `amountB_desired` - The prefered value of the second token that the user would like to deploy as liquidity
//    `factory` - The current factory
//    `signer` - The current signer

async function quoteMintLiquidity(
  address1,
  address2,
  amountA,
  amountB,
  factory,
  signer
){
  const MINIMUM_LIQUIDITY = 1000;
  let _reserveA = 0;
  let _reserveB = 0;
  let totalSupply = 0;
  [_reserveA, _reserveB, totalSupply] = await factory.getPair(address1, address2).then(async (pairAddress) => {
    if (pairAddress !== '0x0000000000000000000000000000000000000000'){
      const pair = new Contract(pairAddress, PAIR.abi, signer);

      const reservesRaw = await fetchReserves(address1, address2, pair, signer); // Returns the reserves already formated as ethers
      const reserveA = reservesRaw[0];
      const reserveB = reservesRaw[1];
    
      const _totalSupply = await pair.totalSupply();
      const totalSupply = Number(ethers.utils.formatEther(_totalSupply));
      return [reserveA, reserveB, totalSupply]
    } else {
      return [0,0,0]
    }
  });

  const token1 = new Contract(address1, ERC20.abi, signer);
  const token2 = new Contract(address2, ERC20.abi, signer);

  // Need to do all this decimals work to account for 0 decimal numbers

  const token1Decimals = await getDecimals(token1);
  const token2Decimals = await getDecimals(token2);

  const valueA = amountA*(10**token1Decimals);
  const valueB = amountB*(10**token2Decimals);

  const reserveA = _reserveA*(10**token1Decimals);
  const reserveB = _reserveB*(10**token2Decimals);

  if (totalSupply == 0){
    return Math.sqrt(((valueA * valueB)-MINIMUM_LIQUIDITY))*10**(-18);
  };
  
  return (
    Math.min(valueA*totalSupply/reserveA, valueB*totalSupply/reserveB)
  );
}
Example #19
Source File: CurveStake.js    From origin-dollar with MIT License 4 votes vote down vote up
CurveStake = ({ rpcProvider, isMobile }) => {
  const { active } = useWeb3React()
  const [crvBaseApy, setCrvBaseApy] = useState(false)
  const [crvBoostedApy, setCrvBoostedApy] = useState(false)
  const [ognApy, setOgnApy] = useState(false)
  const [totalBaseApy, setTotalBaseApy] = useState(false)
  const [totalBoostedApy, setTotalBoostedApy] = useState(false)
  const [gaugeContract, setGaugeContract] = useState(false)
  const [gaugeControllerContract, setGaugeControllerContract] = useState(false)
  const chainId = useStoreState(ContractStore, (s) => s.chainId)
  const readOnlyProvider = useStoreState(
    ContractStore,
    (s) => s.readOnlyProvider
  )
  const ognPrice = useStoreState(CoinStore, (s) => s.ogn.price)
  const { baseApy, virtualPrice, curveRate } = useCurveStaking()

  const setupContracts = () => {
    if (chainId !== 1 || !readOnlyProvider) return

    setGaugeContract(
      new Contract(
        addresses.mainnet.CurveOUSDFactoryGauge,
        gaugeMiniAbi,
        readOnlyProvider
      )
    )
    setGaugeControllerContract(
      new Contract(
        addresses.mainnet.CurveGaugeController,
        gaugeControllerMiniAbi,
        readOnlyProvider
      )
    )
  }

  /*
   * Using `getApy` function from the curve source code:
   *
   * https://github.com/curvefi/curve-js/blob/efbf7eebf31bf67c07e67f63796eb01a304bc5d1/src/pools.ts#L1131-L1149
   */
  const fetchGaugeApy = async () => {
    const [weight, inflation, workingSupply] = await Promise.all([
      gaugeControllerContract['gauge_relative_weight(address)'](
        gaugeContract.address
      ),
      gaugeContract.inflation_rate(),
      gaugeContract.working_supply(),
    ])

    // can not divide by zero
    if (workingSupply.toString() === '0' || virtualPrice.toString() === '0') {
      setCrvBaseApy(0)
      setCrvBoostedApy(0)
      return
    }

    // important to first multiply and in the end divide, to keep the precision
    const rate = inflation
      .mul(weight)
      .mul(BigNumber.from('31536000'))
      // for better precision
      .mul(BigNumber.from('1000000'))
      .mul(BigNumber.from('2'))
      .div(BigNumber.from('5')) // same as mul by 0.4
      .div(workingSupply)
      .div(virtualPrice)

    // multiply rate with the USD price of CRV token
    const baseApy = rate.mul(BigNumber.from(Math.floor(curveRate * 100)))

    // boosted APY is 2.5 times base APY
    const boostedApy = baseApy.mul(BigNumber.from('5')).div(BigNumber.from('2')) // same as mul by 2.5

    // divided by 1000 to counteract the precision increase a few lines above
    setCrvBaseApy(baseApy.toNumber() / 1000000)
    setCrvBoostedApy(boostedApy.toNumber() / 1000000)
  }

  const fetchOgnApy = async () => {
    const totalSupply = await gaugeContract.totalSupply()
    const rewardData = await gaugeContract.reward_data(addresses.mainnet.OGN)

    const tokensReceived = rewardData.rate.mul(BigNumber.from('31536000')) // seconds in a year
    const apy = tokensReceived
      // times 10000 so we keep the decimal point precision
      .mul(BigNumber.from(Math.round(ognPrice * 10000)))
      // important to first multiply and in the end divide, to keep the precision
      .div(totalSupply)
      .toNumber()

    // divide only by 100 instead of 10000 for percentage representation
    setOgnApy(apy / 100)
  }

  useEffect(() => {
    setupContracts()
  }, [readOnlyProvider])

  useEffect(() => {
    if (
      !gaugeContract ||
      !gaugeControllerContract ||
      !virtualPrice ||
      !curveRate ||
      !ognPrice
    )
      return

    fetchGaugeApy()
    fetchOgnApy()
  }, [
    gaugeContract,
    gaugeControllerContract,
    virtualPrice,
    curveRate,
    ognPrice,
  ])

  useEffect(() => {
    if (
      baseApy === false ||
      crvBaseApy === false ||
      crvBoostedApy === false ||
      ognApy === false
    )
      return

    setTotalBaseApy(baseApy + crvBaseApy + ognApy)
    setTotalBoostedApy(baseApy + crvBoostedApy + ognApy)
  }, [baseApy, crvBaseApy, crvBoostedApy, ognApy])

  return (
    <>
      <>
        <div className="home d-flex flex-column">
          <div className="crv-header">
            <h1>
              {fbt(
                'Earn OGN and CRV rewards by providing liquidity on Curve',
                'Earn OGN curve title'
              )}
            </h1>
            <div className="d-flex flex-md-row flex-column w-100 ">
              <div className="box black mr-md-10 d-flex flex-column align-items-center justify-content-center">
                <div className="title">{fbt('Total APY', 'Total APY')}</div>
                <div className="value">
                  {totalBaseApy !== false && totalBoostedApy !== false
                    ? `${formatCurrency(totalBaseApy, 2)}-${formatCurrency(
                        totalBoostedApy,
                        2
                      )}%`
                    : '--%'}
                </div>
              </div>
              <div className="box group flex-grow-1">
                <div className="d-flex flex-md-row flex-column h-100">
                  <div className="box-item d-flex flex-row flex-md-column border-right-md col-md-4 align-items-center justify-content-md-center justify-content-between">
                    <div className="title">{fbt('Base APY', 'Base APY')}</div>
                    <div className="value">
                      {baseApy !== false
                        ? `${formatCurrency(baseApy, 2)}%`
                        : '--%'}
                    </div>
                  </div>
                  <div className="box-item d-flex flex-row flex-md-column border-right-md col-md-4 align-items-center justify-content-md-center justify-content-between">
                    <div className="title">{fbt('CRV APY', 'CRV APY')}</div>
                    <div className="value">
                      {crvBaseApy !== false && crvBoostedApy !== false
                        ? `${formatCurrency(crvBaseApy, 2)}-${formatCurrency(
                            crvBoostedApy,
                            2
                          )}%`
                        : '--%'}
                    </div>
                  </div>
                  <div className="d-flex flex-row flex-md-column col-md-4 align-items-center justify-content-md-center justify-content-between">
                    <div className="title">{fbt('OGN APY', 'OGN APY')}</div>
                    <div className="value">
                      {ognApy !== false
                        ? `${formatCurrency(ognApy, 2)}%`
                        : '--%'}
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div className="curve-logo-holder d-flex">
              <div className="powered-by">
                {fbt('Powered by', 'Powered by')}
              </div>
              <img src={assetRootPath('/images/curve-logo-smaller.svg')} />
            </div>
          </div>
          <div className="crv-body d-flex flex-md-row flex-column">
            <div className="step-holder col-md-4 d-flex flex-column align-items-center justify-content-start border-right2-md border-bottom-sm">
              <div className="step d-flex align-items-center justify-content-center">
                1
              </div>
              <div className="text-center description pl-md-0">
                {fbt(
                  'Provide OUSD + USDT/USDC/ DAI liquidity to the Curve OUSD pool',
                  'Provide OUSD + USDT/USDC/DAI liquidity to the Curve OUSD pool'
                )}
              </div>
            </div>
            <div className="step-holder col-md-4 d-flex flex-column align-items-center justify-content-start border-right2-md border-bottom-sm">
              <div className="step d-flex align-items-center justify-content-center">
                2
              </div>
              <div className="text-center description">
                {fbt(
                  'Click “Deposit & stake in gauge”',
                  'Click “Deposit & stake in gauge”'
                )}
              </div>
              <a
                href="https://curve.fi/factory/9/deposit"
                target="_blank"
                rel="noopener noreferrer"
                className="btn btn-blue mt-md-auto"
                onClick={() => {
                  analytics.track('On Add Liquidity', {
                    category: 'navigation',
                  })
                }}
              >
                {fbt('Add Liquidity', 'Add Liquidity Button')}
              </a>
            </div>
            <div className="step-holder col-md-4 d-flex flex-column align-items-center justify-content-start">
              <div className="step d-flex align-items-center justify-content-center">
                3
              </div>
              <div className="text-center description pr-md-0">
                {fbt(
                  'Once staked, click the “Claim” button on Curve to claim your OGN & CRV rewards',
                  'Once staked, click the “Claim” button on Curve to claim your OGN & CRV rewards'
                )}
              </div>
              <a
                href="https://curve.fi/factory/9/withdraw"
                target="_blank"
                rel="noopener noreferrer"
                className="btn btn-blue mt-md-auto"
                onClick={() => {
                  analytics.track('On Claim Rewards', {
                    category: 'navigation',
                  })
                }}
              >
                {fbt('Claim Rewards', 'Claim Rewards Button')}
              </a>
            </div>
          </div>
        </div>
      </>
      <style jsx>{`
        .home {
          min-width: 940px;
          border-radius: 10px;
          box-shadow: 0 2px 14px 0 rgba(0, 0, 0, 0.1);
          border: solid 1px #dfe9ee;
          background-color: white;
          padding: 60px 0px 0px 0px;
        }

        .crv-header {
          padding: 0px 44px;
          margin-bottom: 60px;
          position: relative;
        }

        .curve-logo-holder {
          position: absolute;
          bottom: -40px;
          right: 20px;
        }

        .crv-body {
          border-radius: 0 0 10px 10px;
          border-top: solid 1px #e9eff4;
          background-color: #fafbfc;
          padding: 40px 30px;
        }

        .step {
          width: 50px;
          height: 50px;
          border-radius: 25px;
          background-color: #183140;
          color: white;
          font-size: 18px;
          font-weight: bold;
          margin-bottom: 25px;
        }

        h1 {
          font-family: Poppins;
          font-size: 24px;
          font-weight: 600;
          text-align: center;
          color: black;
          margin-bottom: 25px;
        }

        .box {
          border-radius: 10px;
          border: solid 1px black;
          background-color: #183140;
          color: white;
          min-height: 126px;
          min-width: 226px;
        }

        .box.black {
          background-color: black;
        }

        .box .title {
          font-size: 14px;
          margin-bottom: 5px;
        }

        .box .value {
          font-size: 18px;
          font-weight: bold;
        }

        .mr-md-10 {
          margin-right: 10px;
        }

        .box.group {
          padding-top: 20px;
          padding-bottom: 20px;
        }

        .box.group .title {
          font-size: 14px;
          margin-bottom: 5px;
        }

        .box.group .value {
          font-size: 18px;
          font-weight: bold;
        }

        .border-right-md {
          border-right: solid 1px #000;
        }

        .border-right2-md {
          border-right: solid 1px #cdd7e0;
        }

        .border-bottom-sm {
          border-bottom: 0;
        }

        .step-holder {
          min-height: 240px;
        }

        .description {
          font-size: 18px;
          padding: 0px 30px;
        }

        a.btn {
          margin: 0px 20px;
          padding: 0px 40px;
        }

        .powered-by {
          font-size: 10px;
          color: #576c7a;
        }

        @media (max-width: 799px) {
          .mr-md-10 {
            margin-right: 0px;
          }

          .home {
            min-width: auto;
            padding: 40px 0px 0px 0px;
          }

          h1 {
            font-size: 20px;
            margin-bottom: 20px;
          }

          .crv-header {
            padding: 0px 20px;
            margin-bottom: 40px;
          }

          .curve-logo-holder {
            bottom: -30px;
          }

          .border-right2-md {
            border-right: 0;
          }

          .border-right-md {
            border-right: 0;
          }

          .border-bottom-sm {
            border-bottom: solid 1px #cdd7e0;
          }

          .crv-body {
            padding: 10px 30px;
          }

          .box {
            min-height: 126px;
            min-width: auto;
            margin-bottom: 10px;
          }

          .box.group {
            margin-bottom: 0px;
          }

          .box-item {
            margin-bottom: 20px;
          }

          .step-holder {
            min-height: auto;
            padding: 30px 0px;
          }

          .description {
            font-size: 16px;
            padding: 0px 15px;
          }

          a.btn {
            margin-top: 25px;
          }
        }
      `}</style>
    </>
  )
}
Example #20
Source File: contracts.js    From origin-dollar with MIT License 4 votes vote down vote up
/* fetchId - used to prevent race conditions.
 * Sometimes "setupContracts" is called twice with very little time in between and it can happen
 * that the call issued first (for example with not yet signed in account) finishes after the second
 * call. We must make sure that previous calls to setupContracts don't override later calls Stores
 */
export async function setupContracts(account, library, chainId, fetchId) {
  /* Using StaticJsonRpcProvider instead of JsonRpcProvider so it doesn't constantly query
   * the network for the current chainId. In case chainId changes, we rerun setupContracts
   * anyway. And StaticJsonRpcProvider also prevents "detected network changed" errors when
   * running node in forked mode.
   */
  const jsonRpcProvider = new ethers.providers.StaticJsonRpcProvider(
    process.env.ETHEREUM_RPC_PROVIDER,
    { chainId: parseInt(process.env.ETHEREUM_RPC_CHAIN_ID) }
  )

  let provider = jsonRpcProvider

  let walletConnected = account && library

  const getContract = (address, abi, overrideProvider) => {
    try {
      return new ethers.Contract(
        address,
        abi,
        overrideProvider ? overrideProvider : provider
      )
    } catch (e) {
      console.error(
        `Error creating contract in [getContract] with address:${address} abi:${JSON.stringify(
          abi
        )}`
      )
      throw e
    }
  }

  let network
  try {
    network = require(`../../${chainId === 1 ? 'prod.' : ''}network.json`)
  } catch (e) {
    console.error('network.json file not present')
    // contract addresses not present no need to continue initialisation
    return
  }

  const contracts = {}
  for (const key in network.contracts) {
    // Use Proxy address if one exists
    const address = network.contracts[`${key}Proxy`]
      ? network.contracts[`${key}Proxy`].address
      : network.contracts[key].address

    try {
      contracts[key] = new ethers.Contract(
        address,
        network.contracts[key].abi,
        null
      )
    } catch (e) {
      console.error(
        `Error creating contract in [setup] with address:${address} name:${key}`
      )
      throw e
    }
  }

  const ousdProxy = contracts['OUSDProxy']
  const vaultProxy = contracts['VaultProxy']
  const OGNStakingProxy = contracts['OGNStakingProxy']
  let liquidityRewardOUSD_USDTProxy,
    liquidityRewardOUSD_DAIProxy,
    liquidityRewardOUSD_USDCProxy

  if (process.env.ENABLE_LIQUIDITY_MINING === 'true') {
    liquidityRewardOUSD_USDTProxy = contracts['LiquidityRewardOUSD_USDTProxy']
    liquidityRewardOUSD_DAIProxy = contracts['LiquidityRewardOUSD_DAIProxy']
    liquidityRewardOUSD_USDCProxy = contracts['LiquidityRewardOUSD_USDCProxy']
  }

  let usdt,
    dai,
    tusd,
    usdc,
    ousd,
    vault,
    ogn,
    wousd,
    flipper,
    uniV2OusdUsdt,
    uniV2OusdUsdt_iErc20,
    uniV2OusdUsdt_iUniPair,
    uniV2OusdUsdc,
    uniV2OusdUsdc_iErc20,
    uniV2OusdUsdc_iUniPair,
    uniV2OusdDai,
    uniV2OusdDai_iErc20,
    uniV2OusdDai_iUniPair,
    uniV3OusdUsdt,
    uniV3DaiUsdt,
    uniV3UsdcUsdt,
    uniV3NonfungiblePositionManager,
    uniV3SwapRouter,
    uniV2Router,
    sushiRouter,
    uniV3SwapQuoter,
    liquidityOusdUsdt,
    liquidityOusdUsdc,
    liquidityOusdDai,
    ognStaking,
    ognStakingView,
    compensation,
    chainlinkEthAggregator,
    chainlinkFastGasAggregator,
    curveAddressProvider

  let iVaultJson,
    wousdJSON,
    liquidityRewardJson,
    iErc20Json,
    iUniPairJson,
    uniV3PoolJson,
    uniV3FactoryJson,
    uniV3NonfungiblePositionManagerJson,
    uniV3SwapRouterJson,
    uniV2SwapRouterJson,
    uniV3SwapQuoterJson,
    singleAssetStakingJson,
    compensationClaimsJson,
    chainlinkAggregatorV3Json,
    curveAddressProviderJson

  try {
    iVaultJson = require('../../abis/IVault.json')
    liquidityRewardJson = require('../../abis/LiquidityReward.json')
    iErc20Json = require('../../abis/IERC20.json')
    iUniPairJson = require('../../abis/IUniswapV2Pair.json')
    singleAssetStakingJson = require('../../abis/SingleAssetStaking.json')
    compensationClaimsJson = require('../../abis/CompensationClaims.json')
    uniV3PoolJson = require('../../abis/UniswapV3Pool.json')
    uniV3FactoryJson = require('../../abis/UniswapV3Factory.json')
    uniV3NonfungiblePositionManagerJson = require('../../abis/UniswapV3NonfungiblePositionManager.json')
    uniV3SwapRouterJson = require('../../abis/UniswapV3SwapRouter.json')
    uniV2SwapRouterJson = require('../../abis/UniswapV2Router.json')
    uniV3SwapQuoterJson = require('../../abis/UniswapV3Quoter.json')
    chainlinkAggregatorV3Json = require('../../abis/ChainlinkAggregatorV3Interface.json')
    curveAddressProviderJson = require('../../abis/CurveAddressProvider.json')
    wousdJSON = require('../../abis/WOUSD.json')
  } catch (e) {
    console.error(`Can not find contract artifact file: `, e)
  }

  vault = getContract(vaultProxy.address, iVaultJson.abi)

  if (process.env.ENABLE_LIQUIDITY_MINING === 'true') {
    liquidityOusdUsdt = getContract(
      liquidityRewardOUSD_USDTProxy.address,
      liquidityRewardJson.abi
    )
    liquidityOusdUsdc = getContract(
      liquidityRewardOUSD_USDCProxy.address,
      liquidityRewardJson.abi
    )
    liquidityOusdDai = getContract(
      liquidityRewardOUSD_DAIProxy.address,
      liquidityRewardJson.abi
    )
  }

  ognStaking = getContract(OGNStakingProxy.address, singleAssetStakingJson.abi)
  ognStakingView = getContract(
    OGNStakingProxy.address,
    singleAssetStakingJson.abi,
    jsonRpcProvider
  )

  ousd = getContract(ousdProxy.address, network.contracts['OUSD'].abi)
  usdt = getContract(addresses.mainnet.USDT, usdtAbi.abi)
  usdc = getContract(addresses.mainnet.USDC, usdcAbi.abi)
  dai = getContract(addresses.mainnet.DAI, daiAbi.abi)
  ogn = getContract(addresses.mainnet.OGN, ognAbi)
  wousd = getContract(addresses.mainnet.WOUSDProxy, wousdJSON.abi)
  flipper = getContract(addresses.mainnet.Flipper, flipperAbi)

  uniV3OusdUsdt = getContract(
    addresses.mainnet.uniswapV3OUSD_USDT,
    uniV3PoolJson.abi
  )
  uniV3SwapRouter = getContract(
    addresses.mainnet.uniswapV3Router,
    uniV3SwapRouterJson.abi
  )
  uniV3SwapQuoter = getContract(
    addresses.mainnet.uniswapV3Quoter,
    uniV3SwapQuoterJson.abi
  )
  uniV2Router = getContract(
    addresses.mainnet.uniswapV2Router,
    uniV2SwapRouterJson.abi
  )
  sushiRouter = getContract(
    addresses.mainnet.sushiSwapRouter,
    uniV2SwapRouterJson.abi
  )
  chainlinkEthAggregator = getContract(
    addresses.mainnet.chainlinkETH_USD,
    chainlinkAggregatorV3Json.abi
  )

  chainlinkFastGasAggregator = getContract(
    addresses.mainnet.chainlinkFAST_GAS,
    chainlinkAggregatorV3Json.abi
  )

  curveAddressProvider = getContract(
    addresses.mainnet.CurveAddressProvider,
    curveAddressProviderJson.abi
  )

  if (process.env.ENABLE_LIQUIDITY_MINING === 'true') {
    uniV2OusdUsdt = null
    uniV2OusdUsdc = null
    uniV2OusdDai = null
    throw new Error(
      'uniV2OusdUsdt, uniV2OusdUsdc, uniV2OusdDai mainnet address is missing'
    )
  }

  compensation = getContract(
    addresses.mainnet.CompensationClaims,
    compensationClaimsJson.abi
  )

  if (process.env.ENABLE_LIQUIDITY_MINING === 'true') {
    uniV2OusdUsdt_iErc20 = getContract(uniV2OusdUsdt.address, iErc20Json.abi)
    uniV2OusdUsdt_iUniPair = getContract(
      uniV2OusdUsdt.address,
      iUniPairJson.abi
    )

    uniV2OusdUsdc_iErc20 = getContract(uniV2OusdUsdc.address, iErc20Json.abi)
    uniV2OusdUsdc_iUniPair = getContract(
      uniV2OusdUsdc.address,
      iUniPairJson.abi
    )

    uniV2OusdDai_iErc20 = getContract(uniV2OusdDai.address, iErc20Json.abi)
    uniV2OusdDai_iUniPair = getContract(uniV2OusdDai.address, iUniPairJson.abi)
  }

  const fetchExchangeRates = async () => {
    const coins = {
      dai: dai,
      usdt: usdt,
      usdc: usdc,
    }
    const ousdExchangeRates = {
      ...ContractStore.currentState.ousdExchangeRates,
    }
    const userActive = AccountStore.currentState.active === 'active'
    // do not fetch anything if the user is not active
    if (!userActive) {
      return
    }

    for (const name in coins) {
      const coin = coins[name]
      try {
        const priceBNMint = await vault.priceUSDMint(coin.address)
        const priceBNRedeem = await vault.priceUSDRedeem(coin.address)
        // Oracle returns with 18 decimal places
        // Also, convert that to USD/<coin> format
        const priceMint = Number(priceBNMint.toString()) / 1000000000000000000
        const priceRedeem =
          Number(priceBNRedeem.toString()) / 1000000000000000000
        ousdExchangeRates[name] = {
          mint: priceMint,
          redeem: priceRedeem,
        }
      } catch (err) {
        console.error('Failed to fetch exchange rate', name, err)
      }
    }

    ContractStore.update((store) => {
      store.ousdExchangeRates = { ...ousdExchangeRates }
    })
  }

  const fetchOgnStats = async () => {
    try {
      const response = await fetch(
        `${process.env.COINGECKO_API}/coins/origin-protocol`
      )
      if (response.ok) {
        const json = await response.json()
        const price = json.market_data.current_price.usd
        const circulating_supply = json.market_data.circulating_supply
        const market_cap = json.market_data.market_cap.usd

        CoinStore.update((s) => {
          s.ogn = {
            price,
            circulating_supply,
            market_cap,
          }
        })
      }
    } catch (err) {
      console.error('Failed to fetch OGN token statistics', err)
    }
  }

  const fetchCreditsPerToken = async () => {
    try {
      const response = await fetch(process.env.CREDITS_ANALYTICS_ENDPOINT)
      if (response.ok) {
        const json = await response.json()
        YieldStore.update((s) => {
          s.currentCreditsPerToken = parseFloat(json.current_credits_per_token)
          s.nextCreditsPerToken = parseFloat(json.next_credits_per_token)
        })
      }
    } catch (err) {
      console.error('Failed to fetch credits per token', err)
    }
  }

  const fetchCreditsBalance = async () => {
    try {
      if (!walletConnected) {
        return
      }
      const credits = await ousd.creditsBalanceOf(account)
      const wousdValue = await wousd.maxWithdraw(account)
      const creditsWrapped = wousdValue.mul(credits[1])
      AccountStore.update((s) => {
        s.creditsBalanceOf = ethers.utils.formatUnits(credits[0], 18)
        s.creditsWrapped = ethers.utils.formatUnits(creditsWrapped, 36)
      })
    } catch (err) {
      console.error('Failed to fetch credits balance', err)
    }
  }

  const callWithDelay = () => {
    setTimeout(async () => {
      Promise.all([
        fetchExchangeRates(),
        fetchCreditsPerToken(),
        fetchCreditsBalance(),
        fetchOgnStats(),
      ])
    }, 2)
  }

  callWithDelay()

  const [curveRegistryExchange, curveOUSDMetaPool, curveUnderlyingCoins] =
    await setupCurve(curveAddressProvider, getContract, chainId)

  if (ContractStore.currentState.fetchId > fetchId) {
    console.log('Contracts already setup with newer fetchId. Exiting...')
    return
  }

  if (window.fetchInterval) {
    clearInterval(fetchInterval)
  }

  if (walletConnected) {
    // execute in parallel and repeat in an interval
    window.fetchInterval = setInterval(() => {
      callWithDelay()
    }, 20000)
  }

  const contractsToExport = {
    usdt,
    dai,
    tusd,
    usdc,
    ousd,
    vault,
    ogn,
    wousd,
    uniV2OusdUsdt,
    uniV2OusdUsdt_iErc20,
    uniV2OusdUsdt_iUniPair,
    uniV2OusdUsdc,
    uniV2OusdUsdc_iErc20,
    uniV2OusdUsdc_iUniPair,
    uniV2OusdDai,
    uniV2OusdDai_iErc20,
    uniV2OusdDai_iUniPair,
    uniV3OusdUsdt,
    uniV3DaiUsdt,
    uniV3UsdcUsdt,
    uniV3SwapRouter,
    uniV3SwapQuoter,
    uniV2Router,
    sushiRouter,
    uniV3NonfungiblePositionManager,
    liquidityOusdUsdt,
    liquidityOusdUsdc,
    liquidityOusdDai,
    ognStaking,
    ognStakingView,
    compensation,
    flipper,
    chainlinkEthAggregator,
    chainlinkFastGasAggregator,
    curveAddressProvider,
    curveRegistryExchange,
    curveOUSDMetaPool,
  }

  const coinInfoList = {
    usdt: {
      contract: usdt,
      decimals: 6,
    },
    usdc: {
      contract: usdc,
      decimals: 6,
    },
    dai: {
      contract: dai,
      decimals: 18,
    },
    ousd: {
      contract: ousd,
      decimals: 18,
    },
  }

  ContractStore.update((s) => {
    s.contracts = contractsToExport
    s.coinInfoList = coinInfoList
    s.walletConnected = walletConnected
    s.chainId = chainId
    s.readOnlyProvider = jsonRpcProvider
    s.curveMetapoolUnderlyingCoins = curveUnderlyingCoins
    s.fetchId = fetchId
  })

  if (process.env.ENABLE_LIQUIDITY_MINING === 'true') {
    await setupPools(contractsToExport)
  }

  await setupStakes(contractsToExport)
  await afterSetup(contractsToExport)

  return contractsToExport
}
Example #21
Source File: LiquidityFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 4 votes vote down vote up
// Function used to remove Liquidity from any pair of tokens or token-AUT
// To work correctly, there needs to be 9 arguments:
//    `address1` - An Ethereum address of the coin to recieve (either a token or AUT)
//    `address2` - An Ethereum address of the coin to recieve (either a token or AUT)
//    `liquidity_tokens` - A float or similar number representing the value of liquidity tokens you will burn to get tokens back
//    `amount1Min` - A float or similar number representing the minimum of address1's coin to recieve
//    `amount2Min` - A float or similar number representing the minimum of address2's coin to recieve
//    `routerContract` - The router contract to carry out this trade
//    `accountAddress` - An Ethereum address of the current user's account
//    `provider` - The current provider
//    `signer` - The current signer
export async function removeLiquidity(
  address1,
  address2,
  liquidity_tokens,
  amount1min,
  amount2min,
  routerContract,
  account,
  signer,
  factory
) {
  const token1 = new Contract(address1, ERC20.abi, signer);
  const token2 = new Contract(address2, ERC20.abi, signer);

  const token1Decimals = await getDecimals(token1);
  const token2Decimals = await getDecimals(token2);

  const Getliquidity = (liquidity_tokens)=>{
    if (liquidity_tokens < 0.001){
      return ethers.BigNumber.from(liquidity_tokens*10**18);
    }
    return ethers.utils.parseUnits(String(liquidity_tokens), 18);
  }

  const liquidity = Getliquidity(liquidity_tokens);
  console.log('liquidity: ', liquidity);

  const amount1Min = ethers.utils.parseUnits(String(amount1min), token1Decimals);
  const amount2Min = ethers.utils.parseUnits(String(amount2min), token2Decimals);

  const time = Math.floor(Date.now() / 1000) + 200000;
  const deadline = ethers.BigNumber.from(time);

  const wethAddress = await routerContract.WETH();
  const pairAddress = await factory.getPair(address1, address2);
  const pair = new Contract(pairAddress, PAIR.abi, signer);

  await pair.approve(routerContract.address, liquidity);

  console.log([
    address1,
    address2,
    Number(liquidity),
    Number(amount1Min),
    Number(amount2Min),
    account,
    deadline,
  ]);

  if (address1 === wethAddress) {
    // Eth + Token
    await routerContract.removeLiquidityETH(
      address2,
      liquidity,
      amount2Min,
      amount1Min,
      account,
      deadline
    );
  } else if (address2 === wethAddress) {
    // Token + Eth
    await routerContract.removeLiquidityETH(
      address1,
      liquidity,
      amount1Min,
      amount2Min,
      account,
      deadline
    );
  } else {
    // Token + Token
    await routerContract.removeLiquidity(
      address1,
      address2,
      liquidity,
      amount1Min,
      amount2Min,
      account,
      deadline
    );
  }
}
Example #22
Source File: LiquidityFunctions.js    From Alternative-Uniswap-Interface with GNU General Public License v3.0 4 votes vote down vote up
// Function used to add Liquidity to any pair of tokens or token-AUT
// To work correctly, there needs to be 9 arguments:
//    `address1` - An Ethereum address of the coin to add from (either a token or AUT)
//    `address2` - An Ethereum address of the coin to add to (either a token or AUT)
//    `amount1` - A float or similar number representing the value of address1's coin to add
//    `amount2` - A float or similar number representing the value of address2's coin to add
//    `amount1Min` - A float or similar number representing the minimum of address1's coin to add
//    `amount2Min` - A float or similar number representing the minimum of address2's coin to add
//    `routerContract` - The router contract to carry out this trade
//    `accountAddress` - An Ethereum address of the current user's account
//    `provider` - The current provider
//    `signer` - The current signer
export async function addLiquidity(
  address1,
  address2,
  amount1,
  amount2,
  amount1min,
  amount2min,
  routerContract,
  account,
  signer
) {
  const token1 = new Contract(address1, ERC20.abi, signer);
  const token2 = new Contract(address2, ERC20.abi, signer);

  const token1Decimals = await getDecimals(token1);
  const token2Decimals = await getDecimals(token2);

  const amountIn1 = ethers.utils.parseUnits(amount1, token1Decimals);
  const amountIn2 = ethers.utils.parseUnits(amount2, token2Decimals);

  const amount1Min = ethers.utils.parseUnits(amount1min, token1Decimals);
  const amount2Min = ethers.utils.parseUnits(amount2min, token2Decimals);

  const time = Math.floor(Date.now() / 1000) + 200000;
  const deadline = ethers.BigNumber.from(time);

  await token1.approve(routerContract.address, amountIn1);
  await token2.approve(routerContract.address, amountIn2);

  const wethAddress = await routerContract.WETH();

  console.log([
    address1,
    address2,
    amountIn1,
    amountIn2,
    amount1Min,
    amount2Min,
    account,
    deadline,
  ]);

  if (address1 === wethAddress) {
    // Eth + Token
    await routerContract.addLiquidityETH(
      address2,
      amountIn2,
      amount2Min,
      amount1Min,
      account,
      deadline,
      { value: amountIn1 }
    );
  } else if (address2 === wethAddress) {
    // Token + Eth
    await routerContract.addLiquidityETH(
      address1,
      amountIn1,
      amount1Min,
      amount2Min,
      account,
      deadline,
      { value: amountIn2 }
    );
  } else {
    // Token + Token
    await routerContract.addLiquidity(
      address1,
      address2,
      amountIn1,
      amountIn2,
      amount1Min,
      amount2Min,
      account,
      deadline
    );
  }
}