From 5c0b86405c2062a979036aad03fa9631a44bf310 Mon Sep 17 00:00:00 2001 From: Victor Creed <69458664+creed-victor@users.noreply.github.com> Date: Thu, 25 Feb 2021 18:24:14 +0200 Subject: [PATCH] reworked whitelisting #414 (#421) --- .env.local | 3 +- .env.mainnet.local | 1 - .env.production | 1 - .env.testnet | 1 - src/app/containers/WalletProvider/saga.ts | 11 +-- src/app/containers/WalletProvider/slice.ts | 6 +- src/utils/blockchain/contracts.testnet.ts | 13 ++- src/utils/blockchain/contracts.ts | 14 ++- src/utils/whitelist.ts | 99 ++++++++++++++++++++++ 9 files changed, 115 insertions(+), 34 deletions(-) create mode 100644 src/utils/whitelist.ts diff --git a/.env.local b/.env.local index 33fe05597..8ecb2048c 100644 --- a/.env.local +++ b/.env.local @@ -9,8 +9,7 @@ REACT_APP_TEST_FIRST_BLOCK=0 REACT_APP_PORTIS_ID=469a25c8-1101-4c57-823d-c47cb328f788 -REACT_APP_WHITELIST=false -REACT_APP_WHITELIST_TOKEN=0xC5452Dbb2E3956C1161cB9C2d6DB53C2b60E7805 +REACT_APP_WHITELIST=true REACT_APP_YBUG_ID= diff --git a/.env.mainnet.local b/.env.mainnet.local index 3bcb611ec..6bfd57f08 100644 --- a/.env.mainnet.local +++ b/.env.mainnet.local @@ -7,7 +7,6 @@ REACT_APP_SENTRY_DSN= REACT_APP_PORTIS_ID=469a25c8-1101-4c57-823d-c47cb328f788 REACT_APP_WHITELIST=false -REACT_APP_WHITELIST_TOKEN=0x576aE218aeCfD4CbD2DBe07250b47e26060932B1 REACT_APP_YBUG_ID= diff --git a/.env.production b/.env.production index 3076467ca..aa5058c53 100644 --- a/.env.production +++ b/.env.production @@ -6,7 +6,6 @@ REACT_APP_SENTRY_DSN=https://2981633dd7f04f0d9fb3facf8c1332b8@o459269.ingest.sen REACT_APP_PORTIS_ID=469a25c8-1101-4c57-823d-c47cb328f788 REACT_APP_WHITELIST=true -REACT_APP_WHITELIST_TOKEN=0x857a62c9c0b6f1211e04275a1f0c5f26fce2021f REACT_APP_YBUG_ID=3f1jrxvzrhkn1b975t8b diff --git a/.env.testnet b/.env.testnet index a72379dd2..2b2a736cc 100644 --- a/.env.testnet +++ b/.env.testnet @@ -9,6 +9,5 @@ REACT_APP_YBUG_ID=3f1jrxvzrhkn1b975t8b REACT_APP_MAILCHIMP=https://gmail.us17.list-manage.com/subscribe/post?u=e66850f0b51ebbdbe1f2c3e36&id=ef5d452839 REACT_APP_WHITELIST=false -REACT_APP_WHITELIST_TOKEN=0xC5452Dbb2E3956C1161cB9C2d6DB53C2b60E7805 REACT_APP_DISABLE_NEW_TRADES=false diff --git a/src/app/containers/WalletProvider/saga.ts b/src/app/containers/WalletProvider/saga.ts index 7c7612ef2..e61c4f732 100644 --- a/src/app/containers/WalletProvider/saga.ts +++ b/src/app/containers/WalletProvider/saga.ts @@ -10,12 +10,12 @@ import { import { PayloadAction } from '@reduxjs/toolkit'; import { TransactionReceipt } from 'web3-core'; import { Sovryn } from 'utils/sovryn'; -import { contractReader } from 'utils/sovryn/contract-reader'; import { selectWalletProvider } from './selectors'; import { actions } from './slice'; import { selectTransactionStack } from '../../../store/global/transactions-store/selectors'; import { actions as txActions } from '../../../store/global/transactions-store/slice'; import { TxStatus } from '../../../store/global/transactions-store/types'; +import { whitelist } from '../../../utils/whitelist'; function createBlockChannels({ web3 }) { return eventChannel(emit => { @@ -167,13 +167,8 @@ function* accountChangedSaga({ payload }: PayloadAction) { function* whitelistCheckSaga() { const state = yield select(selectWalletProvider); try { - const result = yield call( - [contractReader, contractReader.call], - 'whitelistToken' as any, - 'balanceOf', - [state.address], - ); - yield put(actions.whitelistChecked(result > 0)); + const result = yield call([whitelist, whitelist.test], state.address); + yield put(actions.whitelistChecked(result)); } catch (e) { yield put(actions.whitelistChecked(false)); } diff --git a/src/app/containers/WalletProvider/slice.ts b/src/app/containers/WalletProvider/slice.ts index a1653bfcb..26abb4dcf 100644 --- a/src/app/containers/WalletProvider/slice.ts +++ b/src/app/containers/WalletProvider/slice.ts @@ -1,7 +1,7 @@ import { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from 'utils/@reduxjs/toolkit'; +import { currentChainId } from 'utils/classifiers'; import { CachedAssetRate, ContainerState } from './types'; -import { currentChainId } from '../../../utils/classifiers'; // The initial state of the WalletConnector container export const initialState: ContainerState = { @@ -16,9 +16,7 @@ export const initialState: ContainerState = { transactions: {}, transactionStack: [], whitelist: { - enabled: - !!process.env.REACT_APP_WHITELIST_TOKEN && - process.env.REACT_APP_WHITELIST === 'true', + enabled: process.env.REACT_APP_WHITELIST === 'true', loading: false, loaded: false, whitelisted: false, diff --git a/src/utils/blockchain/contracts.testnet.ts b/src/utils/blockchain/contracts.testnet.ts index 2536d59b6..db5081116 100644 --- a/src/utils/blockchain/contracts.testnet.ts +++ b/src/utils/blockchain/contracts.testnet.ts @@ -142,12 +142,9 @@ export const contracts = { abi: CSOVTokenAbi, blockNumber: 1218833, }, - ...(process.env.REACT_APP_WHITELIST_TOKEN && - process.env.REACT_APP_WHITELIST === 'true' && { - whitelistToken: { - address: process.env.REACT_APP_WHITELIST_TOKEN, - abi: tokenAbi, - blockNumber: 1218844, - }, - }), + SOV_token: { + address: '0x6a9A07972D07e58F0daf5122d11E069288A375fb', + abi: tokenAbi, + blockNumber: 1606431, + }, }; diff --git a/src/utils/blockchain/contracts.ts b/src/utils/blockchain/contracts.ts index 7835d5d14..7215b681b 100644 --- a/src/utils/blockchain/contracts.ts +++ b/src/utils/blockchain/contracts.ts @@ -142,13 +142,9 @@ export const contracts = { abi: CSOVTokenAbi, blockNumber: 1218833, }, - // end non-mainnet // - ...(process.env.REACT_APP_WHITELIST_TOKEN && - process.env.REACT_APP_WHITELIST === 'true' && { - whitelistToken: { - address: process.env.REACT_APP_WHITELIST_TOKEN, - abi: tokenAbi, - blockNumber: 1218844, - }, - }), + SOV_token: { + address: '0xEFc78fc7d48b64958315949279Ba181c2114ABBd', + abi: tokenAbi, + blockNumber: 3100260, + }, }; diff --git a/src/utils/whitelist.ts b/src/utils/whitelist.ts new file mode 100644 index 000000000..2eabc0732 --- /dev/null +++ b/src/utils/whitelist.ts @@ -0,0 +1,99 @@ +import { currentChainId, backendUrl, ethGenesisAddress } from './classifiers'; +import { contractReader } from './sovryn/contract-reader'; + +const sovLimit = 100; + +class Whitelist { + public async test(address: string) { + try { + return await this.getApi(address); + } catch (e) { + return await this.getContracts(address); + } + } + + // Check if user is whitelisted using backend server + public async getApi(address: string) { + const controller = new AbortController(); + // abort request if it's not resolved in 30 seconds and start checking in smart-contract from frontend side. + const timeoutId = setTimeout(() => controller.abort(), 30e3); + return fetch(`${backendUrl[currentChainId]}/whitelist/${address}`, { + method: 'GET', + headers: { + accept: 'application/json', + }, + signal: controller.signal, + }) + .then(response => { + clearTimeout(timeoutId); + return response.json(); + }) + .then(({ whitelisted }) => whitelisted); + } + + // Check if user is whitelisted using smart-contracts + public async getContracts(address: string) { + address = address.toLowerCase(); + + const sov = await contractReader + .call('SOV_token', 'balanceOf', [address]) + .then(e => Number(e) / 1e18); + if (sov >= sovLimit) return true; + + const csov1 = await contractReader + .call('CSOV_token', 'balanceOf', [address]) + .then(e => Number(e) / 1e18); + if (csov1 >= sovLimit) return true; + + const csov2 = await contractReader + .call('CSOV2_token', 'balanceOf', [address]) + .then(e => Number(e) / 1e18); + if (csov2 >= sovLimit) return true; + + const staked = await contractReader + .call('staking', 'balanceOf', [address]) + .then(e => Number(e) / 1e18); + if (staked >= sovLimit) return true; + + const vesting1 = await contractReader.call( + 'vestingRegistry', + 'getVesting', + [address], + ); + if (vesting1 !== ethGenesisAddress) { + const staked = await contractReader + .call('staking', 'balanceOf', [vesting1]) + .then(e => Number(e) / 1e18); + if (staked >= sovLimit) return true; + } + + const vesting2 = await contractReader.call( + 'vestingRegistry', + 'getTeamVesting', + [address], + ); + if (vesting2 !== ethGenesisAddress) { + const staked = await contractReader + .call('staking', 'balanceOf', [vesting2]) + .then(e => Number(e) / 1e18); + if (staked >= sovLimit) return true; + } + + // todo enable it after new vesting registry is available + // const vesting3 = await contractReader.call( + // 'vestingRegistry2', + // 'getTeamVesting', + // [address], + // ); + // if (vesting3 !== ethGenesisAddress) { + // const staked = await contractReader + // .call('staking', 'balanceOf', [vesting3]) + // .then(e => Number(e) / 1e18); + // if (staked >= sovLimit) return true; + // } + + return false; + } +} + +export const whitelist = new Whitelist();