Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
a4010df835 | |||
e16995581b | |||
1ded1f51d1 | |||
e110bb29be | |||
69841d8f56 | |||
add30d1939 | |||
57d3ba5ac5 | |||
2fcf0cb443 | |||
1221aad973 | |||
bf3d37dad6 | |||
5de0210127 | |||
63e770cf12 | |||
340d32b2ad | |||
aaa4205145 | |||
ca946343d2 | |||
780ccdc44c | |||
5ebf55204d | |||
2cf3b33b62 | |||
b288ce9356 |
@ -317,8 +317,8 @@
|
|||||||
mask-image: url('../img/icons/ethereum.svg');
|
mask-image: url('../img/icons/ethereum.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
&-ethereum-goerli {
|
&-ethereum-sepolia {
|
||||||
mask-image: url('../img/icons/goerli.svg');
|
mask-image: url('../img/icons/ethereum.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
&-optimism {
|
&-optimism {
|
||||||
|
@ -34,6 +34,14 @@
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
icon-right="stats"
|
icon-right="stats"
|
||||||
></b-button>
|
></b-button>
|
||||||
|
<b-button
|
||||||
|
tag="a"
|
||||||
|
type="is-icon"
|
||||||
|
href="https://t.me/tornadoofficial"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
icon-right="telegram"
|
||||||
|
></b-button>
|
||||||
<b-button
|
<b-button
|
||||||
tag="a"
|
tag="a"
|
||||||
type="is-icon"
|
type="is-icon"
|
||||||
@ -101,7 +109,7 @@ export default {
|
|||||||
...mapGetters('metamask', ['networkConfig', 'netId']),
|
...mapGetters('metamask', ['networkConfig', 'netId']),
|
||||||
...mapGetters('txHashKeeper', ['addressExplorerUrl']),
|
...mapGetters('txHashKeeper', ['addressExplorerUrl']),
|
||||||
duneLink() {
|
duneLink() {
|
||||||
const mainnetNetworks = [1, 5]
|
const mainnetNetworks = [1]
|
||||||
|
|
||||||
if (mainnetNetworks.includes(Number(this.netId))) {
|
if (mainnetNetworks.includes(Number(this.netId))) {
|
||||||
return 'https://dune.xyz/poma/tornado-cash_1'
|
return 'https://dune.xyz/poma/tornado-cash_1'
|
||||||
|
@ -17,8 +17,6 @@ export default {
|
|||||||
switch (this.netId) {
|
switch (this.netId) {
|
||||||
case 1:
|
case 1:
|
||||||
return 'Ethereum'
|
return 'Ethereum'
|
||||||
case 5:
|
|
||||||
return 'Goerli'
|
|
||||||
case 56:
|
case 56:
|
||||||
return 'BSC Mainnet'
|
return 'BSC Mainnet'
|
||||||
case 137:
|
case 137:
|
||||||
@ -27,6 +25,8 @@ export default {
|
|||||||
return 'Arbitrum'
|
return 'Arbitrum'
|
||||||
case 43114:
|
case 43114:
|
||||||
return 'Avalanche'
|
return 'Avalanche'
|
||||||
|
case 11155111:
|
||||||
|
return 'Sepolia'
|
||||||
default:
|
default:
|
||||||
return this.networkName
|
return this.networkName
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ export default {
|
|||||||
}),
|
}),
|
||||||
...mapState('relayer', ['isLoadingRelayers', 'validRelayers']),
|
...mapState('relayer', ['isLoadingRelayers', 'validRelayers']),
|
||||||
isRelayersAvailable() {
|
isRelayersAvailable() {
|
||||||
return !this.isLoadingRelayers && this.validRelayers.length > 0;
|
return !this.isLoadingRelayers && this.validRelayers.length > 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -43,6 +43,8 @@ export const ACTION_GAS = Object.freeze({
|
|||||||
[ACTION.ARB_WITHDRAW]: 1900000
|
[ACTION.ARB_WITHDRAW]: 1900000
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const WITHDRAW_GAS_LIMIT = 600_000
|
||||||
|
|
||||||
export const GAS_PRICES = ['low', 'standard', 'fast']
|
export const GAS_PRICES = ['low', 'standard', 'fast']
|
||||||
|
|
||||||
export const addressType = { type: 'string', pattern: '^0x[a-fA-F0-9]{40}$' }
|
export const addressType = { type: 'string', pattern: '^0x[a-fA-F0-9]{40}$' }
|
||||||
@ -52,9 +54,6 @@ export const cachedEventsLength = {
|
|||||||
mainnet: {
|
mainnet: {
|
||||||
ENCRYPTED_NOTES: 16898
|
ENCRYPTED_NOTES: 16898
|
||||||
},
|
},
|
||||||
goerli: {
|
|
||||||
ENCRYPTED_NOTES: 1662
|
|
||||||
},
|
|
||||||
bsc: {
|
bsc: {
|
||||||
ENCRYPTED_NOTES: 11333
|
ENCRYPTED_NOTES: 11333
|
||||||
}
|
}
|
||||||
|
183
networkConfig.js
183
networkConfig.js
@ -1,5 +1,5 @@
|
|||||||
export const blockSyncInterval = 10000
|
export const blockSyncInterval = 10000
|
||||||
export const enabledChains = ['1', '5', '10', '56', '100', '137', '42161', '43114']
|
export const enabledChains = ['1', '10', '56', '100', '137', '42161', '43114', '11155111']
|
||||||
export default {
|
export default {
|
||||||
netId1: {
|
netId1: {
|
||||||
rpcCallRetryAttempt: 15,
|
rpcCallRetryAttempt: 15,
|
||||||
@ -21,8 +21,12 @@ export default {
|
|||||||
networkName: 'Ethereum Mainnet',
|
networkName: 'Ethereum Mainnet',
|
||||||
deployedBlock: 9116966,
|
deployedBlock: 9116966,
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
chainnodes: {
|
tornadoRPC: {
|
||||||
name: 'Tornado RPC',
|
name: 'Tornado RPC',
|
||||||
|
url: 'https://tornadocash-rpc.com/mainnet'
|
||||||
|
},
|
||||||
|
chainnodes: {
|
||||||
|
name: 'Chainnodes RPC',
|
||||||
url: 'https://mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
url: 'https://mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
||||||
},
|
},
|
||||||
mevblockerRPC: {
|
mevblockerRPC: {
|
||||||
@ -38,6 +42,7 @@ export default {
|
|||||||
routerContract: '0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b',
|
routerContract: '0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b',
|
||||||
registryContract: '0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2',
|
registryContract: '0x58E8dCC13BE9780fC42E8723D8EaD4CF46943dF2',
|
||||||
echoContractAccount: '0x9B27DD5Bb15d42DC224FCD0B7caEbBe16161Df42',
|
echoContractAccount: '0x9B27DD5Bb15d42DC224FCD0B7caEbBe16161Df42',
|
||||||
|
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||||
aggregatorContract: '0xE8F47A78A6D52D317D0D2FFFac56739fE14D1b49',
|
aggregatorContract: '0xE8F47A78A6D52D317D0D2FFFac56739fE14D1b49',
|
||||||
tokens: {
|
tokens: {
|
||||||
eth: {
|
eth: {
|
||||||
@ -58,9 +63,10 @@ export default {
|
|||||||
'100000': '0x23773E65ed146A459791799d01336DB287f25334'
|
'100000': '0x23773E65ed146A459791799d01336DB287f25334'
|
||||||
},
|
},
|
||||||
tokenAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
|
tokenAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
|
||||||
|
tokenGasLimit: 70_000,
|
||||||
symbol: 'DAI',
|
symbol: 'DAI',
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
gasLimit: '55000'
|
gasLimit: 700_000
|
||||||
},
|
},
|
||||||
cdai: {
|
cdai: {
|
||||||
instanceAddress: {
|
instanceAddress: {
|
||||||
@ -70,19 +76,23 @@ export default {
|
|||||||
'5000000': '0xD21be7248e0197Ee08E0c20D4a96DEBdaC3D20Af'
|
'5000000': '0xD21be7248e0197Ee08E0c20D4a96DEBdaC3D20Af'
|
||||||
},
|
},
|
||||||
tokenAddress: '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643',
|
tokenAddress: '0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643',
|
||||||
|
tokenGasLimit: 200_000,
|
||||||
symbol: 'cDAI',
|
symbol: 'cDAI',
|
||||||
decimals: 8,
|
decimals: 8,
|
||||||
gasLimit: '425000'
|
gasLimit: 700_000
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Instances frozen due to sanctions
|
||||||
usdc: {
|
usdc: {
|
||||||
instanceAddress: {
|
instanceAddress: {
|
||||||
'100': '0xd96f2B1c14Db8458374d9Aca76E26c3D18364307',
|
'100': '0xd96f2B1c14Db8458374d9Aca76E26c3D18364307',
|
||||||
'1000': '0x4736dCf1b7A3d580672CcE6E7c65cd5cc9cFBa9D'
|
'1000': '0x4736dCf1b7A3d580672CcE6E7c65cd5cc9cFBa9D'
|
||||||
},
|
},
|
||||||
tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
tokenAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
||||||
|
tokenGasLimit: 70_000,
|
||||||
symbol: 'USDC',
|
symbol: 'USDC',
|
||||||
decimals: 6,
|
decimals: 6,
|
||||||
gasLimit: '80000'
|
gasLimit: 700_000,
|
||||||
},
|
},
|
||||||
usdt: {
|
usdt: {
|
||||||
instanceAddress: {
|
instanceAddress: {
|
||||||
@ -90,10 +100,12 @@ export default {
|
|||||||
'1000': '0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f'
|
'1000': '0x0836222F2B2B24A3F36f98668Ed8F0B38D1a872f'
|
||||||
},
|
},
|
||||||
tokenAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
tokenAddress: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
||||||
|
tokenGasLimit: 70_000,
|
||||||
symbol: 'USDT',
|
symbol: 'USDT',
|
||||||
decimals: 6,
|
decimals: 6,
|
||||||
gasLimit: '100000'
|
gasLimit: 700_000,
|
||||||
},
|
},
|
||||||
|
**/
|
||||||
wbtc: {
|
wbtc: {
|
||||||
instanceAddress: {
|
instanceAddress: {
|
||||||
'0.1': '0x178169B423a011fff22B9e3F3abeA13414dDD0F1',
|
'0.1': '0x178169B423a011fff22B9e3F3abeA13414dDD0F1',
|
||||||
@ -101,9 +113,10 @@ export default {
|
|||||||
'10': '0xbB93e510BbCD0B7beb5A853875f9eC60275CF498'
|
'10': '0xbB93e510BbCD0B7beb5A853875f9eC60275CF498'
|
||||||
},
|
},
|
||||||
tokenAddress: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599',
|
tokenAddress: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599',
|
||||||
|
tokenGasLimit: 70_000,
|
||||||
symbol: 'WBTC',
|
symbol: 'WBTC',
|
||||||
decimals: 8,
|
decimals: 8,
|
||||||
gasLimit: '85000'
|
gasLimit: 700_000
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ensSubdomainKey: 'mainnet-tornado',
|
ensSubdomainKey: 'mainnet-tornado',
|
||||||
@ -140,9 +153,14 @@ export default {
|
|||||||
deployedBlock: 8158799,
|
deployedBlock: 8158799,
|
||||||
multicall: '0x41263cba59eb80dc200f3e2544eda4ed6a90e76c',
|
multicall: '0x41263cba59eb80dc200f3e2544eda4ed6a90e76c',
|
||||||
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||||
|
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
chainnodes: {
|
tornadoRPC: {
|
||||||
name: 'Tornado RPC',
|
name: 'Tornado RPC',
|
||||||
|
url: 'https://tornadocash-rpc.com/bsc'
|
||||||
|
},
|
||||||
|
chainnodes: {
|
||||||
|
name: 'Chainnodes RPC',
|
||||||
url: 'https://bsc-mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
url: 'https://bsc-mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
||||||
},
|
},
|
||||||
oneRPC: {
|
oneRPC: {
|
||||||
@ -191,9 +209,12 @@ export default {
|
|||||||
deployedBlock: 16257962,
|
deployedBlock: 16257962,
|
||||||
multicall: '0x11ce4B23bD875D7F5C6a31084f55fDe1e9A87507',
|
multicall: '0x11ce4B23bD875D7F5C6a31084f55fDe1e9A87507',
|
||||||
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||||
|
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||||
|
gasPriceOracleContract: '0xF81A8D8D3581985D3969fe53bFA67074aDFa8F3C',
|
||||||
|
gasStationApi: 'https://polygon-oracle.tornadocash-rpc.com',
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
chainnodes: {
|
chainnodes: {
|
||||||
name: 'Tornado RPC',
|
name: 'Chainnodes RPC',
|
||||||
url: 'https://polygon-mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
url: 'https://polygon-mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
||||||
},
|
},
|
||||||
oneRpc: {
|
oneRpc: {
|
||||||
@ -242,10 +263,15 @@ export default {
|
|||||||
deployedBlock: 2243689,
|
deployedBlock: 2243689,
|
||||||
multicall: '0x35A6Cdb2C9AD4a45112df4a04147EB07dFA01aB7',
|
multicall: '0x35A6Cdb2C9AD4a45112df4a04147EB07dFA01aB7',
|
||||||
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||||
ovmGasPriceOracleContract: '0x420000000000000000000000000000000000000F',
|
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||||
|
optimismL1FeeOracleAddress: '0x420000000000000000000000000000000000000F',
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
chainnodes: {
|
tornadoRPC: {
|
||||||
name: 'Tornado RPC',
|
name: 'Tornado RPC',
|
||||||
|
url: 'https://tornadocash-rpc.com/op'
|
||||||
|
},
|
||||||
|
chainnodes: {
|
||||||
|
name: 'Chainnodes RPC',
|
||||||
url: 'https://optimism-mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
url: 'https://optimism-mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
||||||
},
|
},
|
||||||
oneRpc: {
|
oneRpc: {
|
||||||
@ -294,9 +320,14 @@ export default {
|
|||||||
deployedBlock: 3430648,
|
deployedBlock: 3430648,
|
||||||
multicall: '0x842eC2c7D803033Edf55E478F461FC547Bc54EB2',
|
multicall: '0x842eC2c7D803033Edf55E478F461FC547Bc54EB2',
|
||||||
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||||
|
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
chainnodes: {
|
tornadoRPC: {
|
||||||
name: 'Tornado RPC',
|
name: 'Tornado RPC',
|
||||||
|
url: 'https://tornadocash-rpc.com/arbitrum'
|
||||||
|
},
|
||||||
|
chainnodes: {
|
||||||
|
name: 'Chainnodes RPC',
|
||||||
url: 'https://arbitrum-one.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
url: 'https://arbitrum-one.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
||||||
},
|
},
|
||||||
oneRpc: {
|
oneRpc: {
|
||||||
@ -349,9 +380,14 @@ export default {
|
|||||||
deployedBlock: 17754561,
|
deployedBlock: 17754561,
|
||||||
multicall: '0xb5b692a88bdfc81ca69dcb1d924f59f0413a602a',
|
multicall: '0xb5b692a88bdfc81ca69dcb1d924f59f0413a602a',
|
||||||
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||||
|
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
chainnodes: {
|
tornadoRPC: {
|
||||||
name: 'Tornado RPC',
|
name: 'Tornado RPC',
|
||||||
|
url: 'https://tornadocash-rpc.com/gnosis'
|
||||||
|
},
|
||||||
|
chainnodes: {
|
||||||
|
name: 'Chainnodes RPC',
|
||||||
url: 'https://gnosis-mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
url: 'https://gnosis-mainnet.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
||||||
},
|
},
|
||||||
blockPi: {
|
blockPi: {
|
||||||
@ -400,6 +436,7 @@ export default {
|
|||||||
deployedBlock: 4429818,
|
deployedBlock: 4429818,
|
||||||
multicall: '0xe86e3989c74293Acc962156cd3F525c07b6a1B6e',
|
multicall: '0xe86e3989c74293Acc962156cd3F525c07b6a1B6e',
|
||||||
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
echoContractAccount: '0xa75BF2815618872f155b7C4B0C81bF990f5245E4',
|
||||||
|
offchainOracleContract: '0x0AdDd25a91563696D8567Df78D5A01C9a991F9B8',
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
publicRpc: {
|
publicRpc: {
|
||||||
name: 'Avalanche RPC',
|
name: 'Avalanche RPC',
|
||||||
@ -433,115 +470,77 @@ export default {
|
|||||||
},
|
},
|
||||||
'tornado-proxy-light.contract.tornadocash.eth': '0x0D5550d52428E7e3175bfc9550207e4ad3859b17'
|
'tornado-proxy-light.contract.tornadocash.eth': '0x0D5550d52428E7e3175bfc9550207e4ad3859b17'
|
||||||
},
|
},
|
||||||
netId5: {
|
netId11155111: {
|
||||||
rpcCallRetryAttempt: 15,
|
rpcCallRetryAttempt: 15,
|
||||||
gasPrices: {
|
gasPrices: {
|
||||||
instant: 80,
|
instant: 2,
|
||||||
fast: 50,
|
fast: 2,
|
||||||
standard: 25,
|
standard: 2,
|
||||||
low: 8
|
low: 2
|
||||||
},
|
},
|
||||||
nativeCurrency: 'eth',
|
nativeCurrency: 'eth',
|
||||||
currencyName: 'gETH',
|
currencyName: 'ETH',
|
||||||
explorerUrl: {
|
explorerUrl: {
|
||||||
tx: 'https://goerli.etherscan.io/tx/',
|
tx: 'https://sepolia.etherscan.io/tx/',
|
||||||
address: 'https://goerli.etherscan.io/address/',
|
address: 'https://sepolia.etherscan.io/address/',
|
||||||
block: 'https://goerli.etherscan.io/block/'
|
block: 'https://sepolia.etherscan.io/block/'
|
||||||
},
|
},
|
||||||
merkleTreeHeight: 20,
|
merkleTreeHeight: 20,
|
||||||
emptyElement: '21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
emptyElement: '21663839004416932945382355908790599225266501822907911457504978515578255421292',
|
||||||
networkName: 'Ethereum Goerli',
|
networkName: 'Ethereum Sepolia',
|
||||||
deployedBlock: 3781595,
|
deployedBlock: 5594395,
|
||||||
multicall: '0x77dca2c955b15e9de4dbbcf1246b4b85b651e50e',
|
multicall: '0xcA11bde05977b3631167028862bE2a173976CA11',
|
||||||
echoContractAccount: '0x37e6859804b6499d1e4a86d70a5fdd5de6a0ac65',
|
echoContractAccount: '0xcDD1fc3F5ac2782D83449d3AbE80D6b7B273B0e5',
|
||||||
aggregatorContract: '0x8cb1436F64a3c33aD17bb42F94e255c4c0E871b2',
|
aggregatorContract: '0x4088712AC9fad39ea133cdb9130E465d235e9642',
|
||||||
rpcUrls: {
|
rpcUrls: {
|
||||||
chainnodes: {
|
tornadoRPC: {
|
||||||
name: 'Tornado RPC',
|
name: 'Tornado RPC',
|
||||||
url: 'https://goerli.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
url: 'https://tornadocash-rpc.com/sepolia'
|
||||||
},
|
},
|
||||||
gatewayRPC: {
|
sepolia: {
|
||||||
name: 'Gateway RPC',
|
name: 'Sepolia RPC',
|
||||||
url: 'https://rpc.goerli.eth.gateway.fm'
|
url: 'https://rpc.sepolia.org'
|
||||||
|
},
|
||||||
|
chainnodes: {
|
||||||
|
name: 'Chainnodes RPC',
|
||||||
|
url: 'https://sepolia.chainnodes.org/d692ae63-0a7e-43e0-9da9-fe4f4cc6c607'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tokens: {
|
tokens: {
|
||||||
eth: {
|
eth: {
|
||||||
instanceAddress: {
|
instanceAddress: {
|
||||||
'0.1': '0x6Bf694a291DF3FeC1f7e69701E3ab6c592435Ae7',
|
'0.1': '0x8C4A04d872a6C1BE37964A21ba3a138525dFF50b',
|
||||||
'1': '0x3aac1cC67c2ec5Db4eA850957b967Ba153aD6279',
|
'1': '0x8cc930096B4Df705A007c4A039BDFA1320Ed2508',
|
||||||
'10': '0x723B78e67497E85279CB204544566F4dC5d2acA0',
|
'10': '0x8D10d506D29Fc62ABb8A290B99F66dB27Fc43585',
|
||||||
'100': '0x0E3A09dDA6B20aFbB34aC7cD4A6881493f3E7bf7'
|
'100': '0x44c5C92ed73dB43888210264f0C8b36Fd68D8379'
|
||||||
},
|
},
|
||||||
symbol: 'ETH',
|
symbol: 'ETH',
|
||||||
decimals: 18
|
decimals: 18
|
||||||
},
|
},
|
||||||
dai: {
|
dai: {
|
||||||
instanceAddress: {
|
instanceAddress: {
|
||||||
'100': '0x76D85B4C0Fc497EeCc38902397aC608000A06607',
|
'100': '0x6921fd1a97441dd603a997ED6DDF388658daf754',
|
||||||
'1000': '0xCC84179FFD19A1627E79F8648d09e095252Bc418',
|
'1000': '0x50a637770F5d161999420F7d70d888DE47207145',
|
||||||
'10000': '0xD5d6f8D9e784d0e26222ad3834500801a68D027D',
|
'10000': '0xecD649870407cD43923A816Cc6334a5bdf113621',
|
||||||
'100000': '0x407CcEeaA7c95d2FE2250Bf9F2c105aA7AAFB512'
|
'100000': '0x73B4BD04bF83206B6e979BE2507098F92EDf4F90'
|
||||||
},
|
},
|
||||||
tokenAddress: '0xdc31Ee1784292379Fbb2964b3B9C4124D8F89C60',
|
tokenAddress: '0xFF34B3d4Aee8ddCd6F9AFFFB6Fe49bD371b8a357',
|
||||||
|
tokenGasLimit: 70_000,
|
||||||
symbol: 'DAI',
|
symbol: 'DAI',
|
||||||
decimals: 18,
|
decimals: 18,
|
||||||
gasLimit: '55000'
|
gasLimit: 700_000
|
||||||
},
|
|
||||||
cdai: {
|
|
||||||
instanceAddress: {
|
|
||||||
'5000': '0x833481186f16Cece3f1Eeea1a694c42034c3a0dB',
|
|
||||||
'50000': '0xd8D7DE3349ccaA0Fde6298fe6D7b7d0d34586193',
|
|
||||||
'500000': '0x8281Aa6795aDE17C8973e1aedcA380258Bc124F9',
|
|
||||||
'5000000': '0x57b2B8c82F065de8Ef5573f9730fC1449B403C9f'
|
|
||||||
},
|
|
||||||
tokenAddress: '0x822397d9a55d0fefd20F5c4bCaB33C5F65bd28Eb',
|
|
||||||
symbol: 'cDAI',
|
|
||||||
decimals: 8,
|
|
||||||
gasLimit: '425000'
|
|
||||||
},
|
|
||||||
usdc: {
|
|
||||||
instanceAddress: {
|
|
||||||
'100': '0x05E0b5B40B7b66098C2161A5EE11C5740A3A7C45',
|
|
||||||
'1000': '0x23173fE8b96A4Ad8d2E17fB83EA5dcccdCa1Ae52'
|
|
||||||
},
|
|
||||||
tokenAddress: '0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C',
|
|
||||||
symbol: 'USDC',
|
|
||||||
decimals: 6,
|
|
||||||
gasLimit: '80000'
|
|
||||||
},
|
|
||||||
usdt: {
|
|
||||||
instanceAddress: {
|
|
||||||
'100': '0x538Ab61E8A9fc1b2f93b3dd9011d662d89bE6FE6',
|
|
||||||
'1000': '0x94Be88213a387E992Dd87DE56950a9aef34b9448'
|
|
||||||
},
|
|
||||||
tokenAddress: '0xb7FC2023D96AEa94Ba0254AA5Aeb93141e4aad66',
|
|
||||||
symbol: 'USDT',
|
|
||||||
decimals: 6,
|
|
||||||
gasLimit: '100000'
|
|
||||||
},
|
|
||||||
wbtc: {
|
|
||||||
instanceAddress: {
|
|
||||||
'0.1': '0x242654336ca2205714071898f67E254EB49ACdCe',
|
|
||||||
'1': '0x776198CCF446DFa168347089d7338879273172cF',
|
|
||||||
'10': '0xeDC5d01286f99A066559F60a585406f3878a033e'
|
|
||||||
},
|
|
||||||
tokenAddress: '0xC04B0d3107736C32e19F1c62b2aF67BE61d63a05',
|
|
||||||
symbol: 'WBTC',
|
|
||||||
decimals: 8,
|
|
||||||
gasLimit: '85000'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ensSubdomainKey: 'goerli-tornado',
|
ensSubdomainKey: 'sepolia-tornado',
|
||||||
pollInterval: 15,
|
pollInterval: 15,
|
||||||
constants: {
|
constants: {
|
||||||
GOVERNANCE_BLOCK: 3945171,
|
GOVERNANCE_BLOCK: 5594395,
|
||||||
NOTE_ACCOUNT_BLOCK: 4131375,
|
NOTE_ACCOUNT_BLOCK: 5594395,
|
||||||
ENCRYPTED_NOTES_BLOCK: 4131375,
|
ENCRYPTED_NOTES_BLOCK: 5594395,
|
||||||
MINING_BLOCK_TIME: 15
|
MINING_BLOCK_TIME: 15
|
||||||
},
|
},
|
||||||
'torn.contract.tornadocash.eth': '0x77777FeDdddFfC19Ff86DB637967013e6C6A116C',
|
'torn.contract.tornadocash.eth': '0x3AE6667167C0f44394106E197904519D808323cA',
|
||||||
'governance.contract.tornadocash.eth': '0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce',
|
'governance.contract.tornadocash.eth': '0xe5324cD7602eeb387418e594B87aCADee08aeCAD',
|
||||||
'tornado-proxy.contract.tornadocash.eth': '0x454d870a72e29d5e5697f635128d18077bd04c60'
|
'tornado-router.contract.tornadocash.eth': '0x1572AFE6949fdF51Cb3E0856216670ae9Ee160Ee'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,6 +178,24 @@ export default {
|
|||||||
if (ctx.isClient) {
|
if (ctx.isClient) {
|
||||||
config.devtool = hasSourceMaps
|
config.devtool = hasSourceMaps
|
||||||
}
|
}
|
||||||
|
config.module.rules.push({
|
||||||
|
test: /\.(js|cjs|mjs|jsx)$/,
|
||||||
|
include: /node_modules/,
|
||||||
|
type: 'javascript/auto',
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: {
|
||||||
|
compact: false,
|
||||||
|
presets: [['@babel/preset-env', { targets: 'defaults' }]],
|
||||||
|
plugins: [
|
||||||
|
'@babel/plugin-transform-private-methods',
|
||||||
|
'@babel/plugin-transform-class-properties',
|
||||||
|
'@babel/plugin-transform-optional-chaining',
|
||||||
|
'@babel/plugin-transform-nullish-coalescing-operator'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
config.module.rules.push({
|
config.module.rules.push({
|
||||||
test: /\.bin$/,
|
test: /\.bin$/,
|
||||||
use: 'arraybuffer-loader'
|
use: 'arraybuffer-loader'
|
||||||
|
15
package.json
15
package.json
@ -7,14 +7,19 @@
|
|||||||
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
|
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
|
||||||
"precommit": "yarn lint",
|
"precommit": "yarn lint",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"dev": "cross-env NODE_OPTIONS='--max-old-space-size=8192' nuxt",
|
"fix:vuex": "node ./scripts/vuex.js",
|
||||||
"build": "nuxt build",
|
"dev": "cross-env NODE_OPTIONS=\"--max_old_space_size=8192\" nuxt",
|
||||||
|
"dev:lts": "yarn fix:vuex && cross-env NODE_OPTIONS=\"--max_old_space_size=8192 --openssl-legacy-provider\" nuxt",
|
||||||
|
"build": "cross-env NODE_OPTIONS=\"--max_old_space_size=8192\" nuxt build",
|
||||||
|
"build:lts": "yarn fix:vuex && cross-env NODE_OPTIONS=\"--max_old_space_size=8192 --openssl-legacy-provider\" nuxt build",
|
||||||
"start": "nuxt start",
|
"start": "nuxt start",
|
||||||
"update:zip": "node -r esm scripts/updateZip.js",
|
"update:zip": "node -r esm scripts/updateZip.js",
|
||||||
"update:events": "node -r esm scripts/updateEvents.js --network",
|
"update:events": "node -r esm scripts/updateEvents.js --network",
|
||||||
"update:encrypted": "node -r esm scripts/updateEncryptedEvents.js --network",
|
"update:encrypted": "node -r esm scripts/updateEncryptedEvents.js --network",
|
||||||
"update:tree": "node -r esm scripts/updateTree.js --network",
|
"update:tree": "node -r esm scripts/updateTree.js --network",
|
||||||
"generate": "cross-env NODE_OPTIONS='--max-old-space-size=8192' nuxt generate && cp dist/404.html dist/ipfs-404.html",
|
"update:copy": "node -r esm scripts/copyFile.js dist/404.html dist/ipfs-404.html",
|
||||||
|
"generate": "cross-env NODE_OPTIONS=\"--max_old_space_size=8192\" nuxt generate && yarn update:copy",
|
||||||
|
"generate:lts": "yarn fix:vuex && cross-env NODE_OPTIONS=\"--max_old_space_size=8192 --openssl-legacy-provider\" nuxt generate && yarn update:copy",
|
||||||
"check:sync": "node -r esm scripts/checkEventsSync.js",
|
"check:sync": "node -r esm scripts/checkEventsSync.js",
|
||||||
"ipfsUpload": "node scripts/ipfsUpload.js",
|
"ipfsUpload": "node scripts/ipfsUpload.js",
|
||||||
"deploy:ipfs": "yarn generate && yarn ipfsUpload"
|
"deploy:ipfs": "yarn generate && yarn ipfsUpload"
|
||||||
@ -25,7 +30,7 @@
|
|||||||
"@nuxtjs/moment": "^1.6.0",
|
"@nuxtjs/moment": "^1.6.0",
|
||||||
"@tornado/fixed-merkle-tree": "0.7",
|
"@tornado/fixed-merkle-tree": "0.7",
|
||||||
"@tornado/snarkjs": "0.1.20",
|
"@tornado/snarkjs": "0.1.20",
|
||||||
"@tornado/tornado-oracles": "^2.1.0",
|
"@tornado/tornado-oracles": "git+https://git.tornado.ws/tornadocontrib/tornado-oracles.git#0e9fe6970d54995f00cf3dbc1cfc73d9f7365a62",
|
||||||
"@tornado/websnark": "0.0.4",
|
"@tornado/websnark": "0.0.4",
|
||||||
"@walletconnect/web3-provider": "1.7.8",
|
"@walletconnect/web3-provider": "1.7.8",
|
||||||
"ajv": "^6.10.2",
|
"ajv": "^6.10.2",
|
||||||
@ -39,6 +44,7 @@
|
|||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"eth-ens-namehash": "^2.0.8",
|
"eth-ens-namehash": "^2.0.8",
|
||||||
"eth-sig-util": "^2.5.3",
|
"eth-sig-util": "^2.5.3",
|
||||||
|
"ethers": "^6.12.1",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"form-data": "^3.0.0",
|
"form-data": "^3.0.0",
|
||||||
"graphql": "^15.5.1",
|
"graphql": "^15.5.1",
|
||||||
@ -59,6 +65,7 @@
|
|||||||
"web3": "1.5.2"
|
"web3": "1.5.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/preset-env": "7.24.4",
|
||||||
"@nuxtjs/eslint-config": "^1.1.2",
|
"@nuxtjs/eslint-config": "^1.1.2",
|
||||||
"@nuxtjs/eslint-module": "^1.1.0",
|
"@nuxtjs/eslint-module": "^1.1.0",
|
||||||
"@vue/test-utils": "^1.0.0-beta.27",
|
"@vue/test-utils": "^1.0.0-beta.27",
|
||||||
|
15
scripts/copyFile.js
Normal file
15
scripts/copyFile.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { argv } from 'process'
|
||||||
|
import { copyFile } from 'fs'
|
||||||
|
|
||||||
|
function copyFiles() {
|
||||||
|
const [, , inFile, outFile] = argv
|
||||||
|
|
||||||
|
copyFile(inFile, outFile, function(err) {
|
||||||
|
if (err) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Copied ${inFile} to ${outFile}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
copyFiles()
|
24
scripts/vuex.js
Normal file
24
scripts/vuex.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Manually patch vuex to support Node.js >= 18.x
|
||||||
|
*
|
||||||
|
* See issue https://github.com/vuejs/vuex/issues/2160
|
||||||
|
* https://github.com/vuejs/vuex/commit/397e9fba45c8b4ec0c4a33d2578e34829bd348d7
|
||||||
|
*/
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
|
const pkgJson = JSON.parse(fs.readFileSync('./node_modules/vuex/package.json', { encoding: 'utf8' }))
|
||||||
|
const backupJson = JSON.stringify(pkgJson, null, 2)
|
||||||
|
|
||||||
|
let changes = false
|
||||||
|
|
||||||
|
if (!pkgJson.exports['./*']) {
|
||||||
|
pkgJson.exports['./*'] = './*'
|
||||||
|
|
||||||
|
changes = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (changes) {
|
||||||
|
fs.writeFileSync('./node_modules/vuex/package.backup.json', backupJson + '\n')
|
||||||
|
fs.writeFileSync('./node_modules/vuex/package.json', JSON.stringify(pkgJson, null, 2) + '\n')
|
||||||
|
}
|
@ -412,10 +412,11 @@ class EventService {
|
|||||||
async getEventsFromBlock({ fromBlock, graphMethod, type }) {
|
async getEventsFromBlock({ fromBlock, graphMethod, type }) {
|
||||||
try {
|
try {
|
||||||
// ToDo think about undefined
|
// ToDo think about undefined
|
||||||
const rpcEvents = await this.getEventsFromRpc({ fromBlock, type })
|
const graphEvents = await this.getEventsFromGraph({ fromBlock, methodName: graphMethod })
|
||||||
|
const lastSyncBlock = fromBlock > graphEvents?.lastBlock ? fromBlock : graphEvents?.lastBlock
|
||||||
const allEvents = [].concat(rpcEvents || [])
|
const rpcEvents = await this.getEventsFromRpc({ fromBlock: lastSyncBlock, type })
|
||||||
|
|
||||||
|
const allEvents = [].concat(graphEvents?.events || [], rpcEvents || [])
|
||||||
if (allEvents.length) {
|
if (allEvents.length) {
|
||||||
return {
|
return {
|
||||||
events: allEvents,
|
events: allEvents,
|
||||||
|
@ -20,14 +20,14 @@ const link = ({ getContext }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CHAIN_GRAPH_URLS = {
|
const CHAIN_GRAPH_URLS = {
|
||||||
1: 'https://api.thegraph.com/subgraphs/name/tornadocash/mainnet-tornado-subgraph',
|
1: 'https://tornadocash-rpc.com/subgraphs/name/tornadocash/mainnet-tornado-subgraph',
|
||||||
5: 'https://api.thegraph.com/subgraphs/name/tornadocash/goerli-tornado-subgraph',
|
10: 'https://tornadocash-rpc.com/subgraphs/name/tornadocash/optimism-tornado-subgraph',
|
||||||
10: 'https://api.thegraph.com/subgraphs/name/tornadocash/optimism-tornado-subgraph',
|
56: 'https://tornadocash-rpc.com/subgraphs/name/tornadocash/bsc-tornado-subgraph',
|
||||||
56: 'https://api.thegraph.com/subgraphs/name/tornadocash/bsc-tornado-subgraph',
|
100: 'https://tornadocash-rpc.com/subgraphs/name/tornadocash/xdai-tornado-subgraph',
|
||||||
100: 'https://api.thegraph.com/subgraphs/name/tornadocash/xdai-tornado-subgraph',
|
137: 'https://tornadocash-rpc.com/subgraphs/name/tornadocash/matic-tornado-subgraph',
|
||||||
137: 'https://api.thegraph.com/subgraphs/name/tornadocash/matic-tornado-subgraph',
|
42161: 'https://tornadocash-rpc.com/subgraphs/name/tornadocash/arbitrum-tornado-subgraph',
|
||||||
42161: 'https://api.thegraph.com/subgraphs/name/tornadocash/arbitrum-tornado-subgraph',
|
43114: 'https://api.thegraph.com/subgraphs/name/tornadocash/avalanche-tornado-subgraph',
|
||||||
43114: 'https://api.thegraph.com/subgraphs/name/tornadocash/avalanche-tornado-subgraph'
|
11155111: 'https://tornadocash-rpc.com/subgraphs/name/tornadocash/sepolia-tornado-subgraph'
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
@ -45,7 +45,7 @@ const client = new ApolloClient({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const registryClient = new ApolloClient({
|
const registryClient = new ApolloClient({
|
||||||
uri: 'https://api.thegraph.com/subgraphs/name/tornadocash/tornado-relayer-registry',
|
uri: 'https://tornadocash-rpc.com/subgraphs/name/tornadocash/tornado-relayer-registry',
|
||||||
cache: new InMemoryCache(),
|
cache: new InMemoryCache(),
|
||||||
credentials: 'omit',
|
credentials: 'omit',
|
||||||
defaultOptions
|
defaultOptions
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
// from https://github.com/ChainSafe/web3.js/issues/2683#issuecomment-547348416
|
// from https://github.com/ChainSafe/web3.js/issues/2683#issuecomment-547348416
|
||||||
|
|
||||||
import namehash from 'eth-ens-namehash'
|
import namehash from 'eth-ens-namehash'
|
||||||
import { BigNumber, utils } from 'ethers'
|
|
||||||
import ABI from 'web3-eth-ens/lib/resources/ABI/Resolver'
|
import ABI from 'web3-eth-ens/lib/resources/ABI/Resolver'
|
||||||
import uniq from 'lodash/uniq'
|
import uniq from 'lodash/uniq'
|
||||||
import chunk from 'lodash/chunk'
|
import chunk from 'lodash/chunk'
|
||||||
import { CHUNK_COUNT_PER_BATCH_REQUEST } from '@/constants'
|
import { CHUNK_COUNT_PER_BATCH_REQUEST } from '@/constants'
|
||||||
|
|
||||||
|
const { isAddress } = require('web3-utils')
|
||||||
|
|
||||||
export const createBatchRequestCallback = (resolve, reject) => (error, data) => {
|
export const createBatchRequestCallback = (resolve, reject) => (error, data) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error)
|
reject(error)
|
||||||
@ -65,8 +66,7 @@ const createFetchEnsNames = (web3, batch, results) => async (data) => {
|
|||||||
batch.add(requestData)
|
batch.add(requestData)
|
||||||
})
|
})
|
||||||
|
|
||||||
const isZeroAddress =
|
const isZeroAddress = ensName.trim().length && isAddress(ensName) && BigInt(ensName) === BigInt(0)
|
||||||
ensName.trim().length && utils.isAddress(ensName) && BigNumber.from(ensName).isZero()
|
|
||||||
|
|
||||||
if (isZeroAddress) return results
|
if (isZeroAddress) return results
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import namehash from 'eth-ens-namehash'
|
|||||||
import { BigNumber as BN } from 'bignumber.js'
|
import { BigNumber as BN } from 'bignumber.js'
|
||||||
import { toChecksumAddress, isAddress } from 'web3-utils'
|
import { toChecksumAddress, isAddress } from 'web3-utils'
|
||||||
|
|
||||||
|
import { graph } from '@/services'
|
||||||
import networkConfig from '@/networkConfig'
|
import networkConfig from '@/networkConfig'
|
||||||
import { REGISTRY_DEPLOYED_BLOCK } from '@/constants'
|
import { REGISTRY_DEPLOYED_BLOCK } from '@/constants'
|
||||||
import { sleep, flattenNArray } from '@/utils'
|
import { sleep, flattenNArray } from '@/utils'
|
||||||
@ -169,9 +170,21 @@ class RelayerRegister {
|
|||||||
fetchRelayers = async () => {
|
fetchRelayers = async () => {
|
||||||
const blockRange = 10000
|
const blockRange = 10000
|
||||||
// eslint-disable-next-line prefer-const
|
// eslint-disable-next-line prefer-const
|
||||||
let { blockTo, cachedEvents } = await this.getCachedData()
|
let { blockFrom, blockTo, cachedEvents } = await this.getCachedData()
|
||||||
let allRelayers = cachedEvents
|
let allRelayers = cachedEvents
|
||||||
|
|
||||||
|
if (!cachedEvents || !cachedEvents.length) {
|
||||||
|
const { lastSyncBlock, events } = await graph.getAllRegisters(blockFrom)
|
||||||
|
|
||||||
|
if (events.length) {
|
||||||
|
blockTo = lastSyncBlock + 1
|
||||||
|
cachedEvents = events.map((el) => ({
|
||||||
|
ensName: el.ensName,
|
||||||
|
relayerAddress: toChecksumAddress(el.address)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const currentBlockNumber = await this.provider.getBlockNumber()
|
const currentBlockNumber = await this.provider.getBlockNumber()
|
||||||
const fromBlock = cachedEvents.length === 0 ? REGISTRY_DEPLOYED_BLOCK[1] : blockTo
|
const fromBlock = cachedEvents.length === 0 ? REGISTRY_DEPLOYED_BLOCK[1] : blockTo
|
||||||
const blockDifference = currentBlockNumber - fromBlock
|
const blockDifference = currentBlockNumber - fromBlock
|
||||||
@ -181,7 +194,7 @@ class RelayerRegister {
|
|||||||
let registerRelayerEvents
|
let registerRelayerEvents
|
||||||
let lastSyncBlock = blockTo
|
let lastSyncBlock = blockTo
|
||||||
|
|
||||||
if (cachedEvents.length > 0 || blockDifference === 0) {
|
if (blockDifference <= 0) {
|
||||||
return cachedEvents
|
return cachedEvents
|
||||||
} else if (blockDifference >= blockRange) {
|
} else if (blockDifference >= blockRange) {
|
||||||
toBlock = currentBlockNumber
|
toBlock = currentBlockNumber
|
||||||
@ -257,12 +270,22 @@ class RelayerRegister {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getValidRelayers = async (relayers, ensSubdomainKey) => {
|
getValidRelayers = async (relayers, ensSubdomainKey) => {
|
||||||
const relayerNameHashes = relayers.map((r) => namehash.hash(r.ensName))
|
const relayersSet = new Set()
|
||||||
|
|
||||||
|
const uniqueRelayers = relayers.filter(({ ensName }) => {
|
||||||
|
if (!relayersSet.has(ensName)) {
|
||||||
|
relayersSet.add(ensName)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
const relayerNameHashes = uniqueRelayers.map((r) => namehash.hash(r.ensName))
|
||||||
|
|
||||||
const relayersData = await this.aggregator.methods.relayersData(relayerNameHashes, subdomains).call()
|
const relayersData = await this.aggregator.methods.relayersData(relayerNameHashes, subdomains).call()
|
||||||
|
|
||||||
const validRelayers = relayersData.reduce(
|
const validRelayers = relayersData.reduce(
|
||||||
(acc, curr, index) => this.filterRelayer(acc, curr, ensSubdomainKey, relayers[index]),
|
(acc, curr, index) => this.filterRelayer(acc, curr, ensSubdomainKey, uniqueRelayers[index]),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
/* eslint-disable no-console, import/order */
|
/* eslint-disable no-console, import/order */
|
||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
|
import { ZeroAddress } from 'ethers'
|
||||||
|
|
||||||
import networkConfig from '@/networkConfig'
|
import networkConfig from '@/networkConfig'
|
||||||
import { cachedEventsLength, eventsType, httpConfig } from '@/constants'
|
import { cachedEventsLength, eventsType, httpConfig } from '@/constants'
|
||||||
@ -106,26 +107,29 @@ const mutations = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
|
getWeb3: (state, getters, rootState, rootGetters) => {
|
||||||
|
const netId = rootGetters['metamask/netId']
|
||||||
|
const { url } = rootState.settings[`netId${netId}`].rpc
|
||||||
|
const httpProvider = new Web3.providers.HttpProvider(url, httpConfig)
|
||||||
|
return new Web3(httpProvider)
|
||||||
|
},
|
||||||
eventsInterface: (state, getters, rootState, rootGetters) => {
|
eventsInterface: (state, getters, rootState, rootGetters) => {
|
||||||
const netId = rootGetters['metamask/netId']
|
const netId = rootGetters['metamask/netId']
|
||||||
const { url } = rootState.settings[`netId${netId}`].rpc
|
const { url } = rootState.settings[`netId${netId}`].rpc
|
||||||
return new EventsFactory(url)
|
return new EventsFactory(url)
|
||||||
},
|
},
|
||||||
instanceContract: (state, getters, rootState) => ({ currency, amount, netId }) => {
|
instanceContract: (state, getters) => ({ currency, amount, netId }) => {
|
||||||
const config = networkConfig[`netId${netId}`]
|
const config = networkConfig[`netId${netId}`]
|
||||||
const { url } = rootState.settings[`netId${netId}`].rpc
|
|
||||||
const address = config.tokens[currency].instanceAddress[amount]
|
const address = config.tokens[currency].instanceAddress[amount]
|
||||||
const httpProvider = new Web3.providers.HttpProvider(url, httpConfig)
|
const web3 = getters.getWeb3
|
||||||
const web3 = new Web3(httpProvider)
|
|
||||||
return new web3.eth.Contract(InstanceABI, address)
|
return new web3.eth.Contract(InstanceABI, address)
|
||||||
},
|
},
|
||||||
multicallContract: (state, getters, rootState) => ({ netId }) => {
|
multicallContract: (state, getters) => ({ netId }) => {
|
||||||
const config = networkConfig[`netId${netId}`]
|
const config = networkConfig[`netId${netId}`]
|
||||||
const { url } = rootState.settings[`netId${netId}`].rpc
|
const web3 = getters.getWeb3
|
||||||
const web3 = new Web3(url)
|
|
||||||
return new web3.eth.Contract(MulticallABI, config.multicall)
|
return new web3.eth.Contract(MulticallABI, config.multicall)
|
||||||
},
|
},
|
||||||
tornadoProxyContract: (state, getters, rootState) => ({ netId }) => {
|
tornadoProxyContract: (state, getters) => ({ netId }) => {
|
||||||
const {
|
const {
|
||||||
'tornado-proxy.contract.tornadocash.eth': tornadoProxy,
|
'tornado-proxy.contract.tornadocash.eth': tornadoProxy,
|
||||||
'tornado-router.contract.tornadocash.eth': tornadoRouter,
|
'tornado-router.contract.tornadocash.eth': tornadoRouter,
|
||||||
@ -133,8 +137,7 @@ const getters = {
|
|||||||
} = networkConfig[`netId${netId}`]
|
} = networkConfig[`netId${netId}`]
|
||||||
|
|
||||||
const proxyContract = tornadoRouter || tornadoProxy || tornadoProxyLight
|
const proxyContract = tornadoRouter || tornadoProxy || tornadoProxyLight
|
||||||
const { url } = rootState.settings[`netId${netId}`].rpc
|
const web3 = getters.getWeb3
|
||||||
const web3 = new Web3(url)
|
|
||||||
return new web3.eth.Contract(TornadoProxyABI, proxyContract)
|
return new web3.eth.Contract(TornadoProxyABI, proxyContract)
|
||||||
},
|
},
|
||||||
currentContract: (state, getters) => (params) => {
|
currentContract: (state, getters) => (params) => {
|
||||||
@ -150,11 +153,16 @@ const getters = {
|
|||||||
const tornadoProxy = getters.tornadoProxyContract({ netId })
|
const tornadoProxy = getters.tornadoProxyContract({ netId })
|
||||||
const tornadoInstance = getters.instanceContract({ currency, amount, netId })
|
const tornadoInstance = getters.instanceContract({ currency, amount, netId })
|
||||||
|
|
||||||
|
const { withdrawType } = state
|
||||||
|
const relayer = rootState.relayer.selectedRelayer.address
|
||||||
|
const { ethAccount } = rootState.metamask
|
||||||
|
|
||||||
const calldata = tornadoProxy.methods
|
const calldata = tornadoProxy.methods
|
||||||
.withdraw(tornadoInstance._address, proof, ...withdrawCallArgs)
|
.withdraw(tornadoInstance._address, proof, ...withdrawCallArgs)
|
||||||
.encodeABI()
|
.encodeABI()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
from: withdrawType === 'relayer' ? relayer : ethAccount,
|
||||||
to: tornadoProxy._address,
|
to: tornadoProxy._address,
|
||||||
data: calldata,
|
data: calldata,
|
||||||
value: withdrawCallArgs[5] || 0
|
value: withdrawCallArgs[5] || 0
|
||||||
@ -410,7 +418,6 @@ const actions = {
|
|||||||
|
|
||||||
const networksWithCache = {
|
const networksWithCache = {
|
||||||
1: cachedEventsLength.mainnet.ENCRYPTED_NOTES,
|
1: cachedEventsLength.mainnet.ENCRYPTED_NOTES,
|
||||||
5: cachedEventsLength.goerli.ENCRYPTED_NOTES,
|
|
||||||
56: cachedEventsLength.bsc.ENCRYPTED_NOTES
|
56: cachedEventsLength.bsc.ENCRYPTED_NOTES
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,6 +518,7 @@ const actions = {
|
|||||||
},
|
},
|
||||||
async sendDeposit({ state, rootState, getters, rootGetters, dispatch, commit }, { isEncrypted }) {
|
async sendDeposit({ state, rootState, getters, rootGetters, dispatch, commit }, { isEncrypted }) {
|
||||||
try {
|
try {
|
||||||
|
const web3 = getters.getWeb3
|
||||||
const { commitment, note, prefix } = state
|
const { commitment, note, prefix } = state
|
||||||
// eslint-disable-next-line prefer-const
|
// eslint-disable-next-line prefer-const
|
||||||
let [, currency, amount, netId] = prefix.split('-')
|
let [, currency, amount, netId] = prefix.split('-')
|
||||||
@ -549,7 +557,7 @@ const actions = {
|
|||||||
value: numberToHex(value),
|
value: numberToHex(value),
|
||||||
data
|
data
|
||||||
}
|
}
|
||||||
const gasLimit = await rootGetters['fees/oracle'].getGasLimit(incompletedTx, 'other', 10)
|
const gasLimit = Math.floor((await web3.eth.estimateGas(incompletedTx)) * 1.2)
|
||||||
|
|
||||||
const callParams = {
|
const callParams = {
|
||||||
method: 'eth_sendTransaction',
|
method: 'eth_sendTransaction',
|
||||||
@ -666,36 +674,69 @@ const actions = {
|
|||||||
{ rootGetters, rootState, state, getters, dispatch },
|
{ rootGetters, rootState, state, getters, dispatch },
|
||||||
{ root, note, tree, recipient, leafIndex }
|
{ root, note, tree, recipient, leafIndex }
|
||||||
) {
|
) {
|
||||||
|
const { circuit, provingKey } = await getTornadoKeys()
|
||||||
|
|
||||||
|
if (!groth16) {
|
||||||
|
groth16 = await buildGroth16()
|
||||||
|
}
|
||||||
|
|
||||||
|
const web3 = getters.getWeb3
|
||||||
|
|
||||||
|
const { nullifierHash, secret, nullifier, amount, currency } = note
|
||||||
|
|
||||||
|
const { denomination, isNativeCurrency } = rootGetters['fees/selectedInstance']
|
||||||
|
const withdrawType = state.withdrawType
|
||||||
|
|
||||||
const { pathElements, pathIndices } = tree.path(leafIndex)
|
const { pathElements, pathIndices } = tree.path(leafIndex)
|
||||||
console.log('pathElements, pathIndices', pathElements, pathIndices)
|
console.log('pathElements, pathIndices', pathElements, pathIndices)
|
||||||
|
|
||||||
const nativeCurrency = rootGetters['metamask/nativeCurrency']
|
const defaultGasLimit = rootGetters['fees/gasLimit']()
|
||||||
const withdrawType = state.withdrawType
|
let gasLimit = defaultGasLimit
|
||||||
|
|
||||||
let relayer = BigInt(0)
|
async function getProof() {
|
||||||
|
let relayer = ZeroAddress
|
||||||
let fee = BigInt(0)
|
let fee = BigInt(0)
|
||||||
let refund = BigInt(0)
|
let refund = BigInt(0)
|
||||||
|
|
||||||
async function calculateSnarkProof() {
|
if (withdrawType === 'relayer') {
|
||||||
|
// Recalculate proof with actual fee and refund
|
||||||
|
await dispatch(
|
||||||
|
'fees/calculateWithdrawalFeeViaRelayer',
|
||||||
|
{
|
||||||
|
tx: {
|
||||||
|
gasLimit
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ root: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
relayer = rootState.relayer.selectedRelayer.address
|
||||||
|
fee = BigInt(rootState.fees.withdrawalFeeViaRelayer)
|
||||||
|
|
||||||
|
if (fee > denomination) {
|
||||||
|
throw new Error(
|
||||||
|
'Relayer fee exceeds the withdraw amount, disable relayer withdrawal or use other amount'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNativeCurrency) {
|
||||||
|
refund = rootGetters['fees/ethRefund']
|
||||||
|
}
|
||||||
|
|
||||||
const input = {
|
const input = {
|
||||||
// public
|
// public
|
||||||
fee,
|
fee,
|
||||||
root,
|
root,
|
||||||
refund,
|
refund,
|
||||||
relayer,
|
relayer: BigInt(relayer),
|
||||||
recipient: BigInt(recipient),
|
recipient: BigInt(recipient),
|
||||||
nullifierHash: note.nullifierHash,
|
nullifierHash,
|
||||||
// private
|
// private
|
||||||
pathIndices,
|
pathIndices,
|
||||||
pathElements,
|
pathElements,
|
||||||
secret: note.secret,
|
secret,
|
||||||
nullifier: note.nullifier
|
nullifier
|
||||||
}
|
|
||||||
|
|
||||||
const { circuit, provingKey } = await getTornadoKeys()
|
|
||||||
|
|
||||||
if (!groth16) {
|
|
||||||
groth16 = await buildGroth16()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Start generating SNARK proof', input)
|
console.log('Start generating SNARK proof', input)
|
||||||
@ -712,31 +753,41 @@ const actions = {
|
|||||||
toFixedHex(input.refund)
|
toFixedHex(input.refund)
|
||||||
]
|
]
|
||||||
console.timeEnd('SNARK proof time')
|
console.timeEnd('SNARK proof time')
|
||||||
return { args, proof }
|
|
||||||
|
return {
|
||||||
|
relayer,
|
||||||
|
fee,
|
||||||
|
proof,
|
||||||
|
args
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't need to calculate or estimate relayer fee, so, return proof immediately
|
// eslint-disable-next-line prefer-const
|
||||||
if (withdrawType !== 'relayer') return calculateSnarkProof()
|
let { proof, args } = await getProof()
|
||||||
|
|
||||||
relayer = BigInt(rootState.relayer.selectedRelayer.address)
|
|
||||||
fee = BigInt(rootState.fees.withdrawalFeeViaRelayer)
|
|
||||||
const naiveProof = await calculateSnarkProof()
|
|
||||||
if (Number(note.netId) === 1) return naiveProof // Don't need to smart-estimate fee if we use V4 withdrawal
|
|
||||||
|
|
||||||
const { proof: dummyProof, args: dummyArgs } = naiveProof
|
|
||||||
const withdrawalTx = getters.relayerWithdrawalTxData({
|
const withdrawalTx = getters.relayerWithdrawalTxData({
|
||||||
proof: dummyProof,
|
proof,
|
||||||
withdrawCallArgs: dummyArgs,
|
withdrawCallArgs: args,
|
||||||
amount: note.amount,
|
amount,
|
||||||
currency: note.currency
|
currency
|
||||||
})
|
})
|
||||||
if (note.currency !== nativeCurrency) refund = BigInt(state.ethToReceive.toString())
|
|
||||||
|
|
||||||
await dispatch('fees/calculateWithdrawalFeeViaRelayer', { tx: withdrawalTx }, { root: true })
|
gasLimit = BigInt(await web3.eth.estimateGas(withdrawalTx))
|
||||||
fee = BigInt(rootState.fees.withdrawalFeeViaRelayer)
|
|
||||||
|
|
||||||
// Recalculate proof with actual fee and refund
|
// If required gasLimit is above default, calculate the snark proof again
|
||||||
return calculateSnarkProof()
|
if (gasLimit > defaultGasLimit) {
|
||||||
|
;({ proof, args } = await getProof())
|
||||||
|
|
||||||
|
const withdrawalTx = getters.relayerWithdrawalTxData({
|
||||||
|
proof,
|
||||||
|
withdrawCallArgs: args,
|
||||||
|
amount,
|
||||||
|
currency
|
||||||
|
})
|
||||||
|
gasLimit = BigInt(await web3.eth.estimateGas(withdrawalTx))
|
||||||
|
}
|
||||||
|
|
||||||
|
return { proof, args }
|
||||||
},
|
},
|
||||||
async prepareWithdraw({ dispatch, commit }, { note, recipient }) {
|
async prepareWithdraw({ dispatch, commit }, { note, recipient }) {
|
||||||
commit('REMOVE_PROOF', { note })
|
commit('REMOVE_PROOF', { note })
|
||||||
@ -766,6 +817,7 @@ const actions = {
|
|||||||
},
|
},
|
||||||
async withdraw({ state, rootState, rootGetters, dispatch, getters }, { note }) {
|
async withdraw({ state, rootState, rootGetters, dispatch, getters }, { note }) {
|
||||||
try {
|
try {
|
||||||
|
const web3 = getters.getWeb3
|
||||||
const [, currency, amount, netId] = note.split('-')
|
const [, currency, amount, netId] = note.split('-')
|
||||||
const config = networkConfig[`netId${netId}`]
|
const config = networkConfig[`netId${netId}`]
|
||||||
const { proof, args } = state.notes[note]
|
const { proof, args } = state.notes[note]
|
||||||
@ -783,7 +835,7 @@ const actions = {
|
|||||||
to: contractInstance._address,
|
to: contractInstance._address,
|
||||||
from: ethAccount
|
from: ethAccount
|
||||||
}
|
}
|
||||||
const gasLimit = await rootGetters['fees/oracle'].getGasLimit(incompletedTx, 'other', 20)
|
const gasLimit = Math.floor((await web3.eth.estimateGas(incompletedTx)) * 1.1)
|
||||||
|
|
||||||
const callParams = {
|
const callParams = {
|
||||||
method: 'eth_sendTransaction',
|
method: 'eth_sendTransaction',
|
||||||
@ -924,8 +976,8 @@ const actions = {
|
|||||||
console.error(`Method loadWithdrawalData has error: ${e}`)
|
console.error(`Method loadWithdrawalData has error: ${e}`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async setDefaultEthToReceive({ commit, rootGetters }, { currency }) {
|
setDefaultEthToReceive({ commit, rootGetters }, { gasPrice, refundGasLimit }) {
|
||||||
const ethToReceive = await rootGetters['fees/oracle'].calculateRefundInETH(currency.toLowerCase())
|
const ethToReceive = rootGetters['fees/oracle'].defaultEthRefund(gasPrice, refundGasLimit).toString()
|
||||||
commit('SAVE_ETH_TO_RECEIVE', { ethToReceive })
|
commit('SAVE_ETH_TO_RECEIVE', { ethToReceive })
|
||||||
commit('SAVE_DEFAULT_ETH_TO_RECEIVE', { ethToReceive })
|
commit('SAVE_DEFAULT_ETH_TO_RECEIVE', { ethToReceive })
|
||||||
},
|
},
|
||||||
|
206
store/fees.js
206
store/fees.js
@ -1,35 +1,122 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import { toWei, fromWei, toBN } from 'web3-utils'
|
import { toWei, toBN } from 'web3-utils'
|
||||||
import { TornadoFeeOracleV4, TornadoFeeOracleV5 } from '@tornado/tornado-oracles'
|
import { formatUnits, parseUnits } from 'ethers'
|
||||||
|
import { ChainId, TornadoFeeOracle, getProvider } from '@tornado/tornado-oracles'
|
||||||
|
import { WITHDRAW_GAS_LIMIT } from '@/constants/variables'
|
||||||
|
|
||||||
export const state = () => {
|
export const state = () => {
|
||||||
return {
|
return {
|
||||||
gasPriceParams: { gasPrice: toWei(toBN(50), 'gwei') },
|
gasPriceParams: { gasPrice: toWei(toBN(50), 'gwei') },
|
||||||
|
l1Fee: toBN(0),
|
||||||
withdrawalNetworkFee: toBN(0),
|
withdrawalNetworkFee: toBN(0),
|
||||||
withdrawalFeeViaRelayer: toBN(0)
|
withdrawalFeeViaRelayer: toBN(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getters = {
|
export const getters = {
|
||||||
|
provider: (state, getters, rootState, rootGetters) => {
|
||||||
|
const netId = Number(rootGetters['metamask/netId'])
|
||||||
|
const { url: rpcUrl } = rootState.settings[`netId${netId}`].rpc
|
||||||
|
const config = rootGetters['metamask/networkConfig']
|
||||||
|
|
||||||
|
return getProvider(netId, rpcUrl, config)
|
||||||
|
},
|
||||||
oracle: (state, getters, rootState, rootGetters) => {
|
oracle: (state, getters, rootState, rootGetters) => {
|
||||||
const netId = Number(rootGetters['metamask/netId'])
|
const netId = Number(rootGetters['metamask/netId'])
|
||||||
const { url: rpcUrl } = rootState.settings[`netId${netId}`].rpc
|
const { url: rpcUrl } = rootState.settings[`netId${netId}`].rpc
|
||||||
const { gasPrices } = rootGetters['metamask/networkConfig']
|
const config = rootGetters['metamask/networkConfig']
|
||||||
|
|
||||||
// Return old oracle for backwards compatibility, if chain is ETH Mainnet
|
return new TornadoFeeOracle(netId, rpcUrl, config)
|
||||||
return netId === 1
|
|
||||||
? new TornadoFeeOracleV4(netId, rpcUrl, gasPrices)
|
|
||||||
: new TornadoFeeOracleV5(netId, rpcUrl, gasPrices)
|
|
||||||
},
|
},
|
||||||
getGasPriceParams: (state) => {
|
getGasPriceParams: (state) => {
|
||||||
return state.gasPriceParams
|
return state.gasPriceParams
|
||||||
},
|
},
|
||||||
gasPrice: (state, getters) => {
|
getMetamaskGasPriceParams: (state) => {
|
||||||
const { gasPrice, maxFeePerGas } = getters.getGasPriceParams
|
const feeData = state.gasPriceParams
|
||||||
return maxFeePerGas || gasPrice
|
|
||||||
|
const gasParams = feeData.maxFeePerGas
|
||||||
|
? {
|
||||||
|
maxFeePerGas: '0x' + feeData.maxFeePerGas.toString(16),
|
||||||
|
maxPriorityFeePerGas: '0x' + feeData.maxPriorityFeePerGas.toString(16)
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
gasPrice: '0x' + feeData.gasPrice.toString(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
return gasParams
|
||||||
|
},
|
||||||
|
l1Fee: (state) => {
|
||||||
|
return state.l1Fee
|
||||||
|
},
|
||||||
|
selectedInstance: (state, getters, rootState, rootGetters) => {
|
||||||
|
const nativeCurrency = rootGetters['metamask/nativeCurrency']
|
||||||
|
const { tokens } = rootGetters['metamask/networkConfig']
|
||||||
|
const { currency, amount } = rootState.application.selectedStatistic
|
||||||
|
|
||||||
|
const {
|
||||||
|
instanceAddress: instanceAddresses,
|
||||||
|
decimals,
|
||||||
|
gasLimit: instanceGasLimit,
|
||||||
|
tokenGasLimit
|
||||||
|
} = tokens[currency]
|
||||||
|
|
||||||
|
const { [amount]: instanceAddress } = instanceAddresses
|
||||||
|
|
||||||
|
const isNativeCurrency = currency.toLowerCase() === nativeCurrency
|
||||||
|
|
||||||
|
const firstAmount = Object.keys(instanceAddresses).sort((a, b) => Number(a) - Number(b))[0]
|
||||||
|
const isFirstAmount = Number(amount) === Number(firstAmount)
|
||||||
|
|
||||||
|
const denomination = parseUnits(String(amount), decimals)
|
||||||
|
|
||||||
|
const tokenPriceInWei = rootState.price.prices[currency.toLowerCase()]
|
||||||
|
|
||||||
|
return {
|
||||||
|
instanceAddress,
|
||||||
|
currency: currency.toLowerCase(),
|
||||||
|
amount: String(amount),
|
||||||
|
decimals,
|
||||||
|
denomination,
|
||||||
|
isNativeCurrency,
|
||||||
|
isFirstAmount,
|
||||||
|
instanceGasLimit,
|
||||||
|
tokenGasLimit,
|
||||||
|
tokenPriceInWei
|
||||||
|
}
|
||||||
|
},
|
||||||
|
gasPrice: (state, getters, rootState, rootGetters) => {
|
||||||
|
const netId = Number(rootGetters['metamask/netId'])
|
||||||
|
const gasPriceParams = getters.getGasPriceParams
|
||||||
|
|
||||||
|
let gasPrice = BigInt(
|
||||||
|
gasPriceParams.maxFeePerGas
|
||||||
|
? gasPriceParams.maxFeePerGas.toString()
|
||||||
|
: gasPriceParams.gasPrice.toString()
|
||||||
|
)
|
||||||
|
|
||||||
|
// to-do: manually bump gas price for BSC, remove this when we are able to check gasPrice from relayer status
|
||||||
|
if (netId === ChainId.BSC && gasPrice < parseUnits('3.3', 'gwei')) {
|
||||||
|
gasPrice = parseUnits('3.3', 'gwei')
|
||||||
|
}
|
||||||
|
|
||||||
|
return gasPrice
|
||||||
},
|
},
|
||||||
gasPriceInGwei: (state, getters) => {
|
gasPriceInGwei: (state, getters) => {
|
||||||
return fromWei(getters.gasPrice, 'gwei')
|
return formatUnits(getters.gasPrice, 'gwei')
|
||||||
|
},
|
||||||
|
gasLimit: (state, getters) => ({ gas, gasLimit } = {}) => {
|
||||||
|
const { instanceGasLimit } = getters.selectedInstance
|
||||||
|
return BigInt(gas || gasLimit || instanceGasLimit || WITHDRAW_GAS_LIMIT)
|
||||||
|
},
|
||||||
|
refundGasLimit: (state, getters) => {
|
||||||
|
const { isFirstAmount, tokenGasLimit } = getters.selectedInstance
|
||||||
|
return isFirstAmount && tokenGasLimit ? BigInt(tokenGasLimit) : undefined
|
||||||
|
},
|
||||||
|
ethRefund: (state, getters, rootState) => {
|
||||||
|
return rootState.application.ethToReceive || 0
|
||||||
|
},
|
||||||
|
relayerFeePercent: (state, getters, rootState) => {
|
||||||
|
return rootState.relayer.selectedRelayer.tornadoServiceFee
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +129,9 @@ export const mutations = {
|
|||||||
},
|
},
|
||||||
SAVE_WITHDRAWAL_FEE_VIA_RELAYER(state, fee) {
|
SAVE_WITHDRAWAL_FEE_VIA_RELAYER(state, fee) {
|
||||||
state.withdrawalFeeViaRelayer = fee
|
state.withdrawalFeeViaRelayer = fee
|
||||||
|
},
|
||||||
|
SAVE_L1_FEE(state, fee) {
|
||||||
|
state.l1Fee = fee
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +140,20 @@ export const actions = {
|
|||||||
const { pollInterval } = rootGetters['metamask/networkConfig']
|
const { pollInterval } = rootGetters['metamask/networkConfig']
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const gasPriceParams = await getters.oracle.getGasPriceParams()
|
const feeData = await getters.provider.getFeeData()
|
||||||
commit('SAVE_GAS_PARAMS', gasPriceParams)
|
|
||||||
|
const gasParams = feeData.maxFeePerGas
|
||||||
|
? {
|
||||||
|
maxFeePerGas: feeData.maxFeePerGas.toString(),
|
||||||
|
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas
|
||||||
|
? feeData.maxPriorityFeePerGas.toString()
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
gasPrice: feeData.gasPrice ? feeData.gasPrice.toString() : parseUnits('50', 'gwei').toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
commit('SAVE_GAS_PARAMS', gasParams)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('fetchGasPrice', e)
|
console.error('fetchGasPrice', e)
|
||||||
} finally {
|
} finally {
|
||||||
@ -62,32 +164,66 @@ export const actions = {
|
|||||||
const { gasPrices } = rootGetters['metamask/networkConfig']
|
const { gasPrices } = rootGetters['metamask/networkConfig']
|
||||||
commit('SAVE_GAS_PARAMS', { gasPrice: toWei(gasPrices?.fast?.toFixed(9) || 0, 'gwei') })
|
commit('SAVE_GAS_PARAMS', { gasPrice: toWei(gasPrices?.fast?.toFixed(9) || 0, 'gwei') })
|
||||||
},
|
},
|
||||||
async calculateWithdrawalNetworkFee({ getters, commit }, { tx }) {
|
calculateWithdrawalNetworkFee({ getters, commit }, { tx }) {
|
||||||
const withdrawalGas = await getters.oracle.getGas(tx, 'user_withdrawal')
|
const gasPrice = getters.gasPrice
|
||||||
|
const gasLimit = BigInt(tx?.gas || tx?.gasLimit || WITHDRAW_GAS_LIMIT)
|
||||||
|
|
||||||
commit('SAVE_WITHDRAWAL_NETWORK_FEE', toBN(withdrawalGas))
|
const gasCost = gasPrice * gasLimit
|
||||||
|
|
||||||
|
commit('SAVE_WITHDRAWAL_NETWORK_FEE', toBN(gasCost.toString()))
|
||||||
|
|
||||||
|
return gasCost
|
||||||
},
|
},
|
||||||
async calculateWithdrawalFeeViaRelayer({ dispatch, getters, commit, rootGetters, rootState }, { tx }) {
|
async calculateL1Fee({ commit, getters }, { tx }) {
|
||||||
const feePercent = rootState.relayer.selectedRelayer.tornadoServiceFee
|
const oracle = getters.oracle
|
||||||
const { currency, amount } = rootState.application.selectedStatistic
|
|
||||||
const nativeCurrency = rootGetters['metamask/nativeCurrency']
|
|
||||||
const { decimals } = rootGetters['metamask/networkConfig'].tokens[currency]
|
|
||||||
|
|
||||||
await dispatch('calculateWithdrawalNetworkFee', { tx })
|
const l1Fee = await oracle.fetchL1OptimismFee(tx)
|
||||||
if (currency !== nativeCurrency)
|
|
||||||
await dispatch('application/setDefaultEthToReceive', { currency }, { root: true })
|
|
||||||
|
|
||||||
const withdrawalFee = await getters.oracle.calculateWithdrawalFeeViaRelayer(
|
commit('SAVE_L1_FEE', toBN(l1Fee.toString()))
|
||||||
'user_withdrawal',
|
},
|
||||||
tx,
|
async calculateWithdrawalFeeViaRelayer({ dispatch, getters, commit }, { tx }) {
|
||||||
feePercent,
|
const { decimals, denomination, isNativeCurrency, tokenPriceInWei } = getters.selectedInstance
|
||||||
currency.toLowerCase(),
|
|
||||||
amount,
|
|
||||||
decimals,
|
|
||||||
rootState.application.ethToReceive || 0,
|
|
||||||
rootState.price.prices[currency.toLowerCase()]
|
|
||||||
)
|
|
||||||
|
|
||||||
commit('SAVE_WITHDRAWAL_FEE_VIA_RELAYER', toBN(withdrawalFee))
|
const oracle = getters.oracle
|
||||||
|
const gasPrice = getters.gasPrice
|
||||||
|
const gasLimit = getters.gasLimit(tx)
|
||||||
|
const refundGasLimit = getters.refundGasLimit
|
||||||
|
const relayerFeePercent = getters.relayerFeePercent
|
||||||
|
|
||||||
|
await dispatch('calculateL1Fee', { tx })
|
||||||
|
dispatch('calculateWithdrawalNetworkFee', { tx })
|
||||||
|
|
||||||
|
const l1Fee = getters.l1Fee
|
||||||
|
|
||||||
|
if (!isNativeCurrency) {
|
||||||
|
dispatch('application/setDefaultEthToReceive', { gasPrice, refundGasLimit }, { root: true })
|
||||||
|
|
||||||
|
const ethRefund = getters.ethRefund
|
||||||
|
|
||||||
|
const relayerFee = oracle.calculateRelayerFee({
|
||||||
|
gasPrice,
|
||||||
|
gasLimit,
|
||||||
|
l1Fee,
|
||||||
|
denomination,
|
||||||
|
ethRefund,
|
||||||
|
tokenPriceInWei,
|
||||||
|
tokenDecimals: decimals,
|
||||||
|
relayerFeePercent,
|
||||||
|
isEth: isNativeCurrency
|
||||||
|
})
|
||||||
|
|
||||||
|
commit('SAVE_WITHDRAWAL_FEE_VIA_RELAYER', toBN(relayerFee.toString()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const relayerFee = oracle.calculateRelayerFee({
|
||||||
|
gasPrice,
|
||||||
|
gasLimit,
|
||||||
|
l1Fee,
|
||||||
|
denomination,
|
||||||
|
relayerFeePercent
|
||||||
|
})
|
||||||
|
|
||||||
|
commit('SAVE_WITHDRAWAL_FEE_VIA_RELAYER', toBN(relayerFee.toString()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/* eslint-disable import/order */
|
/* eslint-disable import/order */
|
||||||
|
|
||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
import { utils } from 'ethers'
|
import { AbiCoder, concat } from 'ethers'
|
||||||
import { ToastProgrammatic as Toast } from 'buefy'
|
import { ToastProgrammatic as Toast } from 'buefy'
|
||||||
|
|
||||||
import networkConfig from '@/networkConfig'
|
import networkConfig from '@/networkConfig'
|
||||||
@ -14,6 +14,8 @@ import { httpConfig } from '@/constants'
|
|||||||
|
|
||||||
const { numberToHex, toWei, fromWei, toBN, hexToNumber, hexToNumberString } = require('web3-utils')
|
const { numberToHex, toWei, fromWei, toBN, hexToNumber, hexToNumberString } = require('web3-utils')
|
||||||
|
|
||||||
|
const defaultAbiCoder = AbiCoder.defaultAbiCoder()
|
||||||
|
|
||||||
const state = () => {
|
const state = () => {
|
||||||
return {
|
return {
|
||||||
approvalAmount: 'unlimited',
|
approvalAmount: 'unlimited',
|
||||||
@ -391,8 +393,8 @@ const actions = {
|
|||||||
|
|
||||||
if (contact || message) {
|
if (contact || message) {
|
||||||
const value = JSON.stringify([contact, message])
|
const value = JSON.stringify([contact, message])
|
||||||
const tail = utils.defaultAbiCoder.encode(['string'], [value])
|
const tail = defaultAbiCoder.encode(['string'], [value])
|
||||||
dataWithTail = utils.hexConcat([data, tail])
|
dataWithTail = concat([data, tail])
|
||||||
}
|
}
|
||||||
|
|
||||||
const gas = await web3.eth.estimateGas({
|
const gas = await web3.eth.estimateGas({
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
/* eslint-disable import/order */
|
/* eslint-disable import/order */
|
||||||
|
|
||||||
import { utils } from 'ethers'
|
import { AbiCoder, dataLength, dataSlice } from 'ethers'
|
||||||
import uniqBy from 'lodash/uniqBy'
|
import uniqBy from 'lodash/uniqBy'
|
||||||
import chunk from 'lodash/chunk'
|
import chunk from 'lodash/chunk'
|
||||||
|
|
||||||
@ -10,6 +10,8 @@ import { CHUNK_COUNT_PER_BATCH_REQUEST } from '@/constants'
|
|||||||
|
|
||||||
const { toWei, fromWei, toBN } = require('web3-utils')
|
const { toWei, fromWei, toBN } = require('web3-utils')
|
||||||
|
|
||||||
|
const defaultAbiCoder = AbiCoder.defaultAbiCoder()
|
||||||
|
|
||||||
const CACHE_TX = {}
|
const CACHE_TX = {}
|
||||||
const CACHE_BLOCK = {}
|
const CACHE_BLOCK = {}
|
||||||
|
|
||||||
@ -18,15 +20,12 @@ const parseComment = (calldata, govInstance) => {
|
|||||||
if (!calldata || !govInstance) return empty
|
if (!calldata || !govInstance) return empty
|
||||||
|
|
||||||
const methodLength = 4 // length of castDelegatedVote method
|
const methodLength = 4 // length of castDelegatedVote method
|
||||||
const result = utils.defaultAbiCoder.decode(
|
const result = defaultAbiCoder.decode(['address[]', 'uint256', 'bool'], dataSlice(calldata, methodLength))
|
||||||
['address[]', 'uint256', 'bool'],
|
|
||||||
utils.hexDataSlice(calldata, methodLength)
|
|
||||||
)
|
|
||||||
const data = govInstance.methods.castDelegatedVote(...result).encodeABI()
|
const data = govInstance.methods.castDelegatedVote(...result).encodeABI()
|
||||||
const dataLength = utils.hexDataLength(data)
|
const length = dataLength(data)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const str = utils.defaultAbiCoder.decode(['string'], utils.hexDataSlice(calldata, dataLength))
|
const str = defaultAbiCoder.decode(['string'], dataSlice(calldata, length))
|
||||||
const [contact, message] = JSON.parse(str)
|
const [contact, message] = JSON.parse(str)
|
||||||
return { contact, message }
|
return { contact, message }
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -505,82 +505,26 @@ const actions = {
|
|||||||
throw new Error(err.message)
|
throw new Error(err.message)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async addNetwork(_, { netId }) {
|
async addNetwork({ rootGetters }, { netId }) {
|
||||||
const METAMASK_LIST = {
|
const config = networkConfig[`netId${netId}`]
|
||||||
56: {
|
const { url } = rootGetters['settings/getRpc'](netId)
|
||||||
chainId: '0x38',
|
|
||||||
chainName: 'Binance Smart Chain Mainnet',
|
|
||||||
rpcUrls: ['https://bscrpc.com'],
|
|
||||||
nativeCurrency: {
|
|
||||||
name: 'Binance Chain Native Token',
|
|
||||||
symbol: 'BNB',
|
|
||||||
decimals: 18
|
|
||||||
},
|
|
||||||
blockExplorerUrls: ['https://bscscan.com']
|
|
||||||
},
|
|
||||||
10: {
|
|
||||||
chainId: '0xa',
|
|
||||||
chainName: 'Optimism',
|
|
||||||
rpcUrls: ['https://mainnet.optimism.io/'],
|
|
||||||
nativeCurrency: {
|
|
||||||
name: 'Ether',
|
|
||||||
symbol: 'ETH',
|
|
||||||
decimals: 18
|
|
||||||
},
|
|
||||||
blockExplorerUrls: ['https://optimistic.etherscan.io']
|
|
||||||
},
|
|
||||||
100: {
|
|
||||||
chainId: '0x64',
|
|
||||||
chainName: 'Gnosis',
|
|
||||||
rpcUrls: ['https://development.tornadocash.community/rpc/v1'],
|
|
||||||
nativeCurrency: {
|
|
||||||
name: 'xDAI',
|
|
||||||
symbol: 'xDAI',
|
|
||||||
decimals: 18
|
|
||||||
},
|
|
||||||
blockExplorerUrls: ['https://blockscout.com/xdai/mainnet']
|
|
||||||
},
|
|
||||||
137: {
|
|
||||||
chainId: '0x89',
|
|
||||||
chainName: 'Polygon Mainnet',
|
|
||||||
rpcUrls: ['https://polygon-rpc.com'],
|
|
||||||
nativeCurrency: {
|
|
||||||
name: 'MATIC',
|
|
||||||
symbol: 'MATIC',
|
|
||||||
decimals: 18
|
|
||||||
},
|
|
||||||
blockExplorerUrls: ['https://polygonscan.com']
|
|
||||||
},
|
|
||||||
42161: {
|
|
||||||
chainId: '0xA4B1',
|
|
||||||
chainName: 'Arbitrum One',
|
|
||||||
rpcUrls: ['https://arb1.arbitrum.io/rpc'],
|
|
||||||
nativeCurrency: {
|
|
||||||
name: 'Ether',
|
|
||||||
symbol: 'ETH',
|
|
||||||
decimals: 18
|
|
||||||
},
|
|
||||||
blockExplorerUrls: ['https://arbiscan.io']
|
|
||||||
},
|
|
||||||
43114: {
|
|
||||||
chainId: '0xA86A',
|
|
||||||
chainName: 'Avalanche C-Chain',
|
|
||||||
rpcUrls: ['https://api.avax.network/ext/bc/C/rpc'],
|
|
||||||
nativeCurrency: {
|
|
||||||
name: 'Avalanche',
|
|
||||||
symbol: 'AVAX',
|
|
||||||
decimals: 18
|
|
||||||
},
|
|
||||||
blockExplorerUrls: ['https://snowtrace.io']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (METAMASK_LIST[netId]) {
|
|
||||||
await this.$provider.sendRequest({
|
await this.$provider.sendRequest({
|
||||||
method: 'wallet_addEthereumChain',
|
method: 'wallet_addEthereumChain',
|
||||||
params: [METAMASK_LIST[netId]]
|
params: [
|
||||||
})
|
{
|
||||||
|
chainId: `0x${Number(netId).toString(16)}`,
|
||||||
|
chainName: config.networkName,
|
||||||
|
rpcUrls: [url],
|
||||||
|
nativeCurrency: {
|
||||||
|
name: config.networkName,
|
||||||
|
symbol: config.currencyName,
|
||||||
|
decimals: 18
|
||||||
|
},
|
||||||
|
blockExplorerUrls: [config.explorerUrl.tx.replace('/tx', '')]
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
},
|
},
|
||||||
async checkNetworkVersion() {
|
async checkNetworkVersion() {
|
||||||
try {
|
try {
|
||||||
|
@ -18,8 +18,25 @@ export const getters = {
|
|||||||
priceOracle: (state, getters, rootState, rootGetters) => {
|
priceOracle: (state, getters, rootState, rootGetters) => {
|
||||||
const netId = Number(rootGetters['metamask/netId'])
|
const netId = Number(rootGetters['metamask/netId'])
|
||||||
const { url: rpcUrl } = rootState.settings[`netId${netId}`].rpc
|
const { url: rpcUrl } = rootState.settings[`netId${netId}`].rpc
|
||||||
|
const config = rootGetters['metamask/networkConfig']
|
||||||
|
|
||||||
return new TokenPriceOracle(rpcUrl)
|
return new TokenPriceOracle(netId, rpcUrl, config)
|
||||||
|
},
|
||||||
|
tokens: (state, getters, rootStater, rootGetters) => {
|
||||||
|
const config = rootGetters['metamask/networkConfig']
|
||||||
|
const { 'torn.contract.tornadocash.eth': tornContract, tokens } = config
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
tokenAddress: tornContract,
|
||||||
|
symbol: 'TORN',
|
||||||
|
decimals: 18
|
||||||
|
},
|
||||||
|
...Object.values(tokens)
|
||||||
|
.map(({ tokenAddress, symbol, decimals }) =>
|
||||||
|
tokenAddress ? { tokenAddress, symbol, decimals } : undefined
|
||||||
|
)
|
||||||
|
.filter((t) => t)
|
||||||
|
]
|
||||||
},
|
},
|
||||||
tokenRate: (state, getters, rootState) => {
|
tokenRate: (state, getters, rootState) => {
|
||||||
return state.prices[rootState.application.selectedStatistic.currency]
|
return state.prices[rootState.application.selectedStatistic.currency]
|
||||||
@ -49,8 +66,10 @@ export const actions = {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tokens = getters.tokens
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const prices = await getters.priceOracle.fetchPrices()
|
const prices = await getters.priceOracle.fetchPrices(tokens)
|
||||||
console.log('prices', prices)
|
console.log('prices', prices)
|
||||||
commit('SAVE_TOKEN_PRICES', prices)
|
commit('SAVE_TOKEN_PRICES', prices)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user