Compare commits
16 Commits
mainnet-v4
...
mainnet-v5
| Author | SHA1 | Date | |
|---|---|---|---|
| 52473197ea | |||
| cb1212d793 | |||
| 531567d8b2 | |||
| 67c0782794 | |||
| 40c55b3e7c | |||
| fd72f09e11 | |||
| fdbbb05733 | |||
| eb908ff1f5 | |||
| 44f70bd41d | |||
| 16a17079eb | |||
| 6adeb27b83 | |||
| 58dae5b030 | |||
| 3b13d3f508 | |||
| 6b1a41585b | |||
| e90d1c4086 | |||
| 61f464441b |
@@ -1,6 +1,6 @@
|
||||
NET_ID=1
|
||||
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=https://api.securerpc.com/v1
|
||||
REDIS_URL=redis://127.0.0.1:6379
|
||||
@@ -12,8 +12,8 @@ APP_PORT=8000
|
||||
|
||||
# without 0x prefix
|
||||
PRIVATE_KEY=
|
||||
# 0.4 means 0.4%
|
||||
REGULAR_TORNADO_WITHDRAW_FEE=0.4
|
||||
# 0.05 means 0.05%
|
||||
RELAYER_FEE=0.4
|
||||
MINING_SERVICE_FEE=0.05
|
||||
REWARD_ACCOUNT=
|
||||
CONFIRMATIONS=4
|
||||
@@ -21,4 +21,4 @@ CONFIRMATIONS=4
|
||||
# in GWEI
|
||||
MAX_GAS_PRICE=1000
|
||||
BASE_FEE_RESERVE_PERCENTAGE=25
|
||||
AGGREGATOR=0x8cb1436F64a3c33aD17bb42F94e255c4c0E871b2
|
||||
AGGREGATOR=0xE8F47A78A6D52D317D0D2FFFac56739fE14D1b49
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,4 +6,3 @@ node_modules/
|
||||
kovan.*
|
||||
dump.rdb
|
||||
.idea
|
||||
yarn-error.log
|
||||
17
README.md
17
README.md
@@ -1,4 +1,4 @@
|
||||
# Relayer for Tornado Cash [](https://github.com/tornadocash/relayer/actions) [](https://hub.docker.com/repository/docker/tornadocash/relayer)
|
||||
# Relayer for Tornado Cash [](https://github.com/tornadocash/relayer/actions) 
|
||||
|
||||
__*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__
|
||||
1. Clone the repository and enter the directory
|
||||
- `git clone https://git.tornado.ws/tornadocash/classic-relayer -b mainnet-v4 && cd classic-relayer`
|
||||
- `git clone https://git.tornado.ws/tornadocash/classic-relayer -b mainnet-v5 && 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.
|
||||
- Set `PRIVATE_KEY` for your relayer address (remove the 0x from your private key)
|
||||
- Set `VIRTUAL_HOST` and `LETSENCRYPT_HOST` to your domain address
|
||||
@@ -63,12 +63,13 @@ __NGINX REVERSE PROXY__
|
||||
|
||||
## Run locally
|
||||
|
||||
1. `npm i`
|
||||
2. `cp .env.example .env`
|
||||
3. Modify `.env` as needed
|
||||
4. `npm run start`
|
||||
5. Go to `http://127.0.0.1:8000`
|
||||
6. In order to execute withdraw request, you can run following command
|
||||
1. `npm i -g yarn` (if yarn not installed in your system)
|
||||
2. `yarn`
|
||||
3. `cp .env.mainnet.example .env`
|
||||
4. Modify `.env` as needed
|
||||
5. `yarn start`
|
||||
6. Go to `http://127.0.0.1:8000`
|
||||
7. In order to execute withdraw request, you can run following command
|
||||
|
||||
```bash
|
||||
curl -X POST -H 'content-type:application/json' --data '<input data>' http://127.0.0.1:8000/relay
|
||||
|
||||
@@ -45,14 +45,15 @@ services:
|
||||
- nginx
|
||||
- dockergen
|
||||
|
||||
# ---------------------- ETH ----------------------- #
|
||||
# ---------------------- ETH Mainnet ----------------------- #
|
||||
|
||||
eth-server:
|
||||
build: .
|
||||
image: tornadocash/relayer:mainnet-v4
|
||||
image: tornadorelayer:mainnet
|
||||
profiles: ['eth']
|
||||
restart: always
|
||||
command: server
|
||||
env_file: .env
|
||||
env_file: .env.eth
|
||||
environment:
|
||||
NET_ID: 1
|
||||
REDIS_URL: redis://redis/0
|
||||
@@ -60,52 +61,58 @@ services:
|
||||
depends_on: [redis]
|
||||
|
||||
eth-treeWatcher:
|
||||
image: tornadocash/relayer:mainnet-v4
|
||||
image: tornadorelayer:mainnet
|
||||
profiles: ['eth']
|
||||
restart: always
|
||||
command: treeWatcher
|
||||
env_file: .env
|
||||
env_file: .env.eth
|
||||
environment:
|
||||
NET_ID: 1
|
||||
REDIS_URL: redis://redis/0
|
||||
depends_on: [redis, eth-server]
|
||||
|
||||
eth-priceWatcher:
|
||||
image: tornadocash/relayer:mainnet-v4
|
||||
image: tornadorelayer:mainnet
|
||||
profiles: ['eth']
|
||||
restart: always
|
||||
command: priceWatcher
|
||||
env_file: .env
|
||||
env_file: .env.eth
|
||||
environment:
|
||||
NET_ID: 1
|
||||
REDIS_URL: redis://redis/0
|
||||
depends_on: [redis, eth-server]
|
||||
|
||||
eth-healthWatcher:
|
||||
image: tornadocash/relayer:mainnet-v4
|
||||
image: tornadorelayer:mainnet
|
||||
profiles: ['eth']
|
||||
restart: always
|
||||
command: healthWatcher
|
||||
env_file: .env
|
||||
env_file: .env.eth
|
||||
environment:
|
||||
NET_ID: 1
|
||||
REDIS_URL: redis://redis/0
|
||||
depends_on: [redis, eth-server]
|
||||
|
||||
eth-worker1:
|
||||
image: tornadocash/relayer:mainnet-v4
|
||||
image: tornadorelayer:mainnet
|
||||
profiles: ['eth']
|
||||
restart: always
|
||||
command: worker
|
||||
env_file: .env
|
||||
env_file: .env.eth
|
||||
environment:
|
||||
NET_ID: 1
|
||||
REDIS_URL: redis://redis/0
|
||||
depends_on: [redis, eth-server]
|
||||
|
||||
# worker2:
|
||||
# image: tornadocash/relayer:mainnet-v4
|
||||
# # This is additional worker for ethereum mainnet
|
||||
# # So you can process transactions from multiple addresses, but before it you need to set up those addresses as workers
|
||||
# eth-worker2:
|
||||
# image: tornadorelayer:mainnet
|
||||
# profiles: [ 'eth' ]
|
||||
# restart: always
|
||||
# command: worker
|
||||
# env_file: .env
|
||||
# env_file: .env2.eth
|
||||
# environment:
|
||||
# PRIVATE_KEY: qwe
|
||||
# REDIS_URL: redis://redis/0
|
||||
|
||||
# # this container will proxy *.onion domain to the server container
|
||||
@@ -124,6 +131,327 @@ services:
|
||||
# ...
|
||||
# -----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:
|
||||
conf:
|
||||
vhost:
|
||||
|
||||
12
package.json
12
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "relay",
|
||||
"version": "4.1.6",
|
||||
"description": "Relayer for Tornado.cash privacy solution. https://tornado.cash",
|
||||
"version": "5.2.0",
|
||||
"description": "Relayer for Tornado.cash privacy solution.",
|
||||
"scripts": {
|
||||
"server": "node src/server.js",
|
||||
"worker": "node src/worker",
|
||||
@@ -13,17 +13,17 @@
|
||||
"prettier:fix": "npx prettier --write . --config .prettierrc",
|
||||
"lint": "yarn eslint && yarn prettier:check",
|
||||
"test": "mocha",
|
||||
"build": "docker build -t tornadocash/relayer:mainnet-v4 .",
|
||||
"build": "docker build -t tornadocash/relayer:mainnet-v5 .",
|
||||
"start": "docker-compose up -d redis && concurrently \"yarn server\" \"yarn priceWatcher\" \"yarn treeWatcher\" \"yarn worker\" \"yarn healthWatcher\""
|
||||
},
|
||||
"author": "tornado.cash",
|
||||
"author": "Tornado Cash team",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tornado/anonymity-mining": "^2.1.5",
|
||||
"@tornado/circomlib": "^0.0.21",
|
||||
"@tornado/fixed-merkle-tree": "^0.4",
|
||||
"@tornado/fixed-merkle-tree": "0.4.0",
|
||||
"@tornado/tornado-config": "^1",
|
||||
"@tornado/tornado-oracles": "1.2.2",
|
||||
"@tornado/tornado-oracles": "^3.3.0",
|
||||
"@tornado/tx-manager": "^0.4.9",
|
||||
"ajv": "^6.12.5",
|
||||
"async-mutex": "^0.2.4",
|
||||
|
||||
@@ -14,8 +14,7 @@ module.exports = {
|
||||
instances: tornConfig.instances,
|
||||
torn: tornConfig,
|
||||
port: process.env.APP_PORT || 8000,
|
||||
tornadoServiceFee: Number(process.env.REGULAR_TORNADO_WITHDRAW_FEE),
|
||||
miningServiceFee: Number(process.env.MINING_SERVICE_FEE),
|
||||
tornadoServiceFee: Number(process.env.RELAYER_FEE),
|
||||
rewardAccount: process.env.REWARD_ACCOUNT,
|
||||
governanceAddress: '0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce',
|
||||
tornadoGoerliProxy: '0x454d870a72e29d5E5697f635128D18077BD04C60',
|
||||
|
||||
@@ -25,7 +25,7 @@ async function status(req, res) {
|
||||
|
||||
function index(req, res) {
|
||||
res.send(
|
||||
'This is <a href=https://tornado.cash>tornado.cash</a> Relayer service. Check the <a href=/v1/status>/status</a> for settings',
|
||||
'This is <a href=https://tornado.ws>Tornado Cash</a> Relayer service. Check the <a href=/v1/status>/status</a> for settings',
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@ const priceOracle = new TokenPriceOracle(oracleRpcUrl)
|
||||
async function main() {
|
||||
try {
|
||||
const ethPrices = await priceOracle.fetchPrices()
|
||||
if (!Object.values(ethPrices).length) {
|
||||
throw new RelayerError('Can`t update prices', 1)
|
||||
}
|
||||
|
||||
await redis.hmset('prices', ethPrices)
|
||||
console.log('Wrote following prices to redis', ethPrices)
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const { instances, netId } = require('./config')
|
||||
const { poseidon } = require('@tornado/circomlib')
|
||||
const { toBN, toChecksumAddress, BN, fromWei, isAddress, toWei } = require('web3-utils')
|
||||
const { toBN, toChecksumAddress, BN, fromWei, isAddress, toWei, toHex } = require('web3-utils')
|
||||
|
||||
const addressMap = new Map()
|
||||
const instance = instances[netId]
|
||||
@@ -134,6 +134,7 @@ module.exports = {
|
||||
toChecksumAddress,
|
||||
fromWei,
|
||||
toWei,
|
||||
toHex,
|
||||
BN,
|
||||
isAddress,
|
||||
RelayerError,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
const fs = require('fs')
|
||||
const MerkleTree = require('@tornado/fixed-merkle-tree')
|
||||
const { TornadoFeeOracleV4, bump } = require('@tornado/tornado-oracles')
|
||||
const { Utils, Controller } = require('@tornado/anonymity-mining')
|
||||
|
||||
const { TornadoFeeOracleV5 } = require('@tornado/tornado-oracles')
|
||||
const swapABI = require('../abis/swap.abi.json')
|
||||
const miningABI = require('../abis/mining.abi.json')
|
||||
const tornadoABI = require('../abis/tornadoABI.json')
|
||||
@@ -11,10 +10,11 @@ const { queue } = require('./queue')
|
||||
const {
|
||||
poseidonHash2,
|
||||
getInstance,
|
||||
isAddress,
|
||||
sleep,
|
||||
toBN,
|
||||
fromWei,
|
||||
toChecksumAddress,
|
||||
isAddress,
|
||||
RelayerError,
|
||||
logRelayerError,
|
||||
} = require('./utils')
|
||||
@@ -30,7 +30,6 @@ const {
|
||||
miningServiceFee,
|
||||
tornadoServiceFee,
|
||||
tornadoGoerliProxy,
|
||||
rewardAccount,
|
||||
} = require('./config')
|
||||
const resolver = require('./modules/resolver')
|
||||
const { TxManager } = require('@tornado/tx-manager')
|
||||
@@ -45,7 +44,7 @@ let txManager
|
||||
let controller
|
||||
let swap
|
||||
let minerContract
|
||||
const feeOracle = new TornadoFeeOracleV4(netId, oracleRpcUrl)
|
||||
const feeOracle = new TornadoFeeOracleV5(netId, oracleRpcUrl)
|
||||
|
||||
async function fetchTree() {
|
||||
const elements = await redis.get('tree:elements')
|
||||
@@ -92,6 +91,7 @@ async function start() {
|
||||
BASE_FEE_RESERVE_PERCENTAGE: baseFeeReserve,
|
||||
},
|
||||
})
|
||||
|
||||
swap = new web3.eth.Contract(swapABI, await resolver.resolve(torn.rewardSwap.address))
|
||||
minerContract = new web3.eth.Contract(miningABI, await resolver.resolve(torn.miningV2.address))
|
||||
redisSubscribe.subscribe('treeUpdate', fetchTree)
|
||||
@@ -110,29 +110,38 @@ async function start() {
|
||||
}
|
||||
}
|
||||
|
||||
function checkFee({ data }) {
|
||||
function checkFee({ data }, gasInfo) {
|
||||
if (data.type === jobType.TORNADO_WITHDRAW) {
|
||||
return checkTornadoFee(data)
|
||||
return checkTornadoFee(data, gasInfo)
|
||||
}
|
||||
return checkMiningFee(data)
|
||||
}
|
||||
|
||||
async function checkTornadoFee({ args, contract }) {
|
||||
async function checkTornadoFee({ args, contract }, tx) {
|
||||
const { currency, amount, decimals } = getInstance(contract)
|
||||
const [userProvidedFee, refund] = [args[4], args[5]]
|
||||
const [userProvidedFee, refund] = [args[4], args[5]].map(toBN)
|
||||
const { gasLimit, gasPrice } = tx
|
||||
|
||||
const ethPrice = await redis.hget('prices', currency)
|
||||
const relayerEstimatedFee = await feeOracle.calculateWithdrawalFeeViaRelayer(
|
||||
'relayer_withdrawal_check_v4',
|
||||
{},
|
||||
tornadoServiceFee,
|
||||
currency,
|
||||
const totalWithdrawalFee = await feeOracle.calculateWithdrawalFeeViaRelayer({
|
||||
tx,
|
||||
txType: 'relayer_withdrawal',
|
||||
amount,
|
||||
currency,
|
||||
decimals,
|
||||
refund,
|
||||
ethPrice,
|
||||
refundInEth: refund.toString(),
|
||||
predefinedGasLimit: gasLimit,
|
||||
predefinedGasPrice: gasPrice,
|
||||
tokenPriceInEth: ethPrice,
|
||||
relayerFeePercent: tornadoServiceFee,
|
||||
})
|
||||
|
||||
console.log(
|
||||
'user-provided fee, desired fee',
|
||||
fromWei(userProvidedFee.toString()),
|
||||
fromWei(toBN(totalWithdrawalFee).toString()),
|
||||
)
|
||||
if (toBN(relayerEstimatedFee).gt(toBN(userProvidedFee))) {
|
||||
if (userProvidedFee.lt(toBN(totalWithdrawalFee))) {
|
||||
throw new RelayerError(
|
||||
'Provided fee is not enough. Probably it is a Gas Price spike, try to resubmit.',
|
||||
0,
|
||||
@@ -141,7 +150,7 @@ async function checkTornadoFee({ args, contract }) {
|
||||
}
|
||||
|
||||
async function checkMiningFee({ args }) {
|
||||
const gasPrice = await feeOracle.getGasPriceInHex()
|
||||
const gasPrice = await feeOracle.getGasPrice()
|
||||
const ethPrice = await redis.hget('prices', 'torn')
|
||||
const isMiningReward = currentJob.data.type === jobType.MINING_REWARD
|
||||
const providedFee = isMiningReward ? toBN(args.fee) : toBN(args.extData.fee)
|
||||
@@ -196,6 +205,7 @@ async function checkRecipient({ data }) {
|
||||
// Checks only for default withdrawals
|
||||
if (data.type !== jobType.TORNADO_WITHDRAW) return
|
||||
|
||||
console.log(data.args)
|
||||
const recipient = data.args[2]
|
||||
if (!isAddress(recipient)) throw new Error('Recipient address is invalid')
|
||||
|
||||
@@ -216,15 +226,16 @@ async function getTxObject({ data }) {
|
||||
|
||||
const incompleteTx = {
|
||||
value: data.args[5],
|
||||
from: txManager.address, // Required, because without it relayerRegistry.burn will fail, because msg.sender is not relayer
|
||||
to: contract._address,
|
||||
data: calldata,
|
||||
}
|
||||
const [gasPrice, gasLimit] = await Promise.all([
|
||||
feeOracle.getGasPrice('relayer_withdrawal'),
|
||||
feeOracle.getGasLimit(incompleteTx, 'relayer_withdrawal'),
|
||||
])
|
||||
const { gasLimit, gasPrice } = await feeOracle.getGasParams({
|
||||
tx: incompleteTx,
|
||||
txType: 'relayer_withdrawal',
|
||||
})
|
||||
|
||||
return Object.assign({ gasLimit, gasPrice }, incompleteTx)
|
||||
return { ...incompleteTx, gasLimit, gasPrice }
|
||||
} else {
|
||||
const method = data.type === jobType.MINING_REWARD ? 'reward' : 'withdraw'
|
||||
const calldata = minerContract.methods[method](data.proof, data.args).encodeABI()
|
||||
@@ -266,20 +277,11 @@ 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) {
|
||||
await checkRecipient(job)
|
||||
await checkFee(job)
|
||||
const tx = await getTxObject(job)
|
||||
await checkRevert(tx)
|
||||
currentTx = await txManager.createTx(tx)
|
||||
const rawTx = await getTxObject(job)
|
||||
await checkFee(job, rawTx)
|
||||
currentTx = await txManager.createTx(rawTx)
|
||||
|
||||
if (job.data.type !== jobType.TORNADO_WITHDRAW) {
|
||||
await fetchTree()
|
||||
|
||||
44
yarn.lock
44
yarn.lock
@@ -10,17 +10,17 @@
|
||||
"@babel/highlight" "^7.22.13"
|
||||
chalk "^2.4.2"
|
||||
|
||||
"@babel/helper-validator-identifier@^7.22.5":
|
||||
version "7.22.19"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.19.tgz#2f34ab1e445f5b95e2e6edfe50ea2449e610583a"
|
||||
integrity sha512-Tinq7ybnEPFFXhlYOYFiSjespWQk0dq2dRNAiMdRTOYQzEGqnnNyrTxPYHP5r6wGjlF1rFgABdDV0g8EwD6Qbg==
|
||||
"@babel/helper-validator-identifier@^7.22.20":
|
||||
version "7.22.20"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
|
||||
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
|
||||
|
||||
"@babel/highlight@^7.22.13":
|
||||
version "7.22.13"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.13.tgz#9cda839e5d3be9ca9e8c26b6dd69e7548f0cbf16"
|
||||
integrity sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==
|
||||
version "7.22.20"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
|
||||
integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.22.5"
|
||||
"@babel/helper-validator-identifier" "^7.22.20"
|
||||
chalk "^2.4.2"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
@@ -534,7 +534,7 @@
|
||||
"@tornado/circomlib" "^0.0.21"
|
||||
"@tornado/snarkjs" "^0.1.20"
|
||||
|
||||
"@tornado/fixed-merkle-tree@^0.4":
|
||||
"@tornado/fixed-merkle-tree@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"
|
||||
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"
|
||||
integrity sha512-7EkpWNfEm34VEOrbLnPpvd/aUJYnA1L+6/qx2fZ/AfmuJFkjSZ18Z4jvVGNY7ktKIhTu3/Tbze+9l3eNueCNIA==
|
||||
|
||||
"@tornado/tornado-oracles@1.2.2":
|
||||
version "1.2.2"
|
||||
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-JJoUAkQLV7bVrU2YMFt9d+TB5BovrvQubg8n0V0ZGcTDv/bz2H3EWwStz6Tvl+wUAnPuNnEeS934vkOvgFtEew==
|
||||
"@tornado/tornado-oracles@^3.3.0":
|
||||
version "3.3.0"
|
||||
resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ftornado-oracles/-/3.3.0/tornado-oracles-3.3.0.tgz#6358f896f399904ed8deb9b8f4253e77732bd227"
|
||||
integrity sha512-OBJ+TmygY6VMcYJCPxSOAzPDZpmF4WhRVhjgTEhqw+hg70WW9L4b3DC1B1P/4Gmar2lzi6BnTI4ckkDy/xsHQQ==
|
||||
dependencies:
|
||||
"@tornado/gas-price-oracle" "^0.5.3"
|
||||
"@tornado/tornado-config" "^2.0.0"
|
||||
@@ -636,9 +636,9 @@
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1":
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682"
|
||||
integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.2.tgz#162f5238c46f4bcbac07a98561724eca1fcf0c5e"
|
||||
integrity sha512-dkpZu0szUtn9UXTmw+e0AJFd4D2XAxDnsCLdc05SfqpqzPEBft8eQr8uaFitfo/dUUOZERaLec2hHMG87A4Dxg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
@@ -653,9 +653,9 @@
|
||||
"@types/responselike" "^1.0.0"
|
||||
|
||||
"@types/http-cache-semantics@*":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812"
|
||||
integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.2.tgz#abe102d06ccda1efdf0ed98c10ccf7f36a785a41"
|
||||
integrity sha512-FD+nQWA2zJjh4L9+pFXqWOi0Hs1ryBCfI+985NjluQ1p8EYtoLvjLOKidXBtZ4/IcxDX4o8/E8qDS3540tNliw==
|
||||
|
||||
"@types/keyv@^3.1.4":
|
||||
version "3.1.4"
|
||||
@@ -665,9 +665,9 @@
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*", "@types/node@^20.5.1":
|
||||
version "20.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.0.tgz#9d7daa855d33d4efec8aea88cd66db1c2f0ebe16"
|
||||
integrity sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==
|
||||
version "20.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.2.tgz#a065925409f59657022e9063275cd0b9bd7e1b12"
|
||||
integrity sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==
|
||||
|
||||
"@types/node@^12.12.6":
|
||||
version "12.20.55"
|
||||
|
||||
Reference in New Issue
Block a user