12 Commits

11 changed files with 95 additions and 429 deletions

View File

@@ -1,6 +1,6 @@
NET_ID=1 NET_ID=1
HTTP_RPC_URL=https://api.securerpc.com/v1 HTTP_RPC_URL=https://api.securerpc.com/v1
WS_RPC_URL=wss://mainnet.infura.io/ws/v3/ # WS_RPC_URL=wss://mainnet.infura.io/ws/v3/
# ORACLE_RPC_URL should always point to the mainnet # ORACLE_RPC_URL should always point to the mainnet
ORACLE_RPC_URL=https://api.securerpc.com/v1 ORACLE_RPC_URL=https://api.securerpc.com/v1
REDIS_URL=redis://127.0.0.1:6379 REDIS_URL=redis://127.0.0.1:6379
@@ -12,8 +12,8 @@ APP_PORT=8000
# without 0x prefix # without 0x prefix
PRIVATE_KEY= PRIVATE_KEY=
# 0.05 means 0.05% # 0.4 means 0.4%
RELAYER_FEE=0.4 REGULAR_TORNADO_WITHDRAW_FEE=0.4
MINING_SERVICE_FEE=0.05 MINING_SERVICE_FEE=0.05
REWARD_ACCOUNT= REWARD_ACCOUNT=
CONFIRMATIONS=4 CONFIRMATIONS=4
@@ -21,4 +21,4 @@ CONFIRMATIONS=4
# in GWEI # in GWEI
MAX_GAS_PRICE=1000 MAX_GAS_PRICE=1000
BASE_FEE_RESERVE_PERCENTAGE=25 BASE_FEE_RESERVE_PERCENTAGE=25
AGGREGATOR=0xE8F47A78A6D52D317D0D2FFFac56739fE14D1b49 AGGREGATOR=0x8cb1436F64a3c33aD17bb42F94e255c4c0E871b2

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ node_modules/
kovan.* kovan.*
dump.rdb dump.rdb
.idea .idea
yarn-error.log

View File

@@ -1,4 +1,4 @@
# Relayer for Tornado Cash [![Build Status](https://github.com/tornadocash/relayer/workflows/build/badge.svg)](https://github.com/tornadocash/relayer/actions) ![Static Badge](https://img.shields.io/badge/version-5.1.0-blue?logo=docker) # Relayer for Tornado Cash [![Build Status](https://github.com/tornadocash/relayer/workflows/build/badge.svg)](https://github.com/tornadocash/relayer/actions) [![Docker Image Version (latest semver)](https://img.shields.io/docker/v/tornadocash/relayer?logo=docker&logoColor=%23FFFFFF&sort=semver)](https://hub.docker.com/repository/docker/tornadocash/relayer)
__*Tornado Cash was sanctioned by the US Treasury on 08/08/2022, this makes it illegal for US citizens to interact with Tornado Cash and all of it's associated deployed smart contracts. Please understand the laws where you live and take all necessary steps to protect and anonymize yourself.__ __*Tornado Cash was sanctioned by the US Treasury on 08/08/2022, this makes it illegal for US citizens to interact with Tornado Cash and all of it's associated deployed smart contracts. Please understand the laws where you live and take all necessary steps to protect and anonymize yourself.__
@@ -33,7 +33,7 @@ _* Warning: Failure to configure SSH as the first UFW rule, will lock you out of
__DEPLOYMENT__ __DEPLOYMENT__
1. Clone the repository and enter the directory 1. Clone the repository and enter the directory
- `git clone https://git.tornado.ws/tornadocash/classic-relayer -b mainnet-v5 && cd classic-relayer` - `git clone https://git.tornado.ws/tornadocash/classic-relayer -b mainnet-v4 && cd classic-relayer`
2. Clone the example environment file `.env.example` to configure for the preferred network - `cp .env.example .env` , then fill `.env` file. 2. Clone the example environment file `.env.example` to configure for the preferred network - `cp .env.example .env` , then fill `.env` file.
- Set `PRIVATE_KEY` for your relayer address (remove the 0x from your private key) - Set `PRIVATE_KEY` for your relayer address (remove the 0x from your private key)
- Set `VIRTUAL_HOST` and `LETSENCRYPT_HOST` to your domain address - Set `VIRTUAL_HOST` and `LETSENCRYPT_HOST` to your domain address
@@ -63,13 +63,12 @@ __NGINX REVERSE PROXY__
## Run locally ## Run locally
1. `npm i -g yarn` (if yarn not installed in your system) 1. `npm i`
2. `yarn` 2. `cp .env.example .env`
3. `cp .env.mainnet.example .env` 3. Modify `.env` as needed
4. Modify `.env` as needed 4. `npm run start`
5. `yarn start` 5. Go to `http://127.0.0.1:8000`
6. Go to `http://127.0.0.1:8000` 6. In order to execute withdraw request, you can run following command
7. In order to execute withdraw request, you can run following command
```bash ```bash
curl -X POST -H 'content-type:application/json' --data '<input data>' http://127.0.0.1:8000/relay curl -X POST -H 'content-type:application/json' --data '<input data>' http://127.0.0.1:8000/relay

