From d7fea8aca22b1f217dd9bf9b18e56276e192fbbe Mon Sep 17 00:00:00 2001 From: CAPtheorem <79423264+CAPtheorem@users.noreply.github.com> Date: Wed, 13 Apr 2022 17:58:37 -0700 Subject: [PATCH] correctly handle exit fee --- .../modals/exit/steps/DoExitStepFast.js | 65 +++++++++++-------- .../src/containers/wallet/token/Token.js | 28 ++++++-- .../gateway/src/services/networkService.js | 58 ++++++----------- .../boba/gateway/src/util/masterConfig.js | 7 +- 4 files changed, 84 insertions(+), 74 deletions(-) diff --git a/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStepFast.js b/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStepFast.js index 8d5b861241..da92cbe6b0 100644 --- a/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStepFast.js +++ b/packages/boba/gateway/src/containers/modals/exit/steps/DoExitStepFast.js @@ -117,8 +117,14 @@ function DoExitStepFast({ handleClose, token }) { setErrorString('') - if (tooSmall || tooBig) { - setErrorString('Warning: Value out of bounds') + if (tooSmall) { + setErrorString('Value too small') + setValidValue(false) + setValue(value) + return false + } + else if (tooBig) { + setErrorString('Value too big') setValidValue(false) setValue(value) return false @@ -138,9 +144,9 @@ function DoExitStepFast({ handleClose, token }) { //pay BOBA, exit BOBA - check BOBA amount feeUseBoba && token.symbol === 'BOBA' && - (Number(value) + feeBOBA) > balance) + (Number(value) + feeBOBA + exitFee) > balance) { - // insufficient BOBA to cover the BOBA amount plus gas + // insufficient BOBA to cover the BOBA amount plus gas plus exitFee setErrorString('Warning: BOBA amount + fees > balance') setValidValue(false) setValue(value) @@ -163,9 +169,9 @@ function DoExitStepFast({ handleClose, token }) { else if ( // insufficient BOBA to cover exit fees feeUseBoba && - feeBOBA > Number(feeBalanceBOBA)) + (feeBOBA + exitFee) > Number(feeBalanceBOBA)) { - setErrorString('Warning: BOBA balance too low to cover gas') + setErrorString('Warning: BOBA balance too low to cover gas/fees') setValidValue(false) setValue(value) return false @@ -282,8 +288,14 @@ function DoExitStepFast({ handleClose, token }) { setMax_Float(0.0) } else if (token.symbol === 'BOBA' && feeUseBoba) { - if(balance - safeCost > 0.0) - setMax_Float(balance - safeCost) + if(balance - (safeCost * feePriceRatio) - exitFee > 0.0) + setMax_Float(balance - (safeCost * feePriceRatio) - exitFee) + else + setMax_Float(0.0) + } + else if (token.symbol === 'BOBA' && !feeUseBoba) { + if(balance - exitFee > 0.0) + setMax_Float(balance - exitFee) else setMax_Float(0.0) } @@ -305,9 +317,9 @@ function DoExitStepFast({ handleClose, token }) { let ETHstring = '' if(feeETH && Number(feeETH) > 0) { if(feeUseBoba) { - ETHstring = `Estimated gas (approval + exit): ${Number(feeBOBA).toFixed(4)} BOBA` + ETHstring = `Estimated gas: ${Number(feeBOBA).toFixed(4)} BOBA` } else { - ETHstring = `Estimated gas (approval + exit): ${Number(feeETH).toFixed(4)} ETH` + ETHstring = `Estimated gas: ${Number(feeETH).toFixed(4)} ETH` } } @@ -320,6 +332,8 @@ function DoExitStepFast({ handleClose, token }) { allowExitall = false } + const balance = Number(logAmount(token.balance, token.decimals)) + return ( <> @@ -360,11 +374,23 @@ function DoExitStepFast({ handleClose, token }) { loading={loading} /> } + {max_Float === 0 && Loading... } + + + {parse(`Token balance: ${Number(balance).toFixed(6)} ${token.symbol}`)} +
+ {parse(`Message Relay Fee: ${exitFee} BOBA`)} +
+ {parse(ETHstring)} +
+ {parse(`Max exitable balance (balance - fees): ${Number(max_Float).toFixed(6)} ${token.symbol}`)} +
+ {validValue && token && ( {value && @@ -377,14 +403,6 @@ function DoExitStepFast({ handleClose, token }) { )} - - {parse(ETHstring)} - - - - {parse(`Exit Fee: ${exitFee} BOBA`)} - - {errorString !== '' && {errorString} @@ -398,23 +416,16 @@ function DoExitStepFast({ handleClose, token }) { )} - {(Number(LPRatio) < 0.10 && Number(value) > Number(balanceSubPending) * 0.90) && ( - - The pool's balance and balance/liquidity ratio are too low. - Please use the classic bridge. - - )} - {(Number(LPRatio) < 0.10 && Number(value) <= Number(balanceSubPending) * 0.90) && ( - The pool's balance/liquidity ratio (of {Number(LPRatio).toFixed(2)}) is low. + The pool's balance/liquidity ratio (of {Number(LPRatio).toFixed(2)}) is too low. Please use the classic bridge. )} {(Number(LPRatio) >= 0.10 && Number(value) > Number(balanceSubPending) * 0.90) && ( - The pool's balance (of {Number(balanceSubPending).toFixed(2)} including inflight bridges) is low. + The pool's balance (of {Number(balanceSubPending).toFixed(2)} including inflight bridges) is too low. Please use the classic bridge or reduce the amount. )} diff --git a/packages/boba/gateway/src/containers/wallet/token/Token.js b/packages/boba/gateway/src/containers/wallet/token/Token.js index 0356dafe3d..6784a3bf27 100644 --- a/packages/boba/gateway/src/containers/wallet/token/Token.js +++ b/packages/boba/gateway/src/containers/wallet/token/Token.js @@ -1,20 +1,25 @@ -import { Box, Typography, useTheme } from '@mui/material' -import { fetchLookUpPrice } from 'actions/networkAction' -import { isEqual } from 'lodash' -import React, { useCallback, useEffect } from 'react' +import React, { useCallback, useState, useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' + import { selectlayer1Balance, selectlayer2Balance } from 'selectors/balanceSelector' import { selectLoading } from 'selectors/loadingSelector' import { selectAccountEnabled, selectLayer } from 'selectors/setupSelector' import { selectTokens } from 'selectors/tokenSelector' + +import { fetchLookUpPrice } from 'actions/networkAction' + import * as S from './Token.styles' +import { Box, Typography, useTheme } from '@mui/material' import { tokenTableHeads } from './token.tableHeads' + import ListToken from 'components/listToken/listToken' import Button from 'components/button/Button' +import Link from 'components/icons/LinkIcon' import lightLoader from 'images/boba2/loading_light.gif' import darkLoader from 'images/boba2/loading_dark.gif' -import Link from 'components/icons/LinkIcon' + +import { isEqual } from 'lodash' import networkService from 'services/networkService' @@ -30,6 +35,8 @@ function TokenPage() { const rootBalance = useSelector(selectlayer1Balance, isEqual) const layer = useSelector(selectLayer()) + const [ debug, setDebug ] = useState(false) + const depositLoading = useSelector(selectLoading([ 'DEPOSIT/CREATE' ])) const exitLoading = useSelector(selectLoading([ 'EXIT/CREATE' ])) const balanceLoading = useSelector(selectLoading([ 'BALANCE/GET' ])) @@ -38,6 +45,15 @@ function TokenPage() { const loaderImage = (theme.palette.mode === 'light') ? lightLoader : darkLoader; + useEffect(() => { + if (!accountEnabled) return + const gasEstimateAccount = networkService.gasEstimateAccount + const wAddress = networkService.account + if (wAddress.toLowerCase() === gasEstimateAccount.toLowerCase()) { + setDebug(true) + } + }, [ accountEnabled, networkService ]) + const getLookupPrice = useCallback(() => { if (!accountEnabled) return // only run once all the tokens have been added to the tokenList @@ -69,8 +85,6 @@ function TokenPage() { console.log("GasEstimateApprove:",approval) } - const debug = false - if (!accountEnabled) { return ( diff --git a/packages/boba/gateway/src/services/networkService.js b/packages/boba/gateway/src/services/networkService.js index fafe9661d0..8f26b7bf1c 100644 --- a/packages/boba/gateway/src/services/networkService.js +++ b/packages/boba/gateway/src/services/networkService.js @@ -88,7 +88,6 @@ import { sortRawTokens } from 'util/common' import GraphQLService from "./graphQLService" import addresses_Rinkeby from "@boba/register/addresses/addressesRinkeby_0x93A96D6A5beb1F661cf052722A1424CDDA3e9418" -//import addresses_Local from "@boba/register/addresses/addressesLocal_0x93A96D6A5beb1F661cf052722A1424CDDA3e9418" import addresses_Mainnet from "@boba/register/addresses/addressesMainnet_0x8376ac6C3f73a25Dd994E0b0669ca7ee0C02F089" require('dotenv').config() @@ -117,8 +116,6 @@ if (process.env.REACT_APP_CHAIN === 'rinkeby') { } let allTokens = {} -const benchmarkAccount = '0x4161aEf7ac9F8772B83Cda1E5F054ADe308d9049' - class NetworkService { constructor() { @@ -168,6 +165,8 @@ class NetworkService { // "param _l1Gas Unused, but included for potential forward compatibility considerations" this.L2GasLimit = 1300000 //use the same as the hardcoded receive + this.gasEstimateAccount = null + // Dao this.BobaContract = null this.xBobaContract = null @@ -616,6 +615,8 @@ class NetworkService { if (networkGateway === 'mainnet' || networkGateway === 'rinkeby') { this.payloadForL1SecurityFee = nw[networkGateway].payloadForL1SecurityFee this.payloadForFastDepositBatchCost = nw[networkGateway].payloadForFastDepositBatchCost + this.gasEstimateAccount = nw[networkGateway].gasEstimateAccount + console.log('gasEstimateAccount:', this.gasEstimateAccount) } this.L1Provider = new ethers.providers.StaticJsonRpcProvider( @@ -2373,7 +2374,7 @@ class NetworkService { utils.parseEther('1.0') ) - const approvalGas_BN = await this.L2Provider.estimateGas({...tx, from: benchmarkAccount}) + const approvalGas_BN = await this.L2Provider.estimateGas({...tx, from: this.gasEstimateAccount}) approvalCost_BN = approvalGas_BN.mul(gasPrice) console.log("Approve cost in ETH:", utils.formatEther(approvalCost_BN)) } @@ -2392,7 +2393,7 @@ class NetworkService { { value: utils.parseEther('0.00001') } ) - const gas_BN = await this.L2Provider.estimateGas({...tx2, from: benchmarkAccount}) + const gas_BN = await this.L2Provider.estimateGas({...tx2, from: this.gasEstimateAccount}) console.log("Classical exit gas", gas_BN.toString()) const cost_BN = gas_BN.mul(gasPrice) @@ -2693,8 +2694,7 @@ class NetworkService { let otherField = {} if( currency === allAddresses.L1_ETH_Address || currency === allAddresses.L2_ETH_Address ) { - // console.log("Yes we have ETH") - // add value field + // add value field for ETH otherField['value'] = value_Wei_String } @@ -2720,42 +2720,24 @@ class NetworkService { async liquidityEstimate(currency) { let otherField = { - from: benchmarkAccount + from: this.gasEstimateAccount } const gasPrice_BN = await this.provider.getGasPrice() - console.log("gas price", gasPrice_BN.toString()) - let approvalCost_BN = BigNumber.from('0') let stakeCost_BN = BigNumber.from('0') try { - // first, we need the allowance of the benchmarkAccount - const BOBA = this.L2_TEST_Contract - .connect(this.provider) - .attach(this.tokenAddresses['BOBA'].L2) - - let allowance_BN = await BOBA - .allowance( - benchmarkAccount, - allAddresses.L2LPAddress - ) - - console.log("benchmarkAllowance", allowance_BN.toString() ) - - if( currency === allAddresses.L2_ETH_Address ) { - otherField['value'] = allowance_BN.toString() - } - - // second, we need the approval cost if non-ETH + // First, we need the approval cost + // not relevant to ETH if( currency !== allAddresses.L2_ETH_Address ) { - const tx1 = await BOBA + const tx1 = await this.BobaContract .populateTransaction .approve( allAddresses.L2LPAddress, - allowance_BN.toString(), + utils.parseEther('1.0'), otherField ) @@ -2764,12 +2746,13 @@ class NetworkService { console.log("Approve cost in ETH:", utils.formatEther(approvalCost_BN)) } - // third, we need the addLiquidity cost + // Second, we need the addLiquidity cost + // all ERC20s will be the same, so use the BOBA contract const tx2 = await this.L2LPContract .connect(this.provider) .populateTransaction .addLiquidity( - allowance_BN.toString(), + utils.parseEther('1.0'), this.tokenAddresses['BOBA'].L2, otherField ) @@ -2778,7 +2761,7 @@ class NetworkService { console.log("addLiquidity cost in ETH:", utils.formatEther(stakeCost_BN)) const safety_margin_BN = BigNumber.from('1000000000000') - console.log("Stake safety margin:", utils.formatEther(safety_margin_BN)) + console.log("Safety margin:", utils.formatEther(safety_margin_BN)) return approvalCost_BN.add(stakeCost_BN).add(safety_margin_BN) @@ -3132,7 +3115,7 @@ class NetworkService { utils.parseEther('1.0') ) - const approvalGas_BN = await this.L2Provider.estimateGas({...tx, from: benchmarkAccount}) + const approvalGas_BN = await this.L2Provider.estimateGas({...tx, from: this.gasEstimateAccount}) approvalCost_BN = approvalGas_BN.mul(gasPrice) console.log("Approve cost in ETH:", utils.formatEther(approvalCost_BN)) } @@ -3147,7 +3130,7 @@ class NetworkService { currencyAddress === allAddresses.L2_ETH_Address ? { value : '1'} : {} ) - const depositGas_BN = await this.L2Provider.estimateGas({...tx2, from: benchmarkAccount}) + const depositGas_BN = await this.L2Provider.estimateGas({...tx2, from: this.gasEstimateAccount}) let l1SecurityFee = BigNumber.from('0') if (this.networkGateway === 'mainnet') { @@ -4051,10 +4034,9 @@ class NetworkService { // used to generate gas estimates for contracts that cannot set amount === 0 // to avoid need to approve amount - const benchmarkAccount = '0x4161aEf7ac9F8772B83Cda1E5F054ADe308d9049' let otherField = { - from: benchmarkAccount + from: this.gasEstimateAccount } const gasPrice_BN = await this.provider.getGasPrice() @@ -4069,7 +4051,7 @@ class NetworkService { let allowance_BN = await this.BobaContract .connect(this.provider) .allowance( - benchmarkAccount, + this.gasEstimateAccount, allAddresses.BobaFixedSavings ) console.log("benchmarkAllowance_BN",allowance_BN.toString()) diff --git a/packages/boba/gateway/src/util/masterConfig.js b/packages/boba/gateway/src/util/masterConfig.js index 6ad5d12bf8..74e54080f7 100644 --- a/packages/boba/gateway/src/util/masterConfig.js +++ b/packages/boba/gateway/src/util/masterConfig.js @@ -53,7 +53,9 @@ if (process.env.REACT_APP_CHAIN === 'rinkeby') { value: '0x038d7ea4c68000', data: '0xa44c80e3000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020000000000000000000000006a6676813d3d4317442cf84667425c13553f4a760000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038d7ea4c68000' - } + }, + gasEstimateAccount: `0x1FE67D4a3c73abAa0703a70bAbf0fB81aC572bd2` + } } } else if (process.env.REACT_APP_CHAIN === 'mainnet') { @@ -92,7 +94,8 @@ if (process.env.REACT_APP_CHAIN === 'rinkeby') { value: '0x038d7ea4c68000', data: '0xa44c80e30000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000042bbfa2e77757c645eeaad1655e0911a7553efbc0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038d7ea4c68000' - } + }, + gasEstimateAccount: `0x1FE67D4a3c73abAa0703a70bAbf0fB81aC572bd2` } } } else if (process.env.REACT_APP_CHAIN === 'local') {