Correct gas estimation to v5 version
This commit is contained in:
parent
d69a17073a
commit
85ca668396
1
.npmrc
Normal file
1
.npmrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
@tornado:registry=https://git.tornado.ws/api/packages/tornado-packages/npm/
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "relay",
|
"name": "classic-relay",
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"description": "Relayer for Tornado.cash privacy solution. https://tornado.cash",
|
"description": "Relayer for Tornado.cash privacy solution. https://tornado.cash",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -25,6 +25,7 @@
|
|||||||
"@fastify/cors": "^8.0.0",
|
"@fastify/cors": "^8.0.0",
|
||||||
"@fastify/helmet": "^9.1.0",
|
"@fastify/helmet": "^9.1.0",
|
||||||
"@fastify/sensible": "^5.1.0",
|
"@fastify/sensible": "^5.1.0",
|
||||||
|
"@tornado/gas-price-oracle": "^0.5.3",
|
||||||
"ajv": "^8.11.0",
|
"ajv": "^8.11.0",
|
||||||
"bullmq": "^1.80.6",
|
"bullmq": "^1.80.6",
|
||||||
"compare-versions": "^4.1.3",
|
"compare-versions": "^4.1.3",
|
||||||
@ -32,7 +33,6 @@
|
|||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"ethers": "^5.6.4",
|
"ethers": "^5.6.4",
|
||||||
"fastify": "^4.2.0",
|
"fastify": "^4.2.0",
|
||||||
"gas-price-oracle": "^0.5.0",
|
|
||||||
"ioredis": "^5.0.6",
|
"ioredis": "^5.0.6",
|
||||||
"json-schema-to-ts": "^2.2.0",
|
"json-schema-to-ts": "^2.2.0",
|
||||||
"node-fetch": "2",
|
"node-fetch": "2",
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { BigNumber, BigNumberish } from 'ethers';
|
||||||
|
|
||||||
export const parseJSON = (str: string) => {
|
export const parseJSON = (str: string) => {
|
||||||
let parsed = null;
|
let parsed = null;
|
||||||
try {
|
try {
|
||||||
@ -8,3 +10,9 @@ export const parseJSON = (str: string) => {
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const bump = (value: BigNumberish, percent: number | BigNumber): BigNumber => {
|
||||||
|
const hundredPercents = BigNumber.from(100);
|
||||||
|
|
||||||
|
return BigNumber.from(value).mul(hundredPercents.add(percent)).div(hundredPercents);
|
||||||
|
};
|
||||||
|
@ -23,8 +23,8 @@ export const relayerProcessor: RelayerProcessor = async (job) => {
|
|||||||
const txService = getTxService();
|
const txService = getTxService();
|
||||||
txService.currentJob = job;
|
txService.currentJob = job;
|
||||||
const withdrawalData = job.data;
|
const withdrawalData = job.data;
|
||||||
await txService.checkTornadoFee(withdrawalData);
|
|
||||||
const txData = await txService.prepareTxData(withdrawalData);
|
const txData = await txService.prepareTxData(withdrawalData);
|
||||||
|
await txService.checkTornadoFee(withdrawalData, txData);
|
||||||
return await txService.sendTx(txData);
|
return await txService.sendTx(txData);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if ((e instanceof ExecutionError && e.code === 'REVERTED') || job.attemptsMade === txJobAttempts) {
|
if ((e instanceof ExecutionError && e.code === 'REVERTED') || job.attemptsMade === txJobAttempts) {
|
||||||
|
@ -27,7 +27,7 @@ import { availableIds, netIds, NetInstances } from 'torn-token';
|
|||||||
import { getAddress } from 'ethers/lib/utils';
|
import { getAddress } from 'ethers/lib/utils';
|
||||||
import { BigNumber, providers, Wallet } from 'ethers';
|
import { BigNumber, providers, Wallet } from 'ethers';
|
||||||
import { container, singleton } from 'tsyringe';
|
import { container, singleton } from 'tsyringe';
|
||||||
import { FallbackGasPrices } from 'gas-price-oracle';
|
import { FallbackGasPrices } from '@tornado/gas-price-oracle';
|
||||||
import { RedisStore } from '../modules/redis';
|
import { RedisStore } from '../modules/redis';
|
||||||
|
|
||||||
type relayerQueueName = `relayer_${availableIds}`;
|
type relayerQueueName = `relayer_${availableIds}`;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { TransactionData, TxManager } from 'tx-manager';
|
import { TransactionData, TxManager } from 'tx-manager';
|
||||||
import { GasPriceOracle } from 'gas-price-oracle';
|
import { GasPriceOracle } from '@tornado/gas-price-oracle';
|
||||||
import { Provider } from '@ethersproject/providers';
|
import { Provider } from '@ethersproject/providers';
|
||||||
import { serialize } from '@ethersproject/transactions';
|
import { serialize } from '@ethersproject/transactions';
|
||||||
import { formatEther, parseUnits } from 'ethers/lib/utils';
|
import { formatEther, parseUnits } from 'ethers/lib/utils';
|
||||||
@ -12,7 +12,7 @@ import { Job } from 'bullmq';
|
|||||||
import { RelayerJobData } from '../queue';
|
import { RelayerJobData } from '../queue';
|
||||||
import { ConfigService } from './config.service';
|
import { ConfigService } from './config.service';
|
||||||
import { container, injectable } from 'tsyringe';
|
import { container, injectable } from 'tsyringe';
|
||||||
import { parseJSON } from '../modules/utils';
|
import { parseJSON, bump } from '../modules/utils';
|
||||||
import { getOvmGasPriceOracle } from '../modules/contracts';
|
import { getOvmGasPriceOracle } from '../modules/contracts';
|
||||||
|
|
||||||
export type WithdrawalData = {
|
export type WithdrawalData = {
|
||||||
@ -50,6 +50,9 @@ export class TxService {
|
|||||||
const gasPriceOracleConfig = {
|
const gasPriceOracleConfig = {
|
||||||
defaultRpc: rpcUrl,
|
defaultRpc: rpcUrl,
|
||||||
chainId: netId,
|
chainId: netId,
|
||||||
|
minPriority: netId === ChainIds.ethereum || ChainIds.goerli ? 2 : 0.05,
|
||||||
|
percentile: 5,
|
||||||
|
blocksCount: 20,
|
||||||
fallbackGasPrices: this.config?.fallbackGasPrices,
|
fallbackGasPrices: this.config?.fallbackGasPrices,
|
||||||
};
|
};
|
||||||
this.txManager = new TxManager({
|
this.txManager = new TxManager({
|
||||||
@ -116,15 +119,64 @@ export class TxService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getGasPrice(): Promise<BigNumber> {
|
||||||
|
let bumpPercent: number;
|
||||||
|
switch (netId) {
|
||||||
|
case ChainIds.goerli:
|
||||||
|
bumpPercent = 50;
|
||||||
|
break;
|
||||||
|
case ChainIds.polygon:
|
||||||
|
case ChainIds.avalanche:
|
||||||
|
case ChainIds.xdai:
|
||||||
|
bumpPercent = 30;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bumpPercent = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const gasParams = await this.oracle.getTxGasParams({
|
||||||
|
legacySpeed: 'fast',
|
||||||
|
bumpPercent,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(BigNumber.from(gasParams['maxFeePerGas']).toString());
|
||||||
|
|
||||||
|
return BigNumber.from(gasParams['maxFeePerGas'] || gasParams['gasPrice']);
|
||||||
|
} catch (e) {
|
||||||
|
const feeData = await this.provider.getFeeData();
|
||||||
|
return bump(feeData.maxFeePerGas, bumpPercent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async estimateGasLimit(txData: TransactionData): Promise<BigNumber> {
|
||||||
|
try {
|
||||||
|
const fetchedGasLimit = await this.provider.estimateGas(txData);
|
||||||
|
const bumped = bump(fetchedGasLimit, 10);
|
||||||
|
console.log('Gas limit: ', bumped.toString());
|
||||||
|
return bumped;
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Estimation error: ', e);
|
||||||
|
return BigNumber.from(this.gasLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async prepareTxData(data: WithdrawalData): Promise<TransactionData> {
|
async prepareTxData(data: WithdrawalData): Promise<TransactionData> {
|
||||||
const { contract, proof, args } = data;
|
const { contract, proof, args } = data;
|
||||||
const calldata = this.tornadoProxy.interface.encodeFunctionData('withdraw', [contract, proof, ...args]);
|
const calldata = this.tornadoProxy.interface.encodeFunctionData('withdraw', [contract, proof, ...args]);
|
||||||
return {
|
|
||||||
|
const gasPrice = await this.getGasPrice();
|
||||||
|
const incompleteTxData: TransactionData = {
|
||||||
value: args[5],
|
value: args[5],
|
||||||
to: this.tornadoProxy.address,
|
to: this.tornadoProxy.address,
|
||||||
|
from: this.txManager.address, // Required to estimate relayerRegistry.burn for Ethereum Mainnet withdrawals
|
||||||
data: calldata,
|
data: calldata,
|
||||||
gasLimit: this.gasLimit,
|
gasLimit: this.gasLimit,
|
||||||
|
gasPrice: gasPrice,
|
||||||
};
|
};
|
||||||
|
const gasLimit = await this.estimateGasLimit(incompleteTxData);
|
||||||
|
|
||||||
|
return Object.assign(incompleteTxData, { gasLimit });
|
||||||
}
|
}
|
||||||
|
|
||||||
async getL1Fee(data: WithdrawalData, gasPrice: BigNumber) {
|
async getL1Fee(data: WithdrawalData, gasPrice: BigNumber) {
|
||||||
@ -145,18 +197,14 @@ export class TxService {
|
|||||||
return await ovmOracle.getL1Fee(tx);
|
return await ovmOracle.getL1Fee(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkTornadoFee(data: WithdrawalData) {
|
async checkTornadoFee(data: WithdrawalData, txData: TransactionData) {
|
||||||
const { contract, args } = data;
|
const { contract, args } = data;
|
||||||
const instance = this.config.getInstance(contract);
|
const instance = this.config.getInstance(contract);
|
||||||
if (!instance) throw new Error('Instance not found');
|
if (!instance) throw new Error('Instance not found');
|
||||||
const { currency, amount, decimals } = instance;
|
const { currency, amount, decimals } = instance;
|
||||||
const [fee, refund] = [args[4], args[5]].map(BigNumber.from);
|
const [fee, refund] = [args[4], args[5]].map(BigNumber.from);
|
||||||
const gasPrice = await this.getGasPrice();
|
const gasPrice = BigNumber.from(txData.gasPrice);
|
||||||
let gasLimit = this.gasLimit;
|
let operationCost = gasPrice.mul(txData.gasLimit);
|
||||||
if (!this.config.isLightMode) {
|
|
||||||
gasLimit = gasLimits[RelayerJobType.TORNADO_WITHDRAW];
|
|
||||||
}
|
|
||||||
let operationCost = gasPrice.mul(gasLimit);
|
|
||||||
|
|
||||||
if (netId === ChainIds.optimism) {
|
if (netId === ChainIds.optimism) {
|
||||||
const l1Fee = await this.getL1Fee(data, gasPrice);
|
const l1Fee = await this.getL1Fee(data, gasPrice);
|
||||||
@ -183,15 +231,6 @@ export class TxService {
|
|||||||
throw new Error('Provided fee is not enough. Probably it is a Gas Price spike, try to resubmit.');
|
throw new Error('Provided fee is not enough. Probably it is a Gas Price spike, try to resubmit.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getGasPrice(): Promise<BigNumber> {
|
|
||||||
const gasPrices = await this.oracle.gasPrices();
|
|
||||||
let gasPrice = gasPrices['fast'];
|
|
||||||
if ('maxFeePerGas' in gasPrices) {
|
|
||||||
gasPrice = gasPrices['maxFeePerGas'];
|
|
||||||
}
|
|
||||||
return parseUnits(String(gasPrice), 'gwei');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default () => container.resolve(TxService);
|
export default () => container.resolve(TxService);
|
||||||
|
21
yarn.lock
21
yarn.lock
@ -857,6 +857,15 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect "^1.0.1"
|
defer-to-connect "^1.0.1"
|
||||||
|
|
||||||
|
"@tornado/gas-price-oracle@^0.5.3":
|
||||||
|
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#fb5423dddee2f52edbc16174c5ddce90bea5413d"
|
||||||
|
integrity sha512-LpVfPiPIz3FOmJdiqJf/yoeO5n9/Pd5jgtdY+6hB9lNW0AiWhylhpScojICViS+3OL9QC8CoTlgr+kbfGeO9pQ==
|
||||||
|
dependencies:
|
||||||
|
axios "^0.21.2"
|
||||||
|
bignumber.js "^9.0.0"
|
||||||
|
node-cache "^5.1.2"
|
||||||
|
|
||||||
"@tsconfig/node10@^1.0.7":
|
"@tsconfig/node10@^1.0.7":
|
||||||
version "1.0.9"
|
version "1.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
|
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
|
||||||
@ -1835,6 +1844,11 @@ clone-response@^1.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mimic-response "^1.0.0"
|
mimic-response "^1.0.0"
|
||||||
|
|
||||||
|
clone@2.x:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
|
||||||
|
integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
|
||||||
|
|
||||||
cluster-key-slot@^1.1.0:
|
cluster-key-slot@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d"
|
resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d"
|
||||||
@ -4427,6 +4441,13 @@ node-addon-api@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
|
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
|
||||||
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
|
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
|
||||||
|
|
||||||
|
node-cache@^5.1.2:
|
||||||
|
version "5.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d"
|
||||||
|
integrity sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==
|
||||||
|
dependencies:
|
||||||
|
clone "2.x"
|
||||||
|
|
||||||
node-fetch@2, node-fetch@^2.6.7:
|
node-fetch@2, node-fetch@^2.6.7:
|
||||||
version "2.6.7"
|
version "2.6.7"
|
||||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
|
||||||
|
Loading…
Reference in New Issue
Block a user