View File

@@ -45,15 +45,14 @@ services:
- nginx - nginx
- dockergen - dockergen
# ---------------------- ETH Mainnet ----------------------- # # ---------------------- ETH ----------------------- #
eth-server: eth-server:
build: . build: .
image: tornadorelayer:mainnet image: tornadocash/relayer:mainnet-v4
profiles: ['eth']
restart: always restart: always
command: server command: server
env_file: .env.eth env_file: .env
environment: environment:
NET_ID: 1 NET_ID: 1
REDIS_URL: redis://redis/0 REDIS_URL: redis://redis/0
@@ -61,58 +60,52 @@ services:
depends_on: [redis] depends_on: [redis]
eth-treeWatcher: eth-treeWatcher:
image: tornadorelayer:mainnet image: tornadocash/relayer:mainnet-v4
profiles: ['eth']
restart: always restart: always
command: treeWatcher command: treeWatcher
env_file: .env.eth env_file: .env
environment: environment:
NET_ID: 1 NET_ID: 1
REDIS_URL: redis://redis/0 REDIS_URL: redis://redis/0
depends_on: [redis, eth-server] depends_on: [redis, eth-server]
eth-priceWatcher: eth-priceWatcher:
image: tornadorelayer:mainnet image: tornadocash/relayer:mainnet-v4
profiles: ['eth']
restart: always restart: always
command: priceWatcher command: priceWatcher
env_file: .env.eth env_file: .env
environment: environment:
NET_ID: 1 NET_ID: 1
REDIS_URL: redis://redis/0 REDIS_URL: redis://redis/0
depends_on: [redis, eth-server] depends_on: [redis, eth-server]
eth-healthWatcher: eth-healthWatcher:
image: tornadorelayer:mainnet image: tornadocash/relayer:mainnet-v4
profiles: ['eth']
restart: always restart: always
command: healthWatcher command: healthWatcher
env_file: .env.eth env_file: .env
environment: environment:
NET_ID: 1 NET_ID: 1
REDIS_URL: redis://redis/0 REDIS_URL: redis://redis/0
depends_on: [redis, eth-server] depends_on: [redis, eth-server]
eth-worker1: eth-worker1:
image: tornadorelayer:mainnet image: tornadocash/relayer:mainnet-v4
profiles: ['eth']
restart: always restart: always
command: worker command: worker
env_file: .env.eth env_file: .env
environment: environment:
NET_ID: 1 NET_ID: 1
REDIS_URL: redis://redis/0 REDIS_URL: redis://redis/0
depends_on: [redis, eth-server] depends_on: [redis, eth-server]
# # This is additional worker for ethereum mainnet # worker2:
# # So you can process transactions from multiple addresses, but before it you need to set up those addresses as workers # image: tornadocash/relayer:mainnet-v4
# eth-worker2:
# image: tornadorelayer:mainnet
# profiles: [ 'eth' ]
# restart: always # restart: always
# command: worker # command: worker
# env_file: .env2.eth # env_file: .env
# environment: # environment:
# PRIVATE_KEY: qwe
# REDIS_URL: redis://redis/0 # REDIS_URL: redis://redis/0
# # this container will proxy *.onion domain to the server container # # this container will proxy *.onion domain to the server container
@@ -131,327 +124,6 @@ services:
# ... # ...
# -----END RSA PRIVATE KEY----- # -----END RSA PRIVATE KEY-----
# # auto update docker containers when new image is pushed to docker hub (be careful with that)
# watchtower:
# image: v2tec/watchtower
# restart: always
# volumes:
# - /var/run/docker.sock:/var/run/docker.sock
# # this container will send Telegram notifications when other containers are stopped/restarted
# # it's best to run this container on some other instance, otherwise it can't notify if the whole instance goes down
# notifier:
# image: poma/docker-telegram-notifier
# restart: always
# volumes:
# - /var/run/docker.sock:/var/run/docker.sock:ro
# environment:
# # How to create bot: https://core.telegram.org/bots#3-how-do-i-create-a-bot
# # How to get chat id: https://stackoverflow.com/questions/32423837/telegram-bot-how-to-get-a-group-chat-id/32572159#32572159
# TELEGRAM_NOTIFIER_BOT_TOKEN: ...
# TELEGRAM_NOTIFIER_CHAT_ID: ...
# # this container will send Telegram notifications if specified address doesn't have enough funds
# monitor_mainnet:
# image: peppersec/monitor_eth
# restart: always
# environment:
# TELEGRAM_NOTIFIER_BOT_TOKEN: ...
# TELEGRAM_NOTIFIER_CHAT_ID: ...
# ADDRESS: '0x0000000000000000000000000000000000000000'
# THRESHOLD: 0.5 # ETH
# RPC_URL: https://mainnet.infura.io
# BLOCK_EXPLORER: etherscan.io
# -------------------------------------------------- #
# ---------------------- BSC (Binance Smart Chain) ----------------------- #
bsc-server:
image: tornadorelayer:sidechain
profiles: ['bsc']
restart: always
command: server
env_file: .env.bsc
environment:
NET_ID: 56
REDIS_URL: redis://redis/1
nginx_proxy_read_timeout: 600
depends_on: [redis]
bsc-healthWatcher:
image: tornadorelayer:sidechain
profiles: ['bsc']
restart: always
command: healthWatcher
env_file: .env.bsc
environment:
NET_ID: 56
REDIS_URL: redis://redis/1
depends_on: [redis, bsc-server]
bsc-worker1:
image: tornadorelayer:sidechain
profiles: ['bsc']
restart: always
command: worker
env_file: .env.bsc
environment:
NET_ID: 56
REDIS_URL: redis://redis/1
depends_on: [redis, bsc-server]
# -------------------------------------------------- #
# ---------------------- Polygon (MATIC) --------------------- #
polygon-server:
image: tornadorelayer:sidechain
profiles: ['polygon']
restart: always
command: server
env_file: .env.polygon
environment:
NET_ID: 137
REDIS_URL: redis://redis/2
nginx_proxy_read_timeout: 600
depends_on: [redis]
polygon-healthWatcher:
image: tornadorelayer:sidechain
profiles: ['polygon']
restart: always
command: healthWatcher
env_file: .env.polygon
environment:
NET_ID: 137
REDIS_URL: redis://redis/2
depends_on: [redis, polygon-server]
polygon-worker1:
image: tornadorelayer:sidechain
profiles: ['polygon']
restart: always
command: worker
env_file: .env.polygon
environment:
NET_ID: 137
REDIS_URL: redis://redis/2
depends_on: [redis, polygon-server]
# -------------------------------------------------- #
# ---------------------- Gnosis (XDAI) ---------------------- #
gnosis-server:
image: tornadorelayer:sidechain
profiles: ['gnosis']
restart: always
command: server
env_file: .env.gnosis
environment:
NET_ID: 100
REDIS_URL: redis://redis/3
nginx_proxy_read_timeout: 600
depends_on: [redis]
gnosis-healthWatcher:
image: tornadorelayer:sidechain
profiles: ['gnosis']
restart: always
command: healthWatcher
env_file: .env.gnosis
environment:
NET_ID: 100
REDIS_URL: redis://redis/3
depends_on: [redis, gnosis-server]
gnosis-worker1:
image: tornadorelayer:sidechain
profiles: ['gnosis']
restart: always
command: worker
env_file: .env.gnosis
environment:
NET_ID: 100
REDIS_URL: redis://redis/3
depends_on: [redis, gnosis-server]
# -------------------------------------------------- #
# ---------------------- AVAX ---------------------- #
avax-server:
image: tornadorelayer:sidechain
profiles: ['avax']
restart: always
command: server
env_file: .env.avax
environment:
NET_ID: 43114
REDIS_URL: redis://redis/4
nginx_proxy_read_timeout: 600
depends_on: [redis]
avax-healthWatcher:
image: tornadorelayer:sidechain
profiles: ['avax']
restart: always
command: healthWatcher
env_file: .env.avax
environment:
NET_ID: 43114
REDIS_URL: redis://redis/4
depends_on: [redis, avax-server]
avax-worker1:
image: tornadorelayer:sidechain
profiles: ['avax']
restart: always
command: worker
env_file: .env.avax
environment:
NET_ID: 43114
REDIS_URL: redis://redis/4
depends_on: [redis, avax-server]
# -------------------------------------------------- #
# ---------------------- OP ------------------------ #
op-server:
image: tornadorelayer:sidechain
profiles: ['op']
restart: always
command: server
env_file: .env.op
environment:
NET_ID: 10
REDIS_URL: redis://redis/5
nginx_proxy_read_timeout: 600
depends_on: [redis]
op-healthWatcher:
image: tornadorelayer:sidechain
profiles: ['op']
restart: always
command: healthWatcher
env_file: .env.op
environment:
NET_ID: 10
REDIS_URL: redis://redis/5
depends_on: [redis, op-server]
op-worker1:
image: tornadorelayer:sidechain
profiles: ['op']
restart: always
command: worker
env_file: .env.op
environment:
NET_ID: 10
REDIS_URL: redis://redis/5
depends_on: [redis, op-server]
# -------------------------------------------------- #
# ---------------------- Arbitrum ----------------------- #
arb-server:
image: tornadorelayer:sidechain
profiles: ['arb']
restart: always
command: server
env_file: .env.arb
environment:
NET_ID: 42161
REDIS_URL: redis://redis/6
nginx_proxy_read_timeout: 600
depends_on: [redis]
arb-healthWatcher:
image: tornadorelayer:sidechain
profiles: ['arb']
restart: always
command: healthWatcher
env_file: .env.arb
environment:
NET_ID: 42161
REDIS_URL: redis://redis/6
depends_on: [redis, arb-server]
arb-worker1:
image: tornadorelayer:sidechain
profiles: ['arb']
restart: always
command: worker
env_file: .env.arb
environment:
NET_ID: 42161
REDIS_URL: redis://redis/6
depends_on: [redis, arb-server]
# -------------------------------------------------- #
# ---------------------- Goerli (Ethereum Testnet) ---------------------- #
goerli-server:
image: tornadorelayer:mainnet
profiles: ['geth']
restart: always
command: server
env_file: .env.goerli
environment:
NET_ID: 5
REDIS_URL: redis://redis/7
nginx_proxy_read_timeout: 600
depends_on: [redis]
goerli-treeWatcher:
image: tornadorelayer:mainnet
profiles: ['goerli']
restart: always
command: treeWatcher
env_file: .env.goerli
environment:
NET_ID: 5
REDIS_URL: redis://redis/7
depends_on: [redis, goerli-server]
goerli-priceWatcher:
image: tornadorelayer:mainnet
profiles: ['goerli']
restart: always
command: priceWatcher
env_file: .env.goerli
environment:
NET_ID: 5
REDIS_URL: redis://redis/7
depends_on: [redis, goerli-server]
goerli-healthWatcher:
image: tornadorelayer:mainnet
profiles: ['goerli']
restart: always
command: healthWatcher
env_file: .env.goerli
environment:
NET_ID: 5
REDIS_URL: redis://redis/7
depends_on: [redis, goerli-server]
goerli-worker1:
image: tornadorelayer:mainnet
profiles: ['goerli']
restart: always
command: worker
env_file: .env.goerli
environment:
NET_ID: 5
REDIS_URL: redis://redis/7
depends_on: [redis, goerli-server]
# -------------------------------------------------- #
volumes: volumes:
conf: conf:
vhost: vhost:

