Compare commits

...

2 Commits

3 changed files with 326 additions and 221 deletions

272
cli.js

@ -18,7 +18,7 @@ const { toWei, fromWei, toBN, BN } = require('web3-utils');
const BigNumber = require('bignumber.js');
const config = require('./config');
const program = require('commander');
const { GasPriceOracle } = require('@tornado/gas-price-oracle');
const { TornadoFeeOracleV4, TornadoFeeOracleV5, TokenPriceOracle } = require('@tornado/tornado-oracles');
const { SocksProxyAgent } = require('socks-proxy-agent');
const is_ip_private = require('private-ip');
const readline = require('readline');
@ -42,7 +42,8 @@ let web3,
netSymbol,
multiCall,
userAction,
subgraph;
subgraph,
feeOracle;
let MERKLE_TREE_HEIGHT, ETH_AMOUNT, TOKEN_AMOUNT, PRIVATE_KEY;
/** Command state parameters */
@ -157,86 +158,27 @@ async function submitTransaction(signedTX) {
});
}
/**
* Estimate gas for created transaction
* @typedef {string} EthAddress Wallet (account) address
* @param {EthAddress} from Transaction sender
* @param {EthAddress} to Transaction recipient
* @param {Number} nonce Account nonce (transactions count on sender account)
* @param {string} encodedData Encoded ABI of transaction
* @param {Number} value Amount of funds to send in this transaction
* @returns {Promise<Number>} current acceptable gas limit to send this transaction
*/
async function estimateGas(from, to, nonce, encodedData, value = 0) {
const fetchedGas = await web3.eth.estimateGas({
from,
to,
value,
nonce,
data: encodedData
});
const bumped = Math.floor(fetchedGas * 1.3);
return bumped;
}
async function fetchL1Fee({ gasPrice, gasLimit }) {
const DUMMY_NONCE = '0x1111111111111111111111111111111111111111111111111111111111111111';
const DUMMY_WITHDRAW_DATA =
'0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111';
if (netId === 10) {
const ovmGasPriceOracleContractAddress = '0x420000000000000000000000000000000000000F';
const optimismL1GasPriceOracleABI = require('./build/contracts/OptimismL1GasPriceOracle.json');
const oracleInstance = new web3.eth.Contract(optimismL1GasPriceOracleABI, ovmGasPriceOracleContractAddress);
try {
const tx = serialize({
type: 0,
gasLimit,
chainId: netId,
nonce: DUMMY_NONCE,
data: DUMMY_WITHDRAW_DATA,
gasPrice,
to: tornadoProxyAddress
});
const l1Fee = await oracleInstance.methods.getL1Fee(tx).call();
return l1Fee;
} catch (err) {
throw new Error('Error while fetching optimism L1 fee: ' + err.message);
}
}
return 0;
}
async function generateTransaction(to, encodedData, value = 0) {
async function generateTransaction(to, encodedData, value = 0, txType = 'other') {
const nonce = await web3.eth.getTransactionCount(senderAccount);
let gasPrice = await fetchGasPrice();
let gasLimit;
value = toBN(value);
if (encodedData) {
gasLimit = await estimateGas(senderAccount, to, nonce, encodedData, value);
} else {
gasLimit = 23000;
}
gasLimit = web3.utils.toHex(gasLimit);
let incompletedTx = {
to,
value: value.toString(),
data: encodedData
};
if (txType === 'send') incompletedTx['from'] = senderAccount;
const isNumRString = typeof value == 'string' || typeof value == 'number';
const valueCost = isNumRString ? toBN(value) : value;
const additionalFees = userAction === 'withdrawal' ? await fetchL1Fee({ gasPrice, gasLimit }) : 0;
const gasCosts = toBN(gasPrice).mul(toBN(gasLimit)).add(toBN(additionalFees));
const totalCosts = valueCost.add(gasCosts);
const { gasPrice, gasLimit, l1Fee } = await feeOracle.getGasParams(incompletedTx, txType);
const gasCosts = toBN(gasPrice).mul(toBN(gasLimit)).add(toBN(l1Fee));
const totalCosts = value.add(gasCosts);
/** Transaction details */
console.log('Gas price: ', web3.utils.hexToNumber(gasPrice));
console.log('Gas limit: ', web3.utils.hexToNumber(gasLimit));
if (additionalFees != 0)
console.log('Additional gas fees (like L1 data fee): ', rmDecimalBN(fromWei(additionalFees), 12), `${netSymbol}`);
console.log('Gas limit: ', gasLimit);
if (!toBN(l1Fee).eq(toBN(0)))
console.log('Additional gas fees (like L1 data fee): ', rmDecimalBN(fromWei(l1Fee), 12), `${netSymbol}`);
console.log('Transaction fee: ', rmDecimalBN(fromWei(gasCosts), 12), `${netSymbol}`);
console.log('Transaction cost: ', rmDecimalBN(fromWei(totalCosts), 12), `${netSymbol}`);
/** ----------------------------------------- **/
@ -431,7 +373,7 @@ async function deposit({ currency, amount, commitmentNote }) {
* @param {Object} deposit Deposit object
* @param {string} currency Currency ticker, like 'ETH' or 'BNB'
* @param {number} amount Tornado instance amount, like 0.1 (ETH or BNB) or 10
* @return {MerkleProof} Calculated valid merkle tree (proof)
* @return {Promise<MerkleProof>} Calculated valid merkle tree (proof)
*/
async function generateMerkleProof(deposit, currency, amount) {
// Get all deposit events from smart contract and assemble merkle tree from them
@ -552,50 +494,49 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, refu
assert(netId === (await web3.eth.net.getId()) || netId === '*', 'This relay is for different network');
console.log('Relay address:', rewardAccount);
const gasPrice = await fetchGasPrice();
const decimals = isTestRPC ? 18 : config.deployments[`netId${netId}`]['tokens'][currency].decimals;
const merkleWithdrawalProof = await generateMerkleProof(deposit, currency, amount);
async function calculateDataForRelayer(gasLimit) {
const { desiredFee: totalFee, feePercent: relayerFee } = await calculateRelayerWithdrawFee({
currency,
gasPrice,
amount,
refund,
ethPrices,
relayerServiceFee: tornadoServiceFee,
decimals,
gasLimit
});
async function calculateDataForRelayer(totalRelayerFee = 0) {
const { proof, args } = await generateProof({
deposit,
currency,
amount,
recipient,
relayerAddress: rewardAccount,
fee: totalFee,
fee: toBN(totalRelayerFee),
refund,
merkleProof: merkleWithdrawalProof
});
return { proof, args, totalFee, relayerFee };
return { proof, args };
}
const { proof: dummyProof, args: dummyArgs } = await calculateDataForRelayer();
const realGasLimit = await estimateWithdrawGasLimit({ relayer: rewardAccount, proof: dummyProof, callArgs: dummyArgs });
const { proof, args, totalFee, relayerFee } = await calculateDataForRelayer(realGasLimit);
const withdrawalTxCalldata = tornado.methods.withdraw(tornadoProxyAddress, dummyProof, ...dummyArgs);
const incompleteWithdrawalTx = {
to: tornadoProxyAddress,
data: withdrawalTxCalldata,
value: toBN(dummyArgs[5]) || 0
};
const totalWithdrawalFee = await feeOracle.calculateWithdrawalFeeViaRelayer(
'user_withdrawal',
incompleteWithdrawalTx,
Number(tornadoServiceFee),
currency,
amount,
decimals,
refund,
ethPrices?.[currency]
);
const { proof, args } = await calculateDataForRelayer(totalWithdrawalFee);
console.log('Sending withdraw transaction through relay');
const l1Fee = await fetchL1Fee({ gasPrice, gasLimit: realGasLimit });
const gasCosts = toBN(gasPrice).mul(toBN(realGasLimit)).add(toBN(l1Fee));
/** Relayer fee details **/
console.log('Transaction fee: ', rmDecimalBN(fromWei(gasCosts), 12), `${netSymbol}`);
console.log('Relayer fee: ', rmDecimalBN(fromWei(relayerFee), 12), `${netSymbol}`);
console.log('Total fees: ', rmDecimalBN(fromWei(totalFee), 12), `${netSymbol}`);
console.log('Total fees: ', rmDecimalBN(fromWei(toBN(totalWithdrawalFee)), 12), `${netSymbol}`);
/** -------------------- **/
if (shouldPromptConfirmation) {
@ -638,7 +579,12 @@ async function withdraw({ deposit, currency, amount, recipient, relayerURL, refu
const { proof, args } = await generateProof({ deposit, currency, amount, recipient, refund });
console.log('Submitting withdraw transaction');
await generateTransaction(tornadoProxyAddress, tornado.methods.withdraw(tornadoInstance, proof, ...args).encodeABI());
await generateTransaction(
tornadoProxyAddress,
tornado.methods.withdraw(tornadoInstance, proof, ...args).encodeABI(),
toBN(args[5]),
'user_withdrawal'
);
}
if (currency === netSymbol.toLowerCase()) {
await printETHBalance({ address: recipient, name: 'Recipient' });
@ -686,11 +632,12 @@ async function send({ address, amount, tokenAddress }) {
process.exit(1);
}
const encodeTransfer = erc20.methods.transfer(address, toSend).encodeABI();
await generateTransaction(tokenAddress, encodeTransfer);
await generateTransaction(tokenAddress, encodeTransfer, 0, 'send');
console.log('Sent', amount, tokenSymbol, 'to', address);
} else {
const balance = new BigNumber(await web3.eth.getBalance(senderAccount));
assert(balance.toNumber() !== 0, "You have 0 balance, can't send transaction");
let toSend = new BigNumber(0);
if (amount) {
toSend = new BigNumber(amount).times(BigNumber(10).pow(18));
if (balance.lt(toSend)) {
@ -703,7 +650,7 @@ async function send({ address, amount, tokenAddress }) {
}
} else {
console.log('Amount not defined, sending all available amounts');
const gasPrice = new BigNumber(await fetchGasPrice());
const gasPrice = new BigNumber(await feeOracle.getGasPrice('other'));
const gasLimit = new BigNumber(21000);
if (netId == 1) {
const priorityFee = new BigNumber(await gasPrices(3));
@ -903,122 +850,6 @@ function getCurrentNetworkSymbol() {
}
}
async function fetchGasPrice() {
try {
/** Gas preferences **/
console.log('Gas speed preference: ', preferenceSpeed);
/** ----------------------------------------------- **/
// Extra bump estimated gas price for some chains
let bumpPercent;
switch (netId) {
case 5:
bumpPercent = 50;
break;
case 137:
case 43114:
case 100:
bumpPercent = 30;
break;
default:
bumpPercent = 10;
}
try {
const oracleOptions = {
chainId: netId,
defaultRpc: web3.currentProvider.host,
minPriority: netId === 1 || netId === 5 ? 2 : 0.05,
percentile: 5,
blocksCount: 20
};
const oracle = new GasPriceOracle(oracleOptions);
const { maxFeePerGas, gasPrice } = await oracle.getTxGasParams({ legacySpeed: preferenceSpeed, bumpPercent });
return maxFeePerGas || gasPrice;
} catch (e) {
const wei = toBN(await web3.eth.getGasPrice());
const bumped = wei.add(wei.mul(toBN(bumpPercent)).div(toBN(100)));
return toHex(bumped);
}
} catch (err) {
throw new Error(`Method fetchGasPrice has error ${err.message}`);
}
}
/**
* Get default gas limit depending on chain ID
* Available chain ID's on Tornado
* @typedef {1 | 5 | 10 | 56 | 100 | 137 | 42161 | 43114 } NetID
* @param {NetID}} netId
* @returns {Number} acceptable withdraw gas limit for selected chain
*/
function getHardcodedWithdrawGasLimit(netId) {
switch (netId) {
case 10:
return 440000;
case 42161:
return 1900000;
default:
return 390000;
}
}
/**
* Estimate gas limit for withdraw transaction via relayer with pregenerated proof
* @typedef {string} EthAddress Wallet (account) address
* @param {object} args Function arguments
* @param {EthAddress} args.relayer Relayer address
* @param {string} args.proof Calculated SNARK proof for withdrawal
* @param {Array<string>} args.callArgs Arguments to call 'withdraw' function from Tornado Proxy contract
* @returns {Promise<Number>} Acceptable gas limit to send withdraw transaction via relayer for selected chain
*/
async function estimateWithdrawGasLimit({ relayer, proof, callArgs }) {
const tx = tornado.methods.withdraw(tornadoInstance, proof, ...callArgs).encodeABI();
const nonce = await web3.eth.getTransactionCount(relayer);
const gasLimit = await estimateGas(relayer, tornadoProxyAddress, nonce, tx, callArgs[5]);
return gasLimit;
}
async function calculateRelayerWithdrawFee({
currency,
gasPrice,
amount,
refund,
ethPrices,
relayerServiceFee,
decimals,
gasLimit
}) {
const decimalsPoint =
Math.floor(relayerServiceFee) === Number(relayerServiceFee) ? 0 : relayerServiceFee.toString().split('.')[1].length;
const roundDecimal = 10 ** decimalsPoint;
const total = toBN(fromDecimals({ amount, decimals }));
const feePercent = total.mul(toBN(relayerServiceFee * roundDecimal)).div(toBN(roundDecimal * 100));
const l1Fee = await fetchL1Fee({ gasPrice, gasLimit });
const expense = toBN(gasPrice)
.mul(toBN(gasLimit || getHardcodedWithdrawGasLimit(netId)))
.add(toBN(l1Fee));
let desiredFee;
switch (currency) {
case netSymbol.toLowerCase(): {
desiredFee = expense.add(feePercent);
break;
}
default: {
desiredFee = expense
.add(toBN(refund))
.mul(toBN(10 ** decimals))
.div(toBN(ethPrices[currency]));
desiredFee = desiredFee.add(feePercent);
break;
}
}
return { desiredFee, feePercent };
}
/**
* Waits for transaction to be mined
* @param txHash Hash of transaction
@ -1599,6 +1430,7 @@ async function init({ rpc, noteNetId, currency = 'dai', amount = '100', balanceC
netId = await web3.eth.net.getId();
netName = getCurrentNetworkName();
netSymbol = getCurrentNetworkSymbol();
feeOracle = Number(netId) === 1 ? new TornadoFeeOracleV4(netId, rpc) : new TornadoFeeOracleV5(netId, rpc);
if (noteNetId && Number(noteNetId) !== netId) {
throw new Error('This note is for a different network. Specify the --rpc option explicitly');
@ -1621,7 +1453,7 @@ async function init({ rpc, noteNetId, currency = 'dai', amount = '100', balanceC
try {
if (balanceCheck) {
currency = netSymbol.toLowerCase();
amount = Object.keys(config.deployments[`netId${netId}`][currency].instanceAddress)[0];
amount = Object.keys(config.deployments[`netId${netId}`]['tokens'][currency].instanceAddress)[0];
}
tornadoProxyAddress = config.deployments[`netId${netId}`].proxy;
multiCall = config.deployments[`netId${netId}`].multicall;

273
package-lock.json generated

@ -158,6 +158,15 @@
"@ethersproject/bytes": "^5.7.0"
}
},
"@ethersproject/basex": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz",
"integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==",
"requires": {
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/properties": "^5.7.0"
}
},
"@ethersproject/bignumber": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz",
@ -191,6 +200,23 @@
"@ethersproject/bignumber": "^5.7.0"
}
},
"@ethersproject/contracts": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz",
"integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==",
"requires": {
"@ethersproject/abi": "^5.7.0",
"@ethersproject/abstract-provider": "^5.7.0",
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/address": "^5.7.0",
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/constants": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/transactions": "^5.7.0"
}
},
"@ethersproject/hash": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz",
@ -207,6 +233,45 @@
"@ethersproject/strings": "^5.7.0"
}
},
"@ethersproject/hdnode": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz",
"integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==",
"requires": {
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/basex": "^5.7.0",
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/pbkdf2": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/sha2": "^5.7.0",
"@ethersproject/signing-key": "^5.7.0",
"@ethersproject/strings": "^5.7.0",
"@ethersproject/transactions": "^5.7.0",
"@ethersproject/wordlists": "^5.7.0"
}
},
"@ethersproject/json-wallets": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz",
"integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==",
"requires": {
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/address": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/hdnode": "^5.7.0",
"@ethersproject/keccak256": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/pbkdf2": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/random": "^5.7.0",
"@ethersproject/strings": "^5.7.0",
"@ethersproject/transactions": "^5.7.0",
"aes-js": "3.0.0",
"scrypt-js": "3.0.1"
}
},
"@ethersproject/keccak256": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz",
@ -229,6 +294,15 @@
"@ethersproject/logger": "^5.7.0"
}
},
"@ethersproject/pbkdf2": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz",
"integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==",
"requires": {
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/sha2": "^5.7.0"
}
},
"@ethersproject/properties": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz",
@ -237,6 +311,49 @@
"@ethersproject/logger": "^5.7.0"
}
},
"@ethersproject/providers": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz",
"integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==",
"requires": {
"@ethersproject/abstract-provider": "^5.7.0",
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/address": "^5.7.0",
"@ethersproject/base64": "^5.7.0",
"@ethersproject/basex": "^5.7.0",
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/constants": "^5.7.0",
"@ethersproject/hash": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/networks": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/random": "^5.7.0",
"@ethersproject/rlp": "^5.7.0",
"@ethersproject/sha2": "^5.7.0",
"@ethersproject/strings": "^5.7.0",
"@ethersproject/transactions": "^5.7.0",
"@ethersproject/web": "^5.7.0",
"bech32": "1.1.4",
"ws": "7.4.6"
},
"dependencies": {
"ws": {
"version": "7.4.6",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A=="
}
}
},
"@ethersproject/random": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz",
"integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==",
"requires": {
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/logger": "^5.7.0"
}
},
"@ethersproject/rlp": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz",
@ -246,6 +363,16 @@
"@ethersproject/logger": "^5.7.0"
}
},
"@ethersproject/sha2": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz",
"integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==",
"requires": {
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"hash.js": "1.1.7"
}
},
"@ethersproject/signing-key": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz",
@ -266,6 +393,19 @@
}
}
},
"@ethersproject/solidity": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz",
"integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==",
"requires": {
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/keccak256": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/sha2": "^5.7.0",
"@ethersproject/strings": "^5.7.0"
}
},
"@ethersproject/strings": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz",
@ -292,6 +432,38 @@
"@ethersproject/signing-key": "^5.7.0"
}
},
"@ethersproject/units": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz",
"integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==",
"requires": {
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/constants": "^5.7.0",
"@ethersproject/logger": "^5.7.0"
}
},
"@ethersproject/wallet": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz",
"integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==",
"requires": {
"@ethersproject/abstract-provider": "^5.7.0",
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/address": "^5.7.0",
"@ethersproject/bignumber": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/hash": "^5.7.0",
"@ethersproject/hdnode": "^5.7.0",
"@ethersproject/json-wallets": "^5.7.0",
"@ethersproject/keccak256": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/random": "^5.7.0",
"@ethersproject/signing-key": "^5.7.0",
"@ethersproject/transactions": "^5.7.0",
"@ethersproject/wordlists": "^5.7.0"
}
},
"@ethersproject/web": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz",
@ -304,6 +476,18 @@
"@ethersproject/strings": "^5.7.0"
}
},
"@ethersproject/wordlists": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz",
"integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==",
"requires": {
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/hash": "^5.7.0",
"@ethersproject/logger": "^5.7.0",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/strings": "^5.7.0"
}
},
"@humanwhocodes/config-array": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
@ -434,6 +618,48 @@
}
}
},
"@tornado/tornado-config": {
"version": "2.0.0",
"resolved": "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ftornado-config/-/2.0.0/tornado-config-2.0.0.tgz",
"integrity": "sha512-7EkpWNfEm34VEOrbLnPpvd/aUJYnA1L+6/qx2fZ/AfmuJFkjSZ18Z4jvVGNY7ktKIhTu3/Tbze+9l3eNueCNIA=="
},
"@tornado/tornado-oracles": {
"version": "1.3.2",
"resolved": "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ftornado-oracles/-/1.3.2/tornado-oracles-1.3.2.tgz",
"integrity": "sha512-z3NI35GKKznxVigF0OghqQ8S3sT/S4oD3AtXqyf+P2bfkriAsdrXnsSMW7Vxej529e5k3cA0dPtOs4eFqFE/7Q==",
"requires": {
"@tornado/gas-price-oracle": "^0.5.3",
"@tornado/tornado-config": "^2.0.0",
"@types/node": "^20.5.1",
"bignumber.js": "^9.1.1",
"ethers": "5.7"
},
"dependencies": {
"@tornado/gas-price-oracle": {
"version": "0.5.3",
"resolved": "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Fgas-price-oracle/-/0.5.3/gas-price-oracle-0.5.3.tgz",
"integrity": "sha512-LpVfPiPIz3FOmJdiqJf/yoeO5n9/Pd5jgtdY+6hB9lNW0AiWhylhpScojICViS+3OL9QC8CoTlgr+kbfGeO9pQ==",
"requires": {
"axios": "^0.21.2",
"bignumber.js": "^9.0.0",
"node-cache": "^5.1.2"
}
},
"@types/node": {
"version": "20.5.6",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.6.tgz",
"integrity": "sha512-Gi5wRGPbbyOTX+4Y2iULQ27oUPrefaB0PxGQJnfyWN3kvEDGM3mIB5M/gQLmitZf7A9FmLeaqxD3L1CXpm3VKQ=="
},
"axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"requires": {
"follow-redirects": "^1.14.0"
}
}
}
},
"@tornado/web3-providers-http": {
"version": "1.6.5-p1",
"resolved": "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Fweb3-providers-http/-/1.6.5-p1/web3-providers-http-1.6.5-p1.tgz",
@ -587,6 +813,11 @@
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="
},
"aes-js": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz",
"integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw=="
},
"agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -753,6 +984,11 @@
"tweetnacl": "^0.14.3"
}
},
"bech32": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz",
"integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ=="
},
"big-integer": {
"version": "1.6.51",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
@ -2019,6 +2255,43 @@
}
}
},
"ethers": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz",
"integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==",
"requires": {
"@ethersproject/abi": "5.7.0",
"@ethersproject/abstract-provider": "5.7.0",
"@ethersproject/abstract-signer": "5.7.0",
"@ethersproject/address": "5.7.0",
"@ethersproject/base64": "5.7.0",
"@ethersproject/basex": "5.7.0",
"@ethersproject/bignumber": "5.7.0",
"@ethersproject/bytes": "5.7.0",
"@ethersproject/constants": "5.7.0",
"@ethersproject/contracts": "5.7.0",
"@ethersproject/hash": "5.7.0",
"@ethersproject/hdnode": "5.7.0",
"@ethersproject/json-wallets": "5.7.0",
"@ethersproject/keccak256": "5.7.0",
"@ethersproject/logger": "5.7.0",
"@ethersproject/networks": "5.7.1",
"@ethersproject/pbkdf2": "5.7.0",
"@ethersproject/properties": "5.7.0",
"@ethersproject/providers": "5.7.2",
"@ethersproject/random": "5.7.0",
"@ethersproject/rlp": "5.7.0",
"@ethersproject/sha2": "5.7.0",
"@ethersproject/signing-key": "5.7.0",
"@ethersproject/solidity": "5.7.0",
"@ethersproject/strings": "5.7.0",
"@ethersproject/transactions": "5.7.0",
"@ethersproject/units": "5.7.0",
"@ethersproject/wallet": "5.7.0",
"@ethersproject/web": "5.7.1",
"@ethersproject/wordlists": "5.7.0"
}
},
"ethjs-unit": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz",

@ -13,8 +13,8 @@
"@ethersproject/transactions": "^5.7.0",
"@tornado/circomlib": "0.0.20-p2",
"@tornado/fixed-merkle-tree": "0.6.1-p1",
"@tornado/gas-price-oracle": "0.5.2-p1",
"@tornado/snarkjs": "0.1.20-p2",
"@tornado/tornado-oracles": "^1.3.2",
"@tornado/web3-providers-http": "1.6.5-p1",
"@tornado/websnark": "0.0.4-p1",
"axios": "^0.19.2",