Compare commits

...

22 Commits

Author SHA1 Message Date
9e1a3c16d2 Merge pull request 'proposal 44' (#29) from ButterflyEffect/classic-ui:development into master
Reviewed-on: #29
2024-01-02 23:13:15 +01:00
d0cee4aa9a allow wallet withdrawal if no relayers 2023-12-25 13:16:32 +00:00
820a651615 change quorum (proposal 41) 2023-12-19 17:39:47 +00:00
d9d32f54a5 add fallback avax rpc 2023-12-19 17:15:46 +00:00
5b643d2848 add fallback goerli rpc 2023-12-19 12:19:53 +00:00
e5bf96f896 replace censored llamarpc 2023-12-19 12:18:15 +00:00
1494315784 force withdrawal via relayer 2023-12-04 15:59:17 +00:00
91889af448 update cache 2023-12-04 15:09:44 +00:00
558b6fcd0c fix update script 2023-12-04 15:09:30 +00:00
b4e23e96b4 Update self-hosted tornado packages 2023-09-18 23:16:52 -07:00
023c4634c3 Update tornado-oracles dependency to fix BSC gas price underestimate problem 2023-08-30 08:33:06 -07:00
e8a7fec326 Allow only new relayer software version for mainnet: 4.1.5 and higher 2023-08-30 03:33:44 -07:00
500d2bd0a4 Fix proof calculation for self-withdrawal: specify relayer only when recalculating proof for relayer 2023-08-30 03:32:45 -07:00
334412c803 Fix gas limit estimation for metamask & bump gas limit for self-withdrawal without relayer to 20% 2023-08-30 03:28:05 -07:00
6137e1328a Calculate gas for deposit & withdrawal transactions via fee oracle instead of web3 naive methods 2023-08-28 13:19:01 -07:00
879c8549e6 Update tornado-oracles package to fix gas price issues for sidechains & specify explicit node version in .nvmrc 2023-08-28 04:19:45 -07:00
d10ea812db Fix saving bloom to IDB for sidechains & clarify logs for encrypted notes account loading 2023-08-28 02:54:44 -07:00
9210330208 Change gas & fees calculations:
- Use @tornado/tornado-oracles lib to calculate withdrawal fee via relayer
	- When calculating fee, save backwards compatibility for Ethereum Mainnet V4 relayers & old UI builds
	- Bump UI version to 1.2.0
	- Display most up-to-date information about relayer withdrawal fees on WithdrawalTotal page
2023-08-27 12:30:31 -07:00
fb0a5131f4 Update events & trees 2023-08-27 12:29:42 -07:00
d16449bcf8 Rename 'gasPrices' scope to 'fees', and use it to estimate all network withdrawal fee 2023-08-22 09:23:18 -07:00
d9ae37ebb2 Change relayer version validating to save backwards compatibility with on Ethereum Mainnet with old Tornado versions 2023-08-22 09:01:54 -07:00
7db929cc8c Make token price api faster & easier via lib @tornado/tornado-oracles 2023-08-21 10:22:17 -07:00
227 changed files with 659 additions and 759 deletions

5
.gitignore vendored

@ -88,5 +88,8 @@ sw.*
# Mac OSX
.DS_Store
# Events unarchived files
static/*/*.json
# UI build archive
dist.zip

2
.nvmrc

@ -1 +1 @@
14
v14.21.3

@ -4,7 +4,7 @@
## Building locally
- Install [Node.js](https://nodejs.org) version 14
- Install [Node.js](https://nodejs.org) version 16
- If you are using [nvm](https://github.com/creationix/nvm#installation) (recommended) running `nvm use` will automatically choose the right node version for you.
- Install [Yarn](https://yarnpkg.com/en/docs/install)
- Install dependencies: `yarn`

@ -1,181 +0,0 @@
[
{
"inputs": [
{ "internalType": "contract MultiWrapper", "name": "_multiWrapper", "type": "address" },
{ "internalType": "contract IOracle[]", "name": "existingOracles", "type": "address[]" },
{ "internalType": "enum OffchainOracle.OracleType[]", "name": "oracleTypes", "type": "uint8[]" },
{ "internalType": "contract IERC20[]", "name": "existingConnectors", "type": "address[]" },
{ "internalType": "contract IERC20", "name": "wBase", "type": "address" }
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "internalType": "contract IERC20", "name": "connector", "type": "address" }
],
"name": "ConnectorAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "internalType": "contract IERC20", "name": "connector", "type": "address" }
],
"name": "ConnectorRemoved",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "internalType": "contract MultiWrapper", "name": "multiWrapper", "type": "address" }
],
"name": "MultiWrapperUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "internalType": "contract IOracle", "name": "oracle", "type": "address" },
{
"indexed": false,
"internalType": "enum OffchainOracle.OracleType",
"name": "oracleType",
"type": "uint8"
}
],
"name": "OracleAdded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": false, "internalType": "contract IOracle", "name": "oracle", "type": "address" },
{
"indexed": false,
"internalType": "enum OffchainOracle.OracleType",
"name": "oracleType",
"type": "uint8"
}
],
"name": "OracleRemoved",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" },
{ "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" }
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [{ "internalType": "contract IERC20", "name": "connector", "type": "address" }],
"name": "addConnector",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IOracle", "name": "oracle", "type": "address" },
{ "internalType": "enum OffchainOracle.OracleType", "name": "oracleKind", "type": "uint8" }
],
"name": "addOracle",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "connectors",
"outputs": [{ "internalType": "contract IERC20[]", "name": "allConnectors", "type": "address[]" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20", "name": "srcToken", "type": "address" },
{ "internalType": "contract IERC20", "name": "dstToken", "type": "address" },
{ "internalType": "bool", "name": "useWrappers", "type": "bool" }
],
"name": "getRate",
"outputs": [{ "internalType": "uint256", "name": "weightedRate", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IERC20", "name": "srcToken", "type": "address" },
{ "internalType": "bool", "name": "useSrcWrappers", "type": "bool" }
],
"name": "getRateToEth",
"outputs": [{ "internalType": "uint256", "name": "weightedRate", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "multiWrapper",
"outputs": [{ "internalType": "contract MultiWrapper", "name": "", "type": "address" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "oracles",
"outputs": [
{ "internalType": "contract IOracle[]", "name": "allOracles", "type": "address[]" },
{ "internalType": "enum OffchainOracle.OracleType[]", "name": "oracleTypes", "type": "uint8[]" }
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "contract IERC20", "name": "connector", "type": "address" }],
"name": "removeConnector",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{ "internalType": "contract IOracle", "name": "oracle", "type": "address" },
{ "internalType": "enum OffchainOracle.OracleType", "name": "oracleKind", "type": "uint8" }
],
"name": "removeOracle",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "contract MultiWrapper", "name": "_multiWrapper", "type": "address" }],
"name": "setMultiWrapper",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]

@ -1,151 +0,0 @@
[
{
"inputs": [{ "internalType": "address", "name": "_owner", "type": "address" }],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
"name": "DecimalsUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
"name": "GasPriceUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
"name": "L1BaseFeeUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
"name": "OverheadUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{ "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" },
{ "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" }
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [{ "indexed": false, "internalType": "uint256", "name": "", "type": "uint256" }],
"name": "ScalarUpdated",
"type": "event"
},
{
"inputs": [],
"name": "decimals",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "gasPrice",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "bytes", "name": "_data", "type": "bytes" }],
"name": "getL1Fee",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "bytes", "name": "_data", "type": "bytes" }],
"name": "getL1GasUsed",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l1BaseFee",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "overhead",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "scalar",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [{ "internalType": "uint256", "name": "_decimals", "type": "uint256" }],
"name": "setDecimals",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "uint256", "name": "_gasPrice", "type": "uint256" }],
"name": "setGasPrice",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "uint256", "name": "_baseFee", "type": "uint256" }],
"name": "setL1BaseFee",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "uint256", "name": "_overhead", "type": "uint256" }],
"name": "setOverhead",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "uint256", "name": "_scalar", "type": "uint256" }],
"name": "setScalar",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]

@ -4,7 +4,10 @@
<div class="box-modal-title">{{ $t('withdrawalSettings') }}</div>
<button type="button" class="delete" @click="$parent.cancel('escape')" />
</header>
<b-tabs v-model="withdrawType" :animated="false" class="is-modal">
<b-tabs v-if="isRelayersAvailable" v-model="withdrawType" :animated="false" class="is-modal">
<RelayerTab />
</b-tabs>
<b-tabs v-else v-model="withdrawType" :animated="false" class="is-modal">
<RelayerTab />
<WalletTab />
</b-tabs>
@ -46,7 +49,11 @@ export default {
computed: {
...mapState('application', {
defaultWithdrawType: 'withdrawType'
})
}),
...mapState('relayer', ['isLoadingRelayers', 'validRelayers']),
isRelayersAvailable() {
return !this.isLoadingRelayers && this.validRelayers.length > 0;
}
},
created() {
this.withdrawType = this.defaultWithdrawType

@ -192,7 +192,7 @@ export default {
...mapState('relayer', ['isLoadingRelayers']),
...mapGetters('txHashKeeper', ['txExplorerUrl']),
...mapGetters('application', ['isNotEnoughTokens', 'selectedStatisticCurrency']),
...mapGetters('metamask', ['networkConfig', 'netId', 'isLoggedIn', 'nativeCurrency']),
...mapGetters('metamask', ['networkConfig', 'netId', 'isLoggedIn']),
notEnoughDeposits() {
if (this.depositsPast < 5) {
return true
@ -200,7 +200,7 @@ export default {
return false
},
shouldSettingsShow() {
return !this.hasErrorNote && !this.error.message
return !this.isLoading && !this.error.type && !this.hasErrorNote
},
hasErrorNote() {
const note = this.withdrawNote.split('-')[4]
@ -337,9 +337,7 @@ export default {
})
}
this.$store.dispatch('application/setAndUpdateStatistic', { currency, amount: Number(amount) })
if (currency !== this.nativeCurrency) {
this.$store.dispatch('application/setDefaultEthToReceive', { currency })
}
this.$store.dispatch('fees/calculateWithdrawalFeeViaRelayer', {})
this.$store.dispatch('loading/updateProgress', { progress: -1 })
this.depositsPast = Number(depositsPast) <= 0 ? 0 : depositsPast
this.depositTxHash = txHash

@ -18,7 +18,9 @@
</div>
<div v-if="withdrawType === 'relayer'" class="withdraw-data-item">
{{ $t('networkFee') }}
<span data-test="label_network_fee">{{ toDecimals(networkFee, 18, 6) }} {{ networkCurrency }}</span>
<span data-test="label_network_fee"
>{{ toDecimals(withdrawalNetworkFee, 18, 6) }} {{ networkCurrency }}</span
>
</div>
<div v-if="withdrawType === 'relayer'" class="withdraw-data-item">
{{ $t('relayerFee') }}
@ -69,13 +71,13 @@ export default {
},
computed: {
...mapState('application', ['selectedStatistic']),
...mapState('fees', ['withdrawalNetworkFee', 'withdrawalFeeViaRelayer']),
...mapGetters('metamask', ['networkConfig', 'nativeCurrency']),
...mapGetters('metamask', {
networkCurrency: 'currency'
}),
...mapGetters('gasPrices', ['gasPriceInGwei']),
...mapGetters('fees', ['gasPriceInGwei']),
...mapGetters('token', ['toDecimals', 'fromDecimals']),
...mapGetters('application', ['networkFee']),
...mapGetters('price', ['tokenRate']),
relayerFee() {
const { amount } = this.selectedStatistic
@ -91,7 +93,7 @@ export default {
const tornadoServiceFee = this.relayerFee
const { currency } = this.selectedStatistic
const { decimals } = this.networkConfig.tokens[currency]
const ethFee = this.networkFee
const ethFee = this.withdrawalNetworkFee
if (currency === this.nativeCurrency) {
return ethFee.add(tornadoServiceFee)
}
@ -117,17 +119,12 @@ export default {
return fromWei(this.ethToReceive)
},
total() {
const { amount, currency } = this.selectedStatistic
const { amount } = this.selectedStatistic
let total = toBN(this.fromDecimals(amount.toString()))
if (this.withdrawType === 'relayer') {
const relayerFee = this.totalRelayerFee
if (currency === this.nativeCurrency) {
total = total.sub(relayerFee)
} else {
total = total.sub(relayerFee).sub(this.ethToReceiveInToken)
}
const relayerFee = this.withdrawalFeeViaRelayer
total = total.sub(relayerFee)
}
return this.toDecimals(total, null, 6)

@ -65,7 +65,7 @@ export default {
created() {
this.checkRecoveryKey()
this.newNotify()
this.$store.dispatch('gasPrices/setDefault')
this.$store.dispatch('fees/setDefaultGasPrice')
},
mounted() {
this.$preventMultitabs()
@ -80,7 +80,7 @@ export default {
await this.selectRpc({ netId: 1, action: this.preselectRpc })
}
this.$store.dispatch('gasPrices/fetchGasPrice')
this.$store.dispatch('fees/fetchGasPrice')
this.$store.dispatch('price/fetchTokenPrice', {}, { root: true })
try {
this.$store.dispatch('application/loadAllNotesData')

@ -21,7 +21,7 @@ export async function checkExistAccount({ getters, dispatch, rootState, rootGett
const isExist = Boolean(Array.isArray(events) && Boolean(events.length))
console.log('isExist', isExist)
console.log('Is encrypted note events exist: ', isExist)
dispatch('createMutation', {
type: 'CHECK_ACCOUNT',

@ -29,9 +29,9 @@ export default {
name: 'MevblockerRPC',
url: 'https://rpc.mevblocker.io'
},
llamaRPC: {
name: 'llamarpc',
url: 'https://eth.llamarpc.com'
oneRPC: {
name: '1RPC',
url: 'https://1rpc.io/eth'
}
},
multicall: '0xeefba1e63905ef1d7acba5a8513c70307c1ce441',
@ -401,17 +401,17 @@ export default {
multicall: '0xe86e3989c74293Acc962156cd3F525c07b6a1B6e',
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
rpcUrls: {
publicRpc1: {
publicRpc: {
name: 'Avalanche RPC',
url: 'https://endpoints.omniatech.io/v1/avax/mainnet/public'
url: 'https://api.avax.network/ext/bc/C/rpc'
},
meowRPC: {
name: 'Meow RPC',
url: 'https://avax.meowrpc.com'
},
communityRPC: {
name: 'Tornado RPC',
url: 'https://avalanche-rpc.tornado.ws/ext/bc/C/rpc'
oneRPC: {
name: 'OneRPC',
url: 'https://1rpc.io/avax/c'
}
},
tokens: {
@ -459,6 +459,10 @@ export default {
chainnodes: {
name: 'Tornado RPC',
url: 'https://goerli.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
},
gatewayRPC: {
name: 'Gateway RPC',
url: 'https://rpc.goerli.eth.gateway.fm'
}
},
tokens: {

@ -1,6 +1,6 @@
{
"name": "tornadocash-classic-ui",
"version": "1.1.0",
"version": "1.2.0",
"description": "Private ethereum transactions",
"author": "Tornado Cash Team",
"scripts": {
@ -23,9 +23,10 @@
"@apollo/client": "^3.3.20",
"@metamask/onboarding": "^1.0.0",
"@nuxtjs/moment": "^1.6.0",
"@tornado/gas-price-oracle": "^0.5.3",
"@tornado/snarkjs": "0.1.20-p2",
"@tornado/websnark": "0.0.4-p1",
"@tornado/fixed-merkle-tree": "0.7",
"@tornado/snarkjs": "0.1.20",
"@tornado/tornado-oracles": "^2.1.0",
"@tornado/websnark": "0.0.4",
"@walletconnect/web3-provider": "1.7.8",
"ajv": "^6.10.2",
"arraybuffer-loader": "^1.0.8",
@ -39,7 +40,6 @@
"eth-ens-namehash": "^2.0.8",
"eth-sig-util": "^2.5.3",
"file-saver": "^2.0.5",
"fixed-merkle-tree": "^0.7.3",
"form-data": "^3.0.0",
"graphql": "^15.5.1",
"idb": "^6.0.0",

@ -262,7 +262,7 @@ export default async (ctx, inject) => {
Object.keys(tokens).forEach((token) => {
Object.keys(tokens[token].instanceAddress).forEach((amount) => {
if (nativeCurrency === token && netId === 1) {
if (nativeCurrency === token) {
stores.push({
name: `stringify_bloom_${netId}_${token}_${amount}`,
keyPath: 'hashBloom'

@ -3,7 +3,7 @@ import 'dotenv/config'
import fs from 'fs'
import BloomFilter from 'bloomfilter.js'
import { MerkleTree } from 'fixed-merkle-tree'
import { MerkleTree } from '@tornado/fixed-merkle-tree'
import { buildMimcSponge } from 'circomlibjs'
import networkConfig, { enabledChains } from '../networkConfig'

@ -17,21 +17,22 @@ function updateEncrypted(netId) {
async function updateCommon(netId) {
const { nativeCurrency, tokens } = networkConfig[`netId${netId}`]
console.log(Object.keys(tokens[nativeCurrency].instanceAddress))
for (const type of EVENTS) {
for (const [tokenName, tokenInfo] of Object.entries(tokens)) {
console.log(`${tokenInfo.symbol}: ${Object.keys(tokenInfo.instanceAddress)}`)
for (const instance of Object.keys(tokenInfo.instanceAddress)) {
console.warn('instance', instance)
for await (const type of EVENTS) {
for await (const instance of Object.keys(tokens[nativeCurrency].instanceAddress)) {
console.warn('instance', instance)
const filename = `${type.toLowerCase()}s_${netId}_${tokenName}_${instance}.json`
const filename = `${type.toLowerCase()}s_${netId}_${nativeCurrency}_${instance}.json`
const isSaved = save(`${EVENTS_PATH}${filename}`)
const isSaved = save(`${EVENTS_PATH}${filename}`)
if (isSaved) {
try {
testCommon(netId, type, filename)
} catch (err) {
console.error(err.message)
if (isSaved) {
try {
testCommon(netId, type, filename)
} catch (err) {
console.error(err.message)
}
}
}
}

@ -1,4 +1,4 @@
import { MerkleTree, PartialMerkleTree } from 'fixed-merkle-tree'
import { MerkleTree, PartialMerkleTree } from '@tornado/fixed-merkle-tree'
import { trees } from '@/constants'
import { download } from '@/store/snark'

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More