mirror of
https://github.com/tornadocash/tornado-relayer
synced 2024-02-02 15:04:06 +01:00
179 lines
4.4 KiB
JavaScript
179 lines
4.4 KiB
JavaScript
|
const { isHexStrict, toBN, toWei, BN } = require('web3-utils')
|
||
|
const { netId, mixers, relayerServiceFee } = require('../config')
|
||
|
|
||
|
function isValidProof(proof) {
|
||
|
// validator expects `websnarkUtils.toSolidityInput(proof)` output
|
||
|
|
||
|
if (!proof) {
|
||
|
return { valid: false, reason: 'The proof is empty.' }
|
||
|
}
|
||
|
|
||
|
if (!isHexStrict(proof) || proof.length !== 2 + 2 * 8 * 32) {
|
||
|
return { valid: false, reason: 'Corrupted proof' }
|
||
|
}
|
||
|
|
||
|
return { valid: true }
|
||
|
}
|
||
|
|
||
|
function isValidArgs(args) {
|
||
|
if (!args) {
|
||
|
return { valid: false, reason: 'Args are empty' }
|
||
|
}
|
||
|
|
||
|
if (args.length !== 6) {
|
||
|
return { valid: false, reason: 'Length of args is lower than 6' }
|
||
|
}
|
||
|
|
||
|
for (let signal of args) {
|
||
|
if (!isHexStrict(signal)) {
|
||
|
return { valid: false, reason: `Corrupted signal ${signal}` }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
args[0].length !== 66 ||
|
||
|
args[1].length !== 66 ||
|
||
|
args[2].length !== 42 ||
|
||
|
args[3].length !== 42 ||
|
||
|
args[4].length !== 66 ||
|
||
|
args[5].length !== 66
|
||
|
) {
|
||
|
return { valid: false, reason: 'The length one of the signals is incorrect' }
|
||
|
}
|
||
|
|
||
|
return { valid: true }
|
||
|
}
|
||
|
|
||
|
function isKnownContract(contract) {
|
||
|
const mixers = getMixers()
|
||
|
for (let currency of Object.keys(mixers)) {
|
||
|
for (let amount of Object.keys(mixers[currency].mixerAddress)) {
|
||
|
if (mixers[currency].mixerAddress[amount] === contract) {
|
||
|
return { valid: true, currency, amount }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return { valid: false }
|
||
|
}
|
||
|
|
||
|
function sleep(ms) {
|
||
|
return new Promise((resolve) => setTimeout(resolve, ms))
|
||
|
}
|
||
|
|
||
|
function fromDecimals(value, decimals) {
|
||
|
value = value.toString()
|
||
|
let ether = value.toString()
|
||
|
const base = new BN('10').pow(new BN(decimals))
|
||
|
const baseLength = base.toString(10).length - 1 || 1
|
||
|
|
||
|
const negative = ether.substring(0, 1) === '-'
|
||
|
if (negative) {
|
||
|
ether = ether.substring(1)
|
||
|
}
|
||
|
|
||
|
if (ether === '.') {
|
||
|
throw new Error('[ethjs-unit] while converting number ' + value + ' to wei, invalid value')
|
||
|
}
|
||
|
|
||
|
// Split it into a whole and fractional part
|
||
|
const comps = ether.split('.')
|
||
|
if (comps.length > 2) {
|
||
|
throw new Error('[ethjs-unit] while converting number ' + value + ' to wei, too many decimal points')
|
||
|
}
|
||
|
|
||
|
let whole = comps[0]
|
||
|
let fraction = comps[1]
|
||
|
|
||
|
if (!whole) {
|
||
|
whole = '0'
|
||
|
}
|
||
|
if (!fraction) {
|
||
|
fraction = '0'
|
||
|
}
|
||
|
if (fraction.length > baseLength) {
|
||
|
throw new Error('[ethjs-unit] while converting number ' + value + ' to wei, too many decimal places')
|
||
|
}
|
||
|
|
||
|
while (fraction.length < baseLength) {
|
||
|
fraction += '0'
|
||
|
}
|
||
|
|
||
|
whole = new BN(whole)
|
||
|
fraction = new BN(fraction)
|
||
|
let wei = whole.mul(base).add(fraction)
|
||
|
|
||
|
if (negative) {
|
||
|
wei = wei.mul(negative)
|
||
|
}
|
||
|
|
||
|
return new BN(wei.toString(10), 10)
|
||
|
}
|
||
|
|
||
|
function isEnoughFee({ gas, gasPrices, currency, amount, refund, ethPrices, fee }) {
|
||
|
const { decimals } = mixers[`netId${netId}`][currency]
|
||
|
const decimalsPoint =
|
||
|
Math.floor(relayerServiceFee) === relayerServiceFee
|
||
|
? 0
|
||
|
: relayerServiceFee.toString().split('.')[1].length
|
||
|
|
||
|
const roundDecimal = 10 ** decimalsPoint
|
||
|
const feePercent = toBN(fromDecimals(amount, decimals))
|
||
|
.mul(toBN(relayerServiceFee * roundDecimal))
|
||
|
.div(toBN(roundDecimal * 100))
|
||
|
const expense = toBN(toWei(gasPrices.fast.toString(), 'gwei')).mul(toBN(gas))
|
||
|
let desiredFee
|
||
|
switch (currency) {
|
||
|
case 'eth': {
|
||
|
desiredFee = expense.add(feePercent)
|
||
|
break
|
||
|
}
|
||
|
default: {
|
||
|
desiredFee = expense
|
||
|
.add(refund)
|
||
|
.mul(toBN(10 ** decimals))
|
||
|
.div(toBN(ethPrices[currency]))
|
||
|
desiredFee = desiredFee.add(feePercent)
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
console.log(
|
||
|
'sent fee, desired fee, feePercent',
|
||
|
fee.toString(),
|
||
|
desiredFee.toString(),
|
||
|
feePercent.toString()
|
||
|
)
|
||
|
if (fee.lt(desiredFee)) {
|
||
|
return { isEnough: false, reason: 'Not enough fee' }
|
||
|
}
|
||
|
return { isEnough: true }
|
||
|
}
|
||
|
|
||
|
function getArgsForOracle() {
|
||
|
const tokens = mixers['netId1']
|
||
|
const tokenAddresses = []
|
||
|
const oneUintAmount = []
|
||
|
const currencyLookup = {}
|
||
|
Object.entries(tokens).map(([currency, data]) => {
|
||
|
if (currency !== 'eth') {
|
||
|
tokenAddresses.push(data.tokenAddress)
|
||
|
oneUintAmount.push(toBN('10').pow(toBN(data.decimals.toString())).toString())
|
||
|
currencyLookup[data.tokenAddress] = currency
|
||
|
}
|
||
|
})
|
||
|
return { tokenAddresses, oneUintAmount, currencyLookup }
|
||
|
}
|
||
|
|
||
|
function getMixers() {
|
||
|
return mixers[`netId${netId}`]
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
isValidProof,
|
||
|
isValidArgs,
|
||
|
sleep,
|
||
|
isKnownContract,
|
||
|
isEnoughFee,
|
||
|
getMixers,
|
||
|
getArgsForOracle
|
||
|
}
|