From be969ca8c01002c1a707c937432a5e7abd4a56a4 Mon Sep 17 00:00:00 2001
From: smart_ex <sergei.smart@gmail.com>
Date: Thu, 7 Jul 2022 16:47:50 +1000
Subject: [PATCH] Fix gasLimits config, check l1Fee for optimism

---
 src/config.ts              |  7 +++--
 src/services/tx.service.ts | 63 ++++++++++++++++++++++++++++++++------
 src/types.ts               |  6 ++--
 3 files changed, 61 insertions(+), 15 deletions(-)

diff --git a/src/config.ts b/src/config.ts
index 57bf45c..974ed21 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -26,11 +26,12 @@ export const tornadoServiceFee = Number(process.env.REGULAR_TORNADO_WITHDRAW_FEE
 export const rewardAccount = process.env.REWARD_ACCOUNT;
 export const governanceAddress = '0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce';
 export const tornadoGoerliProxy = '0x454d870a72e29d5E5697f635128D18077BD04C60';
+export const ovmGasPriceOracleContract = '0x420000000000000000000000000000000000000F';
 export const gasLimits = {
   [RelayerJobType.TORNADO_WITHDRAW]: 390000,
-  WITHDRAW_WITH_EXTRA: 700000,
-  [RelayerJobType.MINING_REWARD]: 455000,
-  [RelayerJobType.MINING_WITHDRAW]: 400000,
+  [RelayerJobType.WITHDRAW_WITH_EXTRA]: 700000,
+  [RelayerJobType.OP_TORNADO_WITHDRAW]: 440000,
+  [RelayerJobType.ARB_TORNADO_WITHDRAW]: 1900000,
 };
 // export const minimumBalance = '1000000000000000000';
 // export const minimumTornBalance = '30000000000000000000';
diff --git a/src/services/tx.service.ts b/src/services/tx.service.ts
index 242a2ee..f28375f 100644
--- a/src/services/tx.service.ts
+++ b/src/services/tx.service.ts
@@ -1,17 +1,19 @@
 import { TransactionData, TxManager } from 'tx-manager';
 import { GasPriceOracle } from 'gas-price-oracle';
 import { Provider } from '@ethersproject/providers';
+import { serialize } from '@ethersproject/transactions';
 import { formatEther, parseUnits } from 'ethers/lib/utils';
 import { BigNumber, BigNumberish, BytesLike } from 'ethers';
 import { ProxyLightABI, TornadoProxyABI } from '../contracts';
-import { BASE_FEE_RESERVE_PERCENTAGE, CONFIRMATIONS, gasLimits, MAX_GAS_PRICE, tornadoServiceFee } from '../config';
-import { JobStatus, RelayerJobType } from '../types';
+import { BASE_FEE_RESERVE_PERCENTAGE, CONFIRMATIONS, gasLimits, MAX_GAS_PRICE, netId, tornadoServiceFee } from '../config';
+import { ChainIds, JobStatus, RelayerJobType } from '../types';
 import { PriceService } from './price.service';
 import { Job } from 'bullmq';
 import { RelayerJobData } from '../queue';
 import { ConfigService } from './config.service';
 import { container, injectable } from 'tsyringe';
 import { parseJSON } from '../modules/utils';
+import { getOvmGasPriceOracle } from '../modules/contracts';
 
 export type WithdrawalData = {
   contract: string;
@@ -34,6 +36,7 @@ export class TxService {
     this._currentJob = value;
   }
 
+  gasLimit: number;
   txManager: TxManager;
   tornadoProxy: TornadoProxyABI | ProxyLightABI;
   oracle: GasPriceOracle;
@@ -44,17 +47,33 @@ export class TxService {
     const { privateKey, rpcUrl, netId } = this.config;
     this.tornadoProxy = this.config.proxyContract;
     this.provider = this.tornadoProxy.provider;
+    const gasPriceOracleConfig = {
+      defaultRpc: rpcUrl,
+      chainId: netId,
+      fallbackGasPrices: this.config?.fallbackGasPrices,
+    };
     this.txManager = new TxManager({
       privateKey,
       rpcUrl,
       config: { THROW_ON_REVERT: true, CONFIRMATIONS, MAX_GAS_PRICE, BASE_FEE_RESERVE_PERCENTAGE },
+      gasPriceOracleConfig,
       provider: this.provider,
     });
-    this.oracle = new GasPriceOracle({
-      defaultRpc: rpcUrl,
-      chainId: netId,
-      fallbackGasPrices: this.config?.fallbackGasPrices,
-    });
+    this.oracle = new GasPriceOracle(gasPriceOracleConfig);
+    switch (netId) {
+      case ChainIds.ethereum:
+      case ChainIds.goerli:
+        this.gasLimit = gasLimits[RelayerJobType.WITHDRAW_WITH_EXTRA];
+        break;
+      case ChainIds.optimism:
+        this.gasLimit = gasLimits[RelayerJobType.OP_TORNADO_WITHDRAW];
+        break;
+      case ChainIds.arbitrum:
+        this.gasLimit = gasLimits[RelayerJobType.ARB_TORNADO_WITHDRAW];
+        break;
+      default:
+        this.gasLimit = gasLimits[RelayerJobType.TORNADO_WITHDRAW];
+    }
   }
 
   async updateJobData(data: Partial<RelayerJobData>) {
@@ -103,18 +122,42 @@ export class TxService {
       value: args[5],
       to: this.tornadoProxy.address,
       data: calldata,
-      gasLimit: gasLimits['WITHDRAW_WITH_EXTRA'],
+      gasLimit: this.gasLimit,
     };
   }
 
-  async checkTornadoFee({ args, contract }: WithdrawalData) {
+  async getL1Fee(data: WithdrawalData, gasPrice: BigNumber) {
+    const { contract, proof, args } = data;
+    const ovmOracle = getOvmGasPriceOracle();
+    const calldata = this.tornadoProxy.interface.encodeFunctionData('withdraw', [contract, proof, ...args]);
+    const nonce = await this.config.wallet.getTransactionCount();
+    const tx = serialize({
+      nonce,
+      type: 0,
+      data: calldata,
+      chainId: netId,
+      value: data.args[5],
+      to: this.tornadoProxy.address,
+      gasLimit: this.gasLimit,
+      gasPrice: BigNumber.from(gasPrice),
+    });
+    return await ovmOracle.getL1Fee(tx);
+  }
+
+  async checkTornadoFee(data: WithdrawalData) {
+    const { contract, args } = data;
     const instance = this.config.getInstance(contract);
     if (!instance) throw new Error('Instance not found');
     const { currency, amount, decimals } = instance;
     const [fee, refund] = [args[4], args[5]].map(BigNumber.from);
     const gasPrice = await this.getGasPrice();
     // TODO check refund value
-    const operationCost = gasPrice.mul(gasLimits[RelayerJobType.TORNADO_WITHDRAW]);
+    let operationCost = gasPrice.mul(this.gasLimit);
+
+    if (netId === ChainIds.optimism) {
+      const l1Fee = await this.getL1Fee(data, gasPrice);
+      operationCost = operationCost.add(l1Fee);
+    }
 
     const serviceFee = parseUnits(amount, decimals)
       .mul(`${tornadoServiceFee * 1e10}`)
diff --git a/src/types.ts b/src/types.ts
index 27bcea3..4caf3bb 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,7 +1,8 @@
 export enum RelayerJobType {
   TORNADO_WITHDRAW = 'TORNADO_WITHDRAW',
-  MINING_REWARD = 'MINING_REWARD',
-  MINING_WITHDRAW = 'MINING_WITHDRAW',
+  WITHDRAW_WITH_EXTRA = 'WITHDRAW_WITH_EXTRA',
+  OP_TORNADO_WITHDRAW = 'OP_TORNADO_WITHDRAW',
+  ARB_TORNADO_WITHDRAW = 'ARB_TORNADO_WITHDRAW',
 }
 
 export enum JobStatus {
@@ -19,6 +20,7 @@ export type Token = { address: string; decimals: number; symbol?: string };
 export enum ChainIds {
   'kardia' = 0,
   'ethereum' = 1,
+  'goerli' = 5,
   'ubiq' = 8,
   'optimism' = 10,
   'songbird' = 19,