From 76a0ccea6809ad5bee75c45f18775aa784b3b403 Mon Sep 17 00:00:00 2001 From: Theo Date: Tue, 22 Aug 2023 11:56:38 -0700 Subject: [PATCH] Fix refund calculation: we need to use different gas limits for each ERC tokens & bump lib version to 1.2.0 --- package.json | 2 +- src/config.ts | 20 ++++++++++++++++++++ src/feeOracle.ts | 21 +++++++++++---------- src/types.ts | 5 +++-- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index c175870..b24a7a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tornado/tornado-oracles", - "version": "1.1.0", + "version": "1.2.0", "description": "Gas oracle for Tornado-specific transactions", "main": "./lib/index.js", "types": "./lib/index.d.ts", diff --git a/src/config.ts b/src/config.ts index a05305a..502c9ba 100644 --- a/src/config.ts +++ b/src/config.ts @@ -11,6 +11,14 @@ export enum ChainId { AVAX = 43114, } +export enum InstanceTokenSymbol { + DAI = 'dai', + cDAI = 'cdai', + WBTC = 'wbtc', + USDT = 'usdt', + USDC = 'usdc', +} + export type GasPricesConfig = { [chainId in ChainId]: LegacyGasPrices; }; @@ -81,6 +89,18 @@ export const defaultWithdrawalGasLimit: GasLimitConfig = { [ChainId.XDAI]: 390000, }; +type InstanceTokenGasLimitConfig = { + [tokenSymbol in InstanceTokenSymbol]: number; +}; + +export const defaultInstanceTokensGasLimit: InstanceTokenGasLimitConfig = { + [InstanceTokenSymbol.DAI]: 55000, + [InstanceTokenSymbol.cDAI]: 425000, + [InstanceTokenSymbol.WBTC]: 85000, + [InstanceTokenSymbol.USDT]: 100000, + [InstanceTokenSymbol.USDC]: 80000, +}; + export const optimismL1FeeOracleAddress = '0x420000000000000000000000000000000000000F'; export const offchainOracleAddress = '0x07D91f5fb9Bf7798734C3f606dB065549F6893bb'; export const multiCallAddress = '0xda3c19c6fe954576707fa24695efb830d9cca1ca'; diff --git a/src/feeOracle.ts b/src/feeOracle.ts index 33ee0b7..20bbcaf 100644 --- a/src/feeOracle.ts +++ b/src/feeOracle.ts @@ -3,7 +3,7 @@ import { BigNumber, BigNumberish, ethers } from 'ethers'; import { parseUnits } from 'ethers/lib/utils'; import { TransactionData, TxType, ITornadoFeeOracle, LegacyGasPriceKey, GasPriceParams } from './types'; import { JsonRpcProvider } from '@ethersproject/providers'; -import { ChainId, defaultGasPrices } from './config'; +import { ChainId, defaultGasPrices, defaultInstanceTokensGasLimit, InstanceTokenSymbol } from './config'; import { bump, calculateGasPriceInWei, convertETHToToken, fromGweiToWeiHex, serializeTx } from './utils'; import { getOptimismL1FeeOracle } from './contracts/factories'; import { AvailableTokenSymbols } from '@tornado/tornado-config'; @@ -102,28 +102,29 @@ export abstract class TornadoFeeOracle implements ITornadoFeeOracle { * and if the relayer pays a commission and the transfer of tokens fails, this commission will remain to the relayer. * * Refund needed that recipient can use tokens after withdrawal (covers gas fee for send/swap) - * @param {TransactionData} [tx] Transaction data (object in web3 / ethers format) + * @param {InstanceTokenSymbol} tokenSymbol Withdrawal token (currency) symbol - for example, 'dai' * @returns {Promise} Refund amount in WEI (hexed number) */ - async calculateRefundInETH(tx?: TransactionData): Promise { + async calculateRefundInETH(tokenSymbol: InstanceTokenSymbol): Promise { // In Tornado we need to calculate refund only on user side, relayer get refund value in proof - const gas = await this.getGas(tx, 'user_withdrawal'); - return BigNumber.from(gas).mul(2).toHexString(); + const gasPrice = await this.getGasPrice(); + const gasLimit = defaultInstanceTokensGasLimit[tokenSymbol]; + return BigNumber.from(gasPrice).mul(gasLimit).mul(2).toHexString(); } /** * Get refund amount on ETH or Goerli in non-native token * @param {BigNumberish} tokenPriceInEth Token price in WEI in native currency * @param {string | number} tokenDecimals Token (currency) decimals - * @param {TransactionData} [tx] Transaction data (object in web3 / ethers format) + * @param {InstanceTokenSymbol} tokenSymbol Withdrawal token (currency) symbol - for example, 'dai' * @returns {Promise} Refund amount in WEI in selected token (hexed number) */ async calculateRefundInToken( tokenPriceInEth: BigNumberish, tokenDecimals: string | number, - tx?: TransactionData, + tokenSymbol: InstanceTokenSymbol, ): Promise { - const refundInEth = await this.calculateRefundInETH(tx); + const refundInEth = await this.calculateRefundInETH(tokenSymbol); return convertETHToToken(refundInEth, tokenDecimals, tokenPriceInEth).toHexString(); } @@ -148,7 +149,7 @@ export abstract class TornadoFeeOracle implements ITornadoFeeOracle { currency: AvailableTokenSymbols | Uppercase, amount: string | number, decimals: string | number, - refund: BigNumberish = 0, + refundInEth: BigNumberish = 0, tokenPriceInEth?: BigNumberish, ): Promise { const gasCosts = BigNumber.from(await this.getGas(tx, type)); @@ -163,7 +164,7 @@ export abstract class TornadoFeeOracle implements ITornadoFeeOracle { return '0'; } - const feeInEth = gasCosts.add(refund); + const feeInEth = gasCosts.add(refundInEth); return convertETHToToken(feeInEth, decimals, tokenPriceInEth).add(relayerFee).toHexString(); } diff --git a/src/types.ts b/src/types.ts index b6531e4..fe707a1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,6 +1,7 @@ import { BigNumberish, BytesLike } from 'ethers'; import { GasPriceKey, GetTxGasParamsRes } from '@tornado/gas-price-oracle/lib/services'; import { AvailableTokenSymbols } from '@tornado/tornado-config'; +import { InstanceTokenSymbol } from './config'; export type LegacyGasPriceKey = GasPriceKey; export type GasPriceParams = GetTxGasParamsRes; @@ -36,11 +37,11 @@ export interface ITornadoFeeOracle { getGasPrice: (type?: TxType, speed?: LegacyGasPriceKey, bumpPercent?: number) => Promise; getGasLimit: (tx?: TransactionData, type?: TxType, bumpPercent?: number) => Promise; fetchL1OptimismFee: (tx?: TransactionData) => Promise; - calculateRefundInETH: (tx?: TransactionData) => Promise; + calculateRefundInETH: (tokenSymbol: InstanceTokenSymbol) => Promise; calculateRefundInToken: ( tokenPriceInEth: BigNumberish, tokenDecimals: string | number, - tx?: TransactionData, + tokenSymbol: InstanceTokenSymbol, ) => Promise; calculateWithdrawalFeeViaRelayer: ( type: TxType,