View File

@@ -1,7 +1,7 @@
{ {
"name": "relay", "name": "relay",
"version": "5.2.0", "version": "4.1.6",
"description": "Relayer for Tornado.cash privacy solution.", "description": "Relayer for Tornado.cash privacy solution. https://tornado.cash",
"scripts": { "scripts": {
"server": "node src/server.js", "server": "node src/server.js",
"worker": "node src/worker", "worker": "node src/worker",
@@ -13,17 +13,17 @@
"prettier:fix": "npx prettier --write . --config .prettierrc", "prettier:fix": "npx prettier --write . --config .prettierrc",
"lint": "yarn eslint && yarn prettier:check", "lint": "yarn eslint && yarn prettier:check",
"test": "mocha", "test": "mocha",
"build": "docker build -t tornadocash/relayer:mainnet-v5 .", "build": "docker build -t tornadocash/relayer:mainnet-v4 .",
"start": "docker-compose up -d redis && concurrently \"yarn server\" \"yarn priceWatcher\" \"yarn treeWatcher\" \"yarn worker\" \"yarn healthWatcher\"" "start": "docker-compose up -d redis && concurrently \"yarn server\" \"yarn priceWatcher\" \"yarn treeWatcher\" \"yarn worker\" \"yarn healthWatcher\""
}, },
"author": "Tornado Cash team", "author": "tornado.cash",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tornado/anonymity-mining": "^2.1.5", "@tornado/anonymity-mining": "^2.1.5",
"@tornado/circomlib": "^0.0.21", "@tornado/circomlib": "^0.0.21",
"@tornado/fixed-merkle-tree": "0.4.0", "@tornado/fixed-merkle-tree": "^0.4",
"@tornado/tornado-config": "^1", "@tornado/tornado-config": "^1",
"@tornado/tornado-oracles": "^3.3.0", "@tornado/tornado-oracles": "1.2.2",
"@tornado/tx-manager": "^0.4.9", "@tornado/tx-manager": "^0.4.9",
"ajv": "^6.12.5", "ajv": "^6.12.5",
"async-mutex": "^0.2.4", "async-mutex": "^0.2.4",

View File

@@ -14,7 +14,8 @@ module.exports = {
instances: tornConfig.instances, instances: tornConfig.instances,
torn: tornConfig, torn: tornConfig,
port: process.env.APP_PORT || 8000, port: process.env.APP_PORT || 8000,
tornadoServiceFee: Number(process.env.RELAYER_FEE), tornadoServiceFee: Number(process.env.REGULAR_TORNADO_WITHDRAW_FEE),
miningServiceFee: Number(process.env.MINING_SERVICE_FEE),
rewardAccount: process.env.REWARD_ACCOUNT, rewardAccount: process.env.REWARD_ACCOUNT,
governanceAddress: '0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce', governanceAddress: '0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce',
tornadoGoerliProxy: '0x454d870a72e29d5E5697f635128D18077BD04C60', tornadoGoerliProxy: '0x454d870a72e29d5E5697f635128D18077BD04C60',

View File

@@ -25,7 +25,7 @@ async function status(req, res) {
function index(req, res) { function index(req, res) {
res.send( res.send(
'This is <a href=https://tornado.ws>Tornado Cash</a> Relayer service. Check the <a href=/v1/status>/status</a> for settings', 'This is <a href=https://tornado.cash>tornado.cash</a> Relayer service. Check the <a href=/v1/status>/status</a> for settings',
) )
} }

View File

@@ -8,10 +8,6 @@ const priceOracle = new TokenPriceOracle(oracleRpcUrl)
async function main() { async function main() {
try { try {
const ethPrices = await priceOracle.fetchPrices() const ethPrices = await priceOracle.fetchPrices()
if (!Object.values(ethPrices).length) {
throw new RelayerError('Can`t update prices', 1)
}
await redis.hmset('prices', ethPrices) await redis.hmset('prices', ethPrices)
console.log('Wrote following prices to redis', ethPrices) console.log('Wrote following prices to redis', ethPrices)
} catch (e) { } catch (e) {

View File

@@ -1,6 +1,6 @@
const { instances, netId } = require('./config') const { instances, netId } = require('./config')
const { poseidon } = require('@tornado/circomlib') const { poseidon } = require('@tornado/circomlib')
const { toBN, toChecksumAddress, BN, fromWei, isAddress, toWei, toHex } = require('web3-utils') const { toBN, toChecksumAddress, BN, fromWei, isAddress, toWei } = require('web3-utils')
const addressMap = new Map() const addressMap = new Map()
const instance = instances[netId] const instance = instances[netId]
@@ -134,7 +134,6 @@ module.exports = {
toChecksumAddress, toChecksumAddress,
fromWei, fromWei,
toWei, toWei,
toHex,
BN, BN,
isAddress, isAddress,
RelayerError, RelayerError,

View File

@@ -1,7 +1,8 @@
const fs = require('fs') const fs = require('fs')
const MerkleTree = require('@tornado/fixed-merkle-tree') const MerkleTree = require('@tornado/fixed-merkle-tree')
const { TornadoFeeOracleV4, bump } = require('@tornado/tornado-oracles')
const { Utils, Controller } = require('@tornado/anonymity-mining') const { Utils, Controller } = require('@tornado/anonymity-mining')
const { TornadoFeeOracleV5 } = require('@tornado/tornado-oracles')
const swapABI = require('../abis/swap.abi.json') const swapABI = require('../abis/swap.abi.json')
const miningABI = require('../abis/mining.abi.json') const miningABI = require('../abis/mining.abi.json')
const tornadoABI = require('../abis/tornadoABI.json') const tornadoABI = require('../abis/tornadoABI.json')
@@ -10,11 +11,10 @@ const { queue } = require('./queue')
const { const {
poseidonHash2, poseidonHash2,
getInstance, getInstance,
isAddress,
sleep, sleep,
toBN, toBN,
fromWei,
toChecksumAddress, toChecksumAddress,
isAddress,
RelayerError, RelayerError,
logRelayerError, logRelayerError,
} = require('./utils') } = require('./utils')
@@ -30,6 +30,7 @@ const {
miningServiceFee, miningServiceFee,
tornadoServiceFee, tornadoServiceFee,
tornadoGoerliProxy, tornadoGoerliProxy,
rewardAccount,
} = require('./config') } = require('./config')
const resolver = require('./modules/resolver') const resolver = require('./modules/resolver')
const { TxManager } = require('@tornado/tx-manager') const { TxManager } = require('@tornado/tx-manager')
@@ -44,7 +45,7 @@ let txManager
let controller let controller
let swap let swap
let minerContract let minerContract
const feeOracle = new TornadoFeeOracleV5(netId, oracleRpcUrl) const feeOracle = new TornadoFeeOracleV4(netId, oracleRpcUrl)
async function fetchTree() { async function fetchTree() {
const elements = await redis.get('tree:elements') const elements = await redis.get('tree:elements')
@@ -91,7 +92,6 @@ async function start() {
BASE_FEE_RESERVE_PERCENTAGE: baseFeeReserve, BASE_FEE_RESERVE_PERCENTAGE: baseFeeReserve,
}, },
}) })
swap = new web3.eth.Contract(swapABI, await resolver.resolve(torn.rewardSwap.address)) swap = new web3.eth.Contract(swapABI, await resolver.resolve(torn.rewardSwap.address))
minerContract = new web3.eth.Contract(miningABI, await resolver.resolve(torn.miningV2.address)) minerContract = new web3.eth.Contract(miningABI, await resolver.resolve(torn.miningV2.address))
redisSubscribe.subscribe('treeUpdate', fetchTree) redisSubscribe.subscribe('treeUpdate', fetchTree)
@@ -110,38 +110,29 @@ async function start() {
} }
} }
function checkFee({ data }, gasInfo) { function checkFee({ data }) {
if (data.type === jobType.TORNADO_WITHDRAW) { if (data.type === jobType.TORNADO_WITHDRAW) {
return checkTornadoFee(data, gasInfo) return checkTornadoFee(data)
} }
return checkMiningFee(data) return checkMiningFee(data)
} }
async function checkTornadoFee({ args, contract }, tx) { async function checkTornadoFee({ args, contract }) {
const { currency, amount, decimals } = getInstance(contract) const { currency, amount, decimals } = getInstance(contract)
const [userProvidedFee, refund] = [args[4], args[5]].map(toBN) const [userProvidedFee, refund] = [args[4], args[5]]
const { gasLimit, gasPrice } = tx
const ethPrice = await redis.hget('prices', currency) const ethPrice = await redis.hget('prices', currency)
const totalWithdrawalFee = await feeOracle.calculateWithdrawalFeeViaRelayer({ const relayerEstimatedFee = await feeOracle.calculateWithdrawalFeeViaRelayer(
tx, 'relayer_withdrawal_check_v4',
txType: 'relayer_withdrawal', {},
amount, tornadoServiceFee,
currency, currency,
amount,
decimals, decimals,
refundInEth: refund.toString(), refund,
predefinedGasLimit: gasLimit, ethPrice,
predefinedGasPrice: gasPrice,
tokenPriceInEth: ethPrice,
relayerFeePercent: tornadoServiceFee,
})
console.log(
'user-provided fee, desired fee',
fromWei(userProvidedFee.toString()),
fromWei(toBN(totalWithdrawalFee).toString()),
) )
if (userProvidedFee.lt(toBN(totalWithdrawalFee))) { if (toBN(relayerEstimatedFee).gt(toBN(userProvidedFee))) {
throw new RelayerError( throw new RelayerError(
'Provided fee is not enough. Probably it is a Gas Price spike, try to resubmit.', 'Provided fee is not enough. Probably it is a Gas Price spike, try to resubmit.',
0, 0,
@@ -150,7 +141,7 @@ async function checkTornadoFee({ args, contract }, tx) {
} }
async function checkMiningFee({ args }) { async function checkMiningFee({ args }) {
const gasPrice = await feeOracle.getGasPrice() const gasPrice = await feeOracle.getGasPriceInHex()
const ethPrice = await redis.hget('prices', 'torn') const ethPrice = await redis.hget('prices', 'torn')
const isMiningReward = currentJob.data.type === jobType.MINING_REWARD const isMiningReward = currentJob.data.type === jobType.MINING_REWARD
const providedFee = isMiningReward ? toBN(args.fee) : toBN(args.extData.fee) const providedFee = isMiningReward ? toBN(args.fee) : toBN(args.extData.fee)
@@ -205,7 +196,6 @@ async function checkRecipient({ data }) {
// Checks only for default withdrawals // Checks only for default withdrawals
if (data.type !== jobType.TORNADO_WITHDRAW) return if (data.type !== jobType.TORNADO_WITHDRAW) return
console.log(data.args)
const recipient = data.args[2] const recipient = data.args[2]
if (!isAddress(recipient)) throw new Error('Recipient address is invalid') if (!isAddress(recipient)) throw new Error('Recipient address is invalid')
@@ -226,16 +216,15 @@ async function getTxObject({ data }) {
const incompleteTx = { const incompleteTx = {
value: data.args[5], value: data.args[5],
from: txManager.address, // Required, because without it relayerRegistry.burn will fail, because msg.sender is not relayer
to: contract._address, to: contract._address,
data: calldata, data: calldata,
} }
const { gasLimit, gasPrice } = await feeOracle.getGasParams({ const [gasPrice, gasLimit] = await Promise.all([
tx: incompleteTx, feeOracle.getGasPrice('relayer_withdrawal'),
txType: 'relayer_withdrawal', feeOracle.getGasLimit(incompleteTx, 'relayer_withdrawal'),
}) ])
return { ...incompleteTx, gasLimit, gasPrice } return Object.assign({ gasLimit, gasPrice }, incompleteTx)
} else { } else {
const method = data.type === jobType.MINING_REWARD ? 'reward' : 'withdraw' const method = data.type === jobType.MINING_REWARD ? 'reward' : 'withdraw'
const calldata = minerContract.methods[method](data.proof, data.args).encodeABI() const calldata = minerContract.methods[method](data.proof, data.args).encodeABI()
@@ -277,11 +266,20 @@ async function processJob(job) {
} }
} }
async function checkRevert(tx) {
try {
await web3.eth.estimateGas(Object.assign({ from: rewardAccount }, tx))
} catch (e) {
throw new Error('Estimation error: transaction will possibly be reverted')
}
}
async function submitTx(job, retry = 0) { async function submitTx(job, retry = 0) {
await checkRecipient(job) await checkRecipient(job)
const rawTx = await getTxObject(job) await checkFee(job)
await checkFee(job, rawTx) const tx = await getTxObject(job)
currentTx = await txManager.createTx(rawTx) await checkRevert(tx)
currentTx = await txManager.createTx(tx)
if (job.data.type !== jobType.TORNADO_WITHDRAW) { if (job.data.type !== jobType.TORNADO_WITHDRAW) {
await fetchTree() await fetchTree()

View File

@@ -10,17 +10,17 @@
"@babel/highlight" "^7.22.13" "@babel/highlight" "^7.22.13"
chalk "^2.4.2" chalk "^2.4.2"
"@babel/helper-validator-identifier@^7.22.20": "@babel/helper-validator-identifier@^7.22.5":
version "7.22.20" version "7.22.19"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.19.tgz#2f34ab1e445f5b95e2e6edfe50ea2449e610583a"
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== integrity sha512-Tinq7ybnEPFFXhlYOYFiSjespWQk0dq2dRNAiMdRTOYQzEGqnnNyrTxPYHP5r6wGjlF1rFgABdDV0g8EwD6Qbg==
"@babel/highlight@^7.22.13": "@babel/highlight@^7.22.13":
version "7.22.20" version "7.22.13"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.13.tgz#9cda839e5d3be9ca9e8c26b6dd69e7548f0cbf16"
integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== integrity sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==
dependencies: dependencies:
"@babel/helper-validator-identifier" "^7.22.20" "@babel/helper-validator-identifier" "^7.22.5"
chalk "^2.4.2" chalk "^2.4.2"
js-tokens "^4.0.0" js-tokens "^4.0.0"
@@ -534,7 +534,7 @@
"@tornado/circomlib" "^0.0.21" "@tornado/circomlib" "^0.0.21"
"@tornado/snarkjs" "^0.1.20" "@tornado/snarkjs" "^0.1.20"
"@tornado/fixed-merkle-tree@0.4.0": "@tornado/fixed-merkle-tree@^0.4":
version "0.4.0" version "0.4.0"
resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ffixed-merkle-tree/-/0.4.0/fixed-merkle-tree-0.4.0.tgz#2cc4e02e69fd5d91cb18d97ad35e480bb29f8bfa" resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ffixed-merkle-tree/-/0.4.0/fixed-merkle-tree-0.4.0.tgz#2cc4e02e69fd5d91cb18d97ad35e480bb29f8bfa"
integrity sha512-FNO0UGacuw8gB0mY4bekfWamUb/YD7i7q4D5Jcbo+LnNdGnrJv6LK7aWO21dp54z3qAQum0es4Y4kcIw5oVIHg== integrity sha512-FNO0UGacuw8gB0mY4bekfWamUb/YD7i7q4D5Jcbo+LnNdGnrJv6LK7aWO21dp54z3qAQum0es4Y4kcIw5oVIHg==
@@ -581,10 +581,10 @@
resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ftornado-config/-/2.0.0/tornado-config-2.0.0.tgz#52bbc179ecb2385f71b4d56e060b68e7dd6fb8b4" resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ftornado-config/-/2.0.0/tornado-config-2.0.0.tgz#52bbc179ecb2385f71b4d56e060b68e7dd6fb8b4"
integrity sha512-7EkpWNfEm34VEOrbLnPpvd/aUJYnA1L+6/qx2fZ/AfmuJFkjSZ18Z4jvVGNY7ktKIhTu3/Tbze+9l3eNueCNIA== integrity sha512-7EkpWNfEm34VEOrbLnPpvd/aUJYnA1L+6/qx2fZ/AfmuJFkjSZ18Z4jvVGNY7ktKIhTu3/Tbze+9l3eNueCNIA==
"@tornado/tornado-oracles@^3.3.0": "@tornado/tornado-oracles@1.2.2":
version "3.3.0" version "1.2.2"
resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ftornado-oracles/-/3.3.0/tornado-oracles-3.3.0.tgz#6358f896f399904ed8deb9b8f4253e77732bd227" resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ftornado-oracles/-/1.2.2/tornado-oracles-1.2.2.tgz#454be0f34b27aa659b2d590dfbcd721246545a16"
integrity sha512-OBJ+TmygY6VMcYJCPxSOAzPDZpmF4WhRVhjgTEhqw+hg70WW9L4b3DC1B1P/4Gmar2lzi6BnTI4ckkDy/xsHQQ== integrity sha512-JJoUAkQLV7bVrU2YMFt9d+TB5BovrvQubg8n0V0ZGcTDv/bz2H3EWwStz6Tvl+wUAnPuNnEeS934vkOvgFtEew==
dependencies: dependencies:
"@tornado/gas-price-oracle" "^0.5.3" "@tornado/gas-price-oracle" "^0.5.3"
"@tornado/tornado-config" "^2.0.0" "@tornado/tornado-config" "^2.0.0"
@@ -636,9 +636,9 @@
"@types/node" "*" "@types/node" "*"
"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": "@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1":
version "5.1.2" version "5.1.1"
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.2.tgz#162f5238c46f4bcbac07a98561724eca1fcf0c5e" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682"
integrity sha512-dkpZu0szUtn9UXTmw+e0AJFd4D2XAxDnsCLdc05SfqpqzPEBft8eQr8uaFitfo/dUUOZERaLec2hHMG87A4Dxg== integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
@@ -653,9 +653,9 @@
"@types/responselike" "^1.0.0" "@types/responselike" "^1.0.0"
"@types/http-cache-semantics@*": "@types/http-cache-semantics@*":
version "4.0.2" version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.2.tgz#abe102d06ccda1efdf0ed98c10ccf7f36a785a41" resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812"
integrity sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw== integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==
"@types/keyv@^3.1.4": "@types/keyv@^3.1.4":
version "3.1.4" version "3.1.4"
@@ -665,9 +665,9 @@
"@types/node" "*" "@types/node" "*"
"@types/node@*", "@types/node@^20.5.1": "@types/node@*", "@types/node@^20.5.1":
version "20.6.2" version "20.6.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.2.tgz#a065925409f59657022e9063275cd0b9bd7e1b12" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.0.tgz#9d7daa855d33d4efec8aea88cd66db1c2f0ebe16"
integrity sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw== integrity sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==
"@types/node@^12.12.6": "@types/node@^12.12.6":
version "12.20.55" version "12.20.55"