Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
c9f43ff292 |
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tornado/tornado-oracles",
|
||||
"version": "3.3.0",
|
||||
"version": "3.4.0",
|
||||
"description": "Oracles for Tornado-specific transactions & actions",
|
||||
"main": "./lib/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
@ -29,7 +29,6 @@
|
||||
"author": "Theo",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tornado/gas-price-oracle": "^0.5.3",
|
||||
"@tornado/tornado-config": "^2.0.0",
|
||||
"@types/node": "^20.5.1",
|
||||
"bignumber.js": "^9.1.1",
|
||||
|
@ -9,6 +9,7 @@ export enum ChainId {
|
||||
OPTIMISM = 10,
|
||||
ARBITRUM = 42161,
|
||||
AVAX = 43114,
|
||||
SEPOLIA = 11155111,
|
||||
}
|
||||
|
||||
export enum InstanceTokenSymbol {
|
||||
@ -72,6 +73,12 @@ export const defaultGasPrices: GasPricesConfig = {
|
||||
standard: 25,
|
||||
low: 25,
|
||||
},
|
||||
[ChainId.SEPOLIA]: {
|
||||
instant: 80,
|
||||
fast: 50,
|
||||
standard: 25,
|
||||
low: 8,
|
||||
},
|
||||
};
|
||||
|
||||
type GasLimitConfig = {
|
||||
@ -87,6 +94,7 @@ export const defaultWithdrawalGasLimit: GasLimitConfig = {
|
||||
[ChainId.BSC]: 390000,
|
||||
[ChainId.POLYGON]: 390000,
|
||||
[ChainId.XDAI]: 390000,
|
||||
[ChainId.SEPOLIA]: 550000,
|
||||
};
|
||||
|
||||
type InstanceTokenGasLimitConfig = {
|
||||
@ -102,5 +110,6 @@ export const defaultInstanceTokensGasLimit: InstanceTokenGasLimitConfig = {
|
||||
};
|
||||
|
||||
export const optimismL1FeeOracleAddress = '0x420000000000000000000000000000000000000F';
|
||||
export const offchainOracleAddress = '0x07D91f5fb9Bf7798734C3f606dB065549F6893bb';
|
||||
export const multiCallAddress = '0xda3c19c6fe954576707fa24695efb830d9cca1ca';
|
||||
export const offchainOracleAddress = '0x00000000000D6FFc74A8feb35aF5827bf57f6786';
|
||||
export const sepoliaOffchainOracleAddress = '0x1f89EAF03E5b260Bc6D4Ae3c3334b1B750F3e127';
|
||||
export const multiCallAddress = '0xcA11bde05977b3631167028862bE2a173976CA11';
|
||||
|
@ -1,30 +1,137 @@
|
||||
/* Autogenerated file. Do not edit manually. */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import type { BaseContract, BigNumber, BytesLike, CallOverrides, PopulatedTransaction, Signer, utils } from 'ethers';
|
||||
import type {
|
||||
BaseContract,
|
||||
BigNumber,
|
||||
BigNumberish,
|
||||
BytesLike,
|
||||
CallOverrides,
|
||||
ContractTransaction,
|
||||
PayableOverrides,
|
||||
PopulatedTransaction,
|
||||
Signer,
|
||||
utils,
|
||||
} from 'ethers';
|
||||
import type { FunctionFragment, Result } from '@ethersproject/abi';
|
||||
import type { Listener, Provider } from '@ethersproject/providers';
|
||||
import type { TypedEventFilter, TypedEvent, TypedListener, OnEvent } from './common';
|
||||
|
||||
export declare namespace MultiCall {
|
||||
export type CallStruct = { to: string; data: BytesLike };
|
||||
export declare namespace Multicall3 {
|
||||
export type CallStruct = { target: string; callData: BytesLike };
|
||||
|
||||
export type CallStructOutput = [string, string] & {
|
||||
to: string;
|
||||
data: string;
|
||||
target: string;
|
||||
callData: string;
|
||||
};
|
||||
|
||||
export type Call3Struct = {
|
||||
target: string;
|
||||
allowFailure: boolean;
|
||||
callData: BytesLike;
|
||||
};
|
||||
|
||||
export type Call3StructOutput = [string, boolean, string] & {
|
||||
target: string;
|
||||
allowFailure: boolean;
|
||||
callData: string;
|
||||
};
|
||||
|
||||
export type ResultStruct = { success: boolean; returnData: BytesLike };
|
||||
|
||||
export type ResultStructOutput = [boolean, string] & {
|
||||
success: boolean;
|
||||
returnData: string;
|
||||
};
|
||||
|
||||
export type Call3ValueStruct = {
|
||||
target: string;
|
||||
allowFailure: boolean;
|
||||
value: BigNumberish;
|
||||
callData: BytesLike;
|
||||
};
|
||||
|
||||
export type Call3ValueStructOutput = [string, boolean, BigNumber, string] & {
|
||||
target: string;
|
||||
allowFailure: boolean;
|
||||
value: BigNumber;
|
||||
callData: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MulticallAbiInterface extends utils.Interface {
|
||||
functions: {
|
||||
'multicall((address,bytes)[])': FunctionFragment;
|
||||
'aggregate((address,bytes)[])': FunctionFragment;
|
||||
'aggregate3((address,bool,bytes)[])': FunctionFragment;
|
||||
'aggregate3Value((address,bool,uint256,bytes)[])': FunctionFragment;
|
||||
'blockAndAggregate((address,bytes)[])': FunctionFragment;
|
||||
'getBasefee()': FunctionFragment;
|
||||
'getBlockHash(uint256)': FunctionFragment;
|
||||
'getBlockNumber()': FunctionFragment;
|
||||
'getChainId()': FunctionFragment;
|
||||
'getCurrentBlockCoinbase()': FunctionFragment;
|
||||
'getCurrentBlockDifficulty()': FunctionFragment;
|
||||
'getCurrentBlockGasLimit()': FunctionFragment;
|
||||
'getCurrentBlockTimestamp()': FunctionFragment;
|
||||
'getEthBalance(address)': FunctionFragment;
|
||||
'getLastBlockHash()': FunctionFragment;
|
||||
'tryAggregate(bool,(address,bytes)[])': FunctionFragment;
|
||||
'tryBlockAndAggregate(bool,(address,bytes)[])': FunctionFragment;
|
||||
};
|
||||
|
||||
getFunction(nameOrSignatureOrTopic: 'multicall'): FunctionFragment;
|
||||
getFunction(
|
||||
nameOrSignatureOrTopic:
|
||||
| 'aggregate'
|
||||
| 'aggregate3'
|
||||
| 'aggregate3Value'
|
||||
| 'blockAndAggregate'
|
||||
| 'getBasefee'
|
||||
| 'getBlockHash'
|
||||
| 'getBlockNumber'
|
||||
| 'getChainId'
|
||||
| 'getCurrentBlockCoinbase'
|
||||
| 'getCurrentBlockDifficulty'
|
||||
| 'getCurrentBlockGasLimit'
|
||||
| 'getCurrentBlockTimestamp'
|
||||
| 'getEthBalance'
|
||||
| 'getLastBlockHash'
|
||||
| 'tryAggregate'
|
||||
| 'tryBlockAndAggregate',
|
||||
): FunctionFragment;
|
||||
|
||||
encodeFunctionData(functionFragment: 'multicall', values: [MultiCall.CallStruct[]]): string;
|
||||
encodeFunctionData(functionFragment: 'aggregate', values: [Multicall3.CallStruct[]]): string;
|
||||
encodeFunctionData(functionFragment: 'aggregate3', values: [Multicall3.Call3Struct[]]): string;
|
||||
encodeFunctionData(functionFragment: 'aggregate3Value', values: [Multicall3.Call3ValueStruct[]]): string;
|
||||
encodeFunctionData(functionFragment: 'blockAndAggregate', values: [Multicall3.CallStruct[]]): string;
|
||||
encodeFunctionData(functionFragment: 'getBasefee', values?: undefined): string;
|
||||
encodeFunctionData(functionFragment: 'getBlockHash', values: [BigNumberish]): string;
|
||||
encodeFunctionData(functionFragment: 'getBlockNumber', values?: undefined): string;
|
||||
encodeFunctionData(functionFragment: 'getChainId', values?: undefined): string;
|
||||
encodeFunctionData(functionFragment: 'getCurrentBlockCoinbase', values?: undefined): string;
|
||||
encodeFunctionData(functionFragment: 'getCurrentBlockDifficulty', values?: undefined): string;
|
||||
encodeFunctionData(functionFragment: 'getCurrentBlockGasLimit', values?: undefined): string;
|
||||
encodeFunctionData(functionFragment: 'getCurrentBlockTimestamp', values?: undefined): string;
|
||||
encodeFunctionData(functionFragment: 'getEthBalance', values: [string]): string;
|
||||
encodeFunctionData(functionFragment: 'getLastBlockHash', values?: undefined): string;
|
||||
encodeFunctionData(functionFragment: 'tryAggregate', values: [boolean, Multicall3.CallStruct[]]): string;
|
||||
encodeFunctionData(functionFragment: 'tryBlockAndAggregate', values: [boolean, Multicall3.CallStruct[]]): string;
|
||||
|
||||
decodeFunctionResult(functionFragment: 'multicall', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'aggregate', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'aggregate3', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'aggregate3Value', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'blockAndAggregate', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'getBasefee', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'getBlockHash', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'getBlockNumber', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'getChainId', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'getCurrentBlockCoinbase', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'getCurrentBlockDifficulty', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'getCurrentBlockGasLimit', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'getCurrentBlockTimestamp', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'getEthBalance', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'getLastBlockHash', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'tryAggregate', data: BytesLike): Result;
|
||||
decodeFunctionResult(functionFragment: 'tryBlockAndAggregate', data: BytesLike): Result;
|
||||
|
||||
events: {};
|
||||
}
|
||||
@ -52,31 +159,275 @@ export interface MulticallAbi extends BaseContract {
|
||||
removeListener: OnEvent<this>;
|
||||
|
||||
functions: {
|
||||
multicall(
|
||||
calls: MultiCall.CallStruct[],
|
||||
overrides?: CallOverrides,
|
||||
): Promise<[string[], boolean[]] & { results: string[]; success: boolean[] }>;
|
||||
aggregate(
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
aggregate3(
|
||||
calls: Multicall3.Call3Struct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
aggregate3Value(
|
||||
calls: Multicall3.Call3ValueStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
blockAndAggregate(
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
getBasefee(overrides?: CallOverrides): Promise<[BigNumber] & { basefee: BigNumber }>;
|
||||
|
||||
getBlockHash(blockNumber: BigNumberish, overrides?: CallOverrides): Promise<[string] & { blockHash: string }>;
|
||||
|
||||
getBlockNumber(overrides?: CallOverrides): Promise<[BigNumber] & { blockNumber: BigNumber }>;
|
||||
|
||||
getChainId(overrides?: CallOverrides): Promise<[BigNumber] & { chainid: BigNumber }>;
|
||||
|
||||
getCurrentBlockCoinbase(overrides?: CallOverrides): Promise<[string] & { coinbase: string }>;
|
||||
|
||||
getCurrentBlockDifficulty(overrides?: CallOverrides): Promise<[BigNumber] & { difficulty: BigNumber }>;
|
||||
|
||||
getCurrentBlockGasLimit(overrides?: CallOverrides): Promise<[BigNumber] & { gaslimit: BigNumber }>;
|
||||
|
||||
getCurrentBlockTimestamp(overrides?: CallOverrides): Promise<[BigNumber] & { timestamp: BigNumber }>;
|
||||
|
||||
getEthBalance(addr: string, overrides?: CallOverrides): Promise<[BigNumber] & { balance: BigNumber }>;
|
||||
|
||||
getLastBlockHash(overrides?: CallOverrides): Promise<[string] & { blockHash: string }>;
|
||||
|
||||
tryAggregate(
|
||||
requireSuccess: boolean,
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
tryBlockAndAggregate(
|
||||
requireSuccess: boolean,
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
};
|
||||
|
||||
multicall(
|
||||
calls: MultiCall.CallStruct[],
|
||||
overrides?: CallOverrides,
|
||||
): Promise<[string[], boolean[]] & { results: string[]; success: boolean[] }>;
|
||||
aggregate(
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
aggregate3(
|
||||
calls: Multicall3.Call3Struct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
aggregate3Value(
|
||||
calls: Multicall3.Call3ValueStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
blockAndAggregate(
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
getBasefee(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getBlockHash(blockNumber: BigNumberish, overrides?: CallOverrides): Promise<string>;
|
||||
|
||||
getBlockNumber(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getChainId(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getCurrentBlockCoinbase(overrides?: CallOverrides): Promise<string>;
|
||||
|
||||
getCurrentBlockDifficulty(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getCurrentBlockGasLimit(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getCurrentBlockTimestamp(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getEthBalance(addr: string, overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getLastBlockHash(overrides?: CallOverrides): Promise<string>;
|
||||
|
||||
tryAggregate(
|
||||
requireSuccess: boolean,
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
tryBlockAndAggregate(
|
||||
requireSuccess: boolean,
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<ContractTransaction>;
|
||||
|
||||
callStatic: {
|
||||
multicall(
|
||||
calls: MultiCall.CallStruct[],
|
||||
aggregate(
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: CallOverrides,
|
||||
): Promise<[string[], boolean[]] & { results: string[]; success: boolean[] }>;
|
||||
): Promise<[BigNumber, string[]] & { blockNumber: BigNumber; returnData: string[] }>;
|
||||
|
||||
aggregate3(calls: Multicall3.Call3Struct[], overrides?: CallOverrides): Promise<Multicall3.ResultStructOutput[]>;
|
||||
|
||||
aggregate3Value(
|
||||
calls: Multicall3.Call3ValueStruct[],
|
||||
overrides?: CallOverrides,
|
||||
): Promise<Multicall3.ResultStructOutput[]>;
|
||||
|
||||
blockAndAggregate(
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: CallOverrides,
|
||||
): Promise<
|
||||
[BigNumber, string, Multicall3.ResultStructOutput[]] & {
|
||||
blockNumber: BigNumber;
|
||||
blockHash: string;
|
||||
returnData: Multicall3.ResultStructOutput[];
|
||||
}
|
||||
>;
|
||||
|
||||
getBasefee(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getBlockHash(blockNumber: BigNumberish, overrides?: CallOverrides): Promise<string>;
|
||||
|
||||
getBlockNumber(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getChainId(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getCurrentBlockCoinbase(overrides?: CallOverrides): Promise<string>;
|
||||
|
||||
getCurrentBlockDifficulty(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getCurrentBlockGasLimit(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getCurrentBlockTimestamp(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getEthBalance(addr: string, overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getLastBlockHash(overrides?: CallOverrides): Promise<string>;
|
||||
|
||||
tryAggregate(
|
||||
requireSuccess: boolean,
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: CallOverrides,
|
||||
): Promise<Multicall3.ResultStructOutput[]>;
|
||||
|
||||
tryBlockAndAggregate(
|
||||
requireSuccess: boolean,
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: CallOverrides,
|
||||
): Promise<
|
||||
[BigNumber, string, Multicall3.ResultStructOutput[]] & {
|
||||
blockNumber: BigNumber;
|
||||
blockHash: string;
|
||||
returnData: Multicall3.ResultStructOutput[];
|
||||
}
|
||||
>;
|
||||
};
|
||||
|
||||
filters: {};
|
||||
|
||||
estimateGas: {
|
||||
multicall(calls: MultiCall.CallStruct[], overrides?: CallOverrides): Promise<BigNumber>;
|
||||
aggregate(calls: Multicall3.CallStruct[], overrides?: PayableOverrides & { from?: string }): Promise<BigNumber>;
|
||||
|
||||
aggregate3(calls: Multicall3.Call3Struct[], overrides?: PayableOverrides & { from?: string }): Promise<BigNumber>;
|
||||
|
||||
aggregate3Value(
|
||||
calls: Multicall3.Call3ValueStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<BigNumber>;
|
||||
|
||||
blockAndAggregate(
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<BigNumber>;
|
||||
|
||||
getBasefee(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getBlockHash(blockNumber: BigNumberish, overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getBlockNumber(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getChainId(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getCurrentBlockCoinbase(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getCurrentBlockDifficulty(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getCurrentBlockGasLimit(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getCurrentBlockTimestamp(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getEthBalance(addr: string, overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
getLastBlockHash(overrides?: CallOverrides): Promise<BigNumber>;
|
||||
|
||||
tryAggregate(
|
||||
requireSuccess: boolean,
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<BigNumber>;
|
||||
|
||||
tryBlockAndAggregate(
|
||||
requireSuccess: boolean,
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<BigNumber>;
|
||||
};
|
||||
|
||||
populateTransaction: {
|
||||
multicall(calls: MultiCall.CallStruct[], overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
aggregate(
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<PopulatedTransaction>;
|
||||
|
||||
aggregate3(
|
||||
calls: Multicall3.Call3Struct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<PopulatedTransaction>;
|
||||
|
||||
aggregate3Value(
|
||||
calls: Multicall3.Call3ValueStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<PopulatedTransaction>;
|
||||
|
||||
blockAndAggregate(
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<PopulatedTransaction>;
|
||||
|
||||
getBasefee(overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
|
||||
getBlockHash(blockNumber: BigNumberish, overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
|
||||
getBlockNumber(overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
|
||||
getChainId(overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
|
||||
getCurrentBlockCoinbase(overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
|
||||
getCurrentBlockDifficulty(overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
|
||||
getCurrentBlockGasLimit(overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
|
||||
getCurrentBlockTimestamp(overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
|
||||
getEthBalance(addr: string, overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
|
||||
getLastBlockHash(overrides?: CallOverrides): Promise<PopulatedTransaction>;
|
||||
|
||||
tryAggregate(
|
||||
requireSuccess: boolean,
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<PopulatedTransaction>;
|
||||
|
||||
tryBlockAndAggregate(
|
||||
requireSuccess: boolean,
|
||||
calls: Multicall3.CallStruct[],
|
||||
overrides?: PayableOverrides & { from?: string },
|
||||
): Promise<PopulatedTransaction>;
|
||||
};
|
||||
}
|
||||
|
@ -1,12 +1,21 @@
|
||||
import { OptimismL1FeeOracleAbi__factory, OffchainOracleAbi__factory, MulticallAbi__factory } from './';
|
||||
import { optimismL1FeeOracleAddress, offchainOracleAddress, multiCallAddress } from '../config';
|
||||
import {
|
||||
optimismL1FeeOracleAddress,
|
||||
offchainOracleAddress,
|
||||
multiCallAddress,
|
||||
sepoliaOffchainOracleAddress,
|
||||
} from '../config';
|
||||
import { Provider } from '@ethersproject/abstract-provider';
|
||||
import { ChainId } from '../config';
|
||||
|
||||
export const getOptimismL1FeeOracle = (provider: Provider) => {
|
||||
return OptimismL1FeeOracleAbi__factory.connect(optimismL1FeeOracleAddress, provider);
|
||||
};
|
||||
|
||||
export const getOffchainOracleContract = (provider: Provider) => {
|
||||
export const getOffchainOracleContract = (provider: Provider, chainId?: ChainId) => {
|
||||
if (chainId === ChainId.SEPOLIA) {
|
||||
return OffchainOracleAbi__factory.connect(sepoliaOffchainOracleAddress, provider);
|
||||
}
|
||||
return OffchainOracleAbi__factory.connect(offchainOracleAddress, provider);
|
||||
};
|
||||
|
||||
|
@ -13,36 +13,438 @@ const _abi = [
|
||||
components: [
|
||||
{
|
||||
internalType: 'address',
|
||||
name: 'to',
|
||||
name: 'target',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'data',
|
||||
name: 'callData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct MultiCall.Call[]',
|
||||
internalType: 'struct Multicall3.Call[]',
|
||||
name: 'calls',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
name: 'multicall',
|
||||
name: 'aggregate',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'bytes[]',
|
||||
name: 'results',
|
||||
type: 'bytes[]',
|
||||
internalType: 'uint256',
|
||||
name: 'blockNumber',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
internalType: 'bool[]',
|
||||
name: 'success',
|
||||
type: 'bool[]',
|
||||
internalType: 'bytes[]',
|
||||
name: 'returnData',
|
||||
type: 'bytes[]',
|
||||
},
|
||||
],
|
||||
stateMutability: 'payable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
components: [
|
||||
{
|
||||
internalType: 'address',
|
||||
name: 'target',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
internalType: 'bool',
|
||||
name: 'allowFailure',
|
||||
type: 'bool',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'callData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct Multicall3.Call3[]',
|
||||
name: 'calls',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
name: 'aggregate3',
|
||||
outputs: [
|
||||
{
|
||||
components: [
|
||||
{
|
||||
internalType: 'bool',
|
||||
name: 'success',
|
||||
type: 'bool',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'returnData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct Multicall3.Result[]',
|
||||
name: 'returnData',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
stateMutability: 'payable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
components: [
|
||||
{
|
||||
internalType: 'address',
|
||||
name: 'target',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
internalType: 'bool',
|
||||
name: 'allowFailure',
|
||||
type: 'bool',
|
||||
},
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'value',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'callData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct Multicall3.Call3Value[]',
|
||||
name: 'calls',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
name: 'aggregate3Value',
|
||||
outputs: [
|
||||
{
|
||||
components: [
|
||||
{
|
||||
internalType: 'bool',
|
||||
name: 'success',
|
||||
type: 'bool',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'returnData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct Multicall3.Result[]',
|
||||
name: 'returnData',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
stateMutability: 'payable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
components: [
|
||||
{
|
||||
internalType: 'address',
|
||||
name: 'target',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'callData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct Multicall3.Call[]',
|
||||
name: 'calls',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
name: 'blockAndAggregate',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'blockNumber',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes32',
|
||||
name: 'blockHash',
|
||||
type: 'bytes32',
|
||||
},
|
||||
{
|
||||
components: [
|
||||
{
|
||||
internalType: 'bool',
|
||||
name: 'success',
|
||||
type: 'bool',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'returnData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct Multicall3.Result[]',
|
||||
name: 'returnData',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
stateMutability: 'payable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: 'getBasefee',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'basefee',
|
||||
type: 'uint256',
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'blockNumber',
|
||||
type: 'uint256',
|
||||
},
|
||||
],
|
||||
name: 'getBlockHash',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'bytes32',
|
||||
name: 'blockHash',
|
||||
type: 'bytes32',
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: 'getBlockNumber',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'blockNumber',
|
||||
type: 'uint256',
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: 'getChainId',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'chainid',
|
||||
type: 'uint256',
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: 'getCurrentBlockCoinbase',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'address',
|
||||
name: 'coinbase',
|
||||
type: 'address',
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: 'getCurrentBlockDifficulty',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'difficulty',
|
||||
type: 'uint256',
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: 'getCurrentBlockGasLimit',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'gaslimit',
|
||||
type: 'uint256',
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: 'getCurrentBlockTimestamp',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'timestamp',
|
||||
type: 'uint256',
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
internalType: 'address',
|
||||
name: 'addr',
|
||||
type: 'address',
|
||||
},
|
||||
],
|
||||
name: 'getEthBalance',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'balance',
|
||||
type: 'uint256',
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [],
|
||||
name: 'getLastBlockHash',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'bytes32',
|
||||
name: 'blockHash',
|
||||
type: 'bytes32',
|
||||
},
|
||||
],
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
internalType: 'bool',
|
||||
name: 'requireSuccess',
|
||||
type: 'bool',
|
||||
},
|
||||
{
|
||||
components: [
|
||||
{
|
||||
internalType: 'address',
|
||||
name: 'target',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'callData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct Multicall3.Call[]',
|
||||
name: 'calls',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
name: 'tryAggregate',
|
||||
outputs: [
|
||||
{
|
||||
components: [
|
||||
{
|
||||
internalType: 'bool',
|
||||
name: 'success',
|
||||
type: 'bool',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'returnData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct Multicall3.Result[]',
|
||||
name: 'returnData',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
stateMutability: 'payable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{
|
||||
internalType: 'bool',
|
||||
name: 'requireSuccess',
|
||||
type: 'bool',
|
||||
},
|
||||
{
|
||||
components: [
|
||||
{
|
||||
internalType: 'address',
|
||||
name: 'target',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'callData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct Multicall3.Call[]',
|
||||
name: 'calls',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
name: 'tryBlockAndAggregate',
|
||||
outputs: [
|
||||
{
|
||||
internalType: 'uint256',
|
||||
name: 'blockNumber',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes32',
|
||||
name: 'blockHash',
|
||||
type: 'bytes32',
|
||||
},
|
||||
{
|
||||
components: [
|
||||
{
|
||||
internalType: 'bool',
|
||||
name: 'success',
|
||||
type: 'bool',
|
||||
},
|
||||
{
|
||||
internalType: 'bytes',
|
||||
name: 'returnData',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
internalType: 'struct Multicall3.Result[]',
|
||||
name: 'returnData',
|
||||
type: 'tuple[]',
|
||||
},
|
||||
],
|
||||
stateMutability: 'payable',
|
||||
type: 'function',
|
||||
},
|
||||
] as const;
|
||||
|
||||
export class MulticallAbi__factory {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { GasPriceOracle } from '@tornado/gas-price-oracle';
|
||||
import { BigNumber, BigNumberish, ethers } from 'ethers';
|
||||
import BigNumberFloat from 'bignumber.js';
|
||||
import { parseUnits } from 'ethers/lib/utils';
|
||||
@ -24,10 +23,9 @@ export abstract class TornadoFeeOracle implements ITornadoFeeOracle {
|
||||
protected provider: JsonRpcProvider;
|
||||
|
||||
public constructor(
|
||||
public version: 4 | 5,
|
||||
public version: 4 | 5 | 6,
|
||||
protected chainId: ChainId,
|
||||
rpcUrl: string,
|
||||
protected oracle: GasPriceOracle,
|
||||
) {
|
||||
this.provider = new ethers.providers.JsonRpcProvider(rpcUrl);
|
||||
}
|
||||
@ -122,12 +120,41 @@ export abstract class TornadoFeeOracle implements ITornadoFeeOracle {
|
||||
* @param {number} [bumpPercent=0] Gas bump percent to prioritize transaction
|
||||
* @returns {Promise<GasPriceParams>} Estimated gas price info in WEI (hexed) - legacy object with gasPrice property or
|
||||
* EIP-1559 object with maxFeePerGas and maxPriorityFeePerGas properties
|
||||
* NOTICE: It is recommended to bump fees for EIP-1559 transactions, because they can bump 12.5% per block
|
||||
*/
|
||||
async getGasPriceParams(speed?: LegacyGasPriceKey, bumpPercent: number = 0): Promise<GasPriceParams> {
|
||||
// Use instant for BSC, because on this chain "fast" and "instant" differs more than third and "fast" transaction can take hours
|
||||
if (!speed) speed = this.chainId === ChainId.BSC ? 'instant' : 'fast';
|
||||
try {
|
||||
return await this.oracle.getTxGasParams({ legacySpeed: speed, bumpPercent });
|
||||
const [block, gasPrice, priorityFee] = await Promise.all([
|
||||
this.provider.getBlock('latest'),
|
||||
this.provider.getGasPrice(),
|
||||
(async () => {
|
||||
try {
|
||||
return BigNumber.from(
|
||||
(await this.provider.send('eth_maxPriorityFeePerGas', [])) || parseUnits('1.5', 'gwei'),
|
||||
);
|
||||
} catch {
|
||||
return parseUnits('1.5', 'gwei');
|
||||
}
|
||||
})(),
|
||||
]);
|
||||
|
||||
if (block?.baseFeePerGas?.gt(0)) {
|
||||
const maxPriorityFeePerGas = priorityFee.toHexString();
|
||||
const maxFeePerGas = bump(block.baseFeePerGas as BigNumber, bumpPercent)
|
||||
.add(priorityFee)
|
||||
.toHexString();
|
||||
|
||||
return {
|
||||
maxFeePerGas,
|
||||
maxPriorityFeePerGas,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
gasPrice: bump(gasPrice, bumpPercent).toHexString(),
|
||||
};
|
||||
} catch (e) {
|
||||
return { gasPrice: bump(fromGweiToWeiHex(defaultGasPrices[this.chainId][speed]), bumpPercent).toHexString() };
|
||||
}
|
||||
@ -256,22 +283,33 @@ export abstract class TornadoFeeOracle implements ITornadoFeeOracle {
|
||||
tokenPriceInEth,
|
||||
predefinedGasLimit,
|
||||
predefinedGasPrice,
|
||||
bumpGasLimitPercent,
|
||||
bumpGasPricePercent,
|
||||
}: GetWithdrawalFeeViaRelayerInput): Promise<HexadecimalStringifiedNumber> {
|
||||
const relayerFee = this.calculateRelayerFeeInWei(relayerFeePercent, amount, decimals);
|
||||
const { gasPrice, gasLimit } = await this.getGasParams({ tx, txType, predefinedGasLimit, predefinedGasPrice });
|
||||
const { gasPrice, gasLimit } = await this.getGasParams({
|
||||
tx,
|
||||
txType,
|
||||
predefinedGasLimit,
|
||||
predefinedGasPrice,
|
||||
bumpGasLimitPercent,
|
||||
bumpGasPricePercent,
|
||||
});
|
||||
const gasCosts = BigNumber.from(gasPrice).mul(gasLimit);
|
||||
|
||||
if ((this.chainId === ChainId.MAINNET || this.chainId === ChainId.GOERLI) && currency.toLowerCase() != 'eth') {
|
||||
if (!tokenPriceInEth) {
|
||||
console.error('Token price is required argument, if not native chain token is withdrawed');
|
||||
return '0';
|
||||
}
|
||||
const hasTokenPrice =
|
||||
typeof tokenPriceInEth === 'object' && typeof (tokenPriceInEth as BigNumber)?.gt === 'function'
|
||||
? Boolean((tokenPriceInEth as BigNumber).gt(0))
|
||||
: Boolean(tokenPriceInEth);
|
||||
|
||||
if (hasTokenPrice) {
|
||||
if (txType === 'user_withdrawal' && refundInEth === undefined)
|
||||
refundInEth = this.calculateRefundInETH(gasPrice, currency.toLowerCase() as InstanceTokenSymbol);
|
||||
|
||||
const feeInEth = BigNumber.from(gasCosts).add(refundInEth || 0);
|
||||
return convertETHToToken(feeInEth, decimals, tokenPriceInEth).add(relayerFee).toHexString();
|
||||
return convertETHToToken(feeInEth, decimals, tokenPriceInEth as BigNumberish)
|
||||
.add(relayerFee)
|
||||
.toHexString();
|
||||
}
|
||||
|
||||
return BigNumber.from(gasCosts).add(relayerFee).toHexString();
|
||||
|
@ -1,22 +1,14 @@
|
||||
import { defaultWithdrawalGasLimit } from './config';
|
||||
import { TornadoFeeOracle } from './feeOracle';
|
||||
import { ITornadoFeeOracle, TransactionData, TxType, LegacyGasPrices } from './types';
|
||||
import { GasPriceOracle } from '@tornado/gas-price-oracle';
|
||||
import { ITornadoFeeOracle, TransactionData, TxType } from './types';
|
||||
import { bump } from './utils';
|
||||
|
||||
/**
|
||||
* Oracle for V4 (old-version) transactions - estimates fee with predefined gas limit and without smart bumping
|
||||
*/
|
||||
export class TornadoFeeOracleV4 extends TornadoFeeOracle implements ITornadoFeeOracle {
|
||||
public constructor(chainId: number, rpcUrl: string, defaultGasPrices?: LegacyGasPrices) {
|
||||
const oracleConfig = {
|
||||
chainId,
|
||||
defaultRpc: rpcUrl,
|
||||
defaultFallbackGasPrices: defaultGasPrices,
|
||||
};
|
||||
const gasPriceOracle = new GasPriceOracle(oracleConfig);
|
||||
|
||||
super(4, chainId, rpcUrl, gasPriceOracle);
|
||||
public constructor(chainId: number, rpcUrl: string) {
|
||||
super(4, chainId, rpcUrl);
|
||||
}
|
||||
|
||||
async getGasLimit(tx?: TransactionData, type: TxType = 'other', bumpPercent: number = 0): Promise<number> {
|
||||
|
@ -1,14 +1,6 @@
|
||||
import { ChainId } from './config';
|
||||
import { TornadoFeeOracle } from './feeOracle';
|
||||
import {
|
||||
ITornadoFeeOracle,
|
||||
TransactionData,
|
||||
TxType,
|
||||
LegacyGasPrices,
|
||||
LegacyGasPriceKey,
|
||||
GasPriceParams,
|
||||
} from './types';
|
||||
import { GasPriceOracle } from '@tornado/gas-price-oracle';
|
||||
import { ITornadoFeeOracle, TransactionData, TxType, LegacyGasPriceKey, GasPriceParams } from './types';
|
||||
import { bump } from './utils';
|
||||
import { TornadoFeeOracleV4 } from './feeOracleV4';
|
||||
|
||||
@ -18,20 +10,10 @@ import { TornadoFeeOracleV4 } from './feeOracleV4';
|
||||
export class TornadoFeeOracleV5 extends TornadoFeeOracle implements ITornadoFeeOracle {
|
||||
private fallbackFeeOracle: TornadoFeeOracleV4;
|
||||
|
||||
public constructor(chainId: number, rpcUrl: string, defaultGasPrices?: LegacyGasPrices) {
|
||||
const oracleConfig = {
|
||||
chainId,
|
||||
defaultRpc: rpcUrl,
|
||||
minPriority: chainId === ChainId.MAINNET || chainId === ChainId.GOERLI ? 2 : chainId === ChainId.BSC ? 3 : 0.05,
|
||||
percentile: 5,
|
||||
blocksCount: 20,
|
||||
defaultFallbackGasPrices: defaultGasPrices,
|
||||
};
|
||||
const gasPriceOracle = new GasPriceOracle(oracleConfig);
|
||||
public constructor(chainId: number, rpcUrl: string) {
|
||||
super(5, chainId, rpcUrl);
|
||||
|
||||
super(5, chainId, rpcUrl, gasPriceOracle);
|
||||
|
||||
this.fallbackFeeOracle = new TornadoFeeOracleV4(chainId, rpcUrl, defaultGasPrices);
|
||||
this.fallbackFeeOracle = new TornadoFeeOracleV4(chainId, rpcUrl);
|
||||
}
|
||||
|
||||
async getGasLimit(tx?: TransactionData, type: TxType = 'other', bumpPercent: number = 20): Promise<number> {
|
||||
|
73
src/feeOracleV6.ts
Normal file
73
src/feeOracleV6.ts
Normal file
@ -0,0 +1,73 @@
|
||||
import { ChainId } from './config';
|
||||
import { TornadoFeeOracle } from './feeOracle';
|
||||
import {
|
||||
ITornadoFeeOracle,
|
||||
TransactionData,
|
||||
TxType,
|
||||
LegacyGasPriceKey,
|
||||
GasPriceParams,
|
||||
GetWithdrawalFeeViaRelayerInput,
|
||||
HexadecimalStringifiedNumber,
|
||||
} from './types';
|
||||
import { bump } from './utils';
|
||||
import { TornadoFeeOracleV5 } from './feeOracleV5';
|
||||
|
||||
/**
|
||||
* V6 version that would cover every available networks and relayers
|
||||
*
|
||||
* Ported from https://git.tornado.ws/tornadocontrib/tornado-core/src/branch/main/src/fees.ts and has been verified over time
|
||||
*/
|
||||
export class TornadoFeeOracleV6 extends TornadoFeeOracle implements ITornadoFeeOracle {
|
||||
private fallbackFeeOracle: TornadoFeeOracleV5;
|
||||
// Override value for BSC (Since old relayers use static value of 3.3 gwei)
|
||||
public overrideGasPrice?: GasPriceParams;
|
||||
|
||||
public constructor(chainId: number, rpcUrl: string, overrideGasPrice?: GasPriceParams) {
|
||||
super(6, chainId, rpcUrl);
|
||||
|
||||
this.fallbackFeeOracle = new TornadoFeeOracleV5(chainId, rpcUrl);
|
||||
this.overrideGasPrice = overrideGasPrice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply static 10% gasLimit premium as it wouldn't change across nodes or relayers
|
||||
*/
|
||||
async getGasLimit(tx?: TransactionData, type: TxType = 'other', bumpPercent: number = 10): Promise<number> {
|
||||
if (!tx || Object.keys(tx).length === 0) return this.fallbackFeeOracle.getGasLimit(tx, type, bumpPercent);
|
||||
|
||||
const fetchedGasLimit = await this.provider.estimateGas(tx);
|
||||
return bump(fetchedGasLimit, bumpPercent).toNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply static 50% gasPrice premium for EIP-1559 enabled networks
|
||||
*
|
||||
* Because Tornado Transactions are censored from block builders
|
||||
* it would take some time to be confirmed after when the transaction is broadcasted.
|
||||
*
|
||||
* We apply 50% premium to combat basefee spike (ethers.js uses 100% premium by default)
|
||||
* (Can spike 12.5% per block accoring to the EIP-1559 metrics https://metamask.io/1559/)
|
||||
*/
|
||||
async getGasPriceParams(speed?: LegacyGasPriceKey, bumpPercent?: number): Promise<GasPriceParams> {
|
||||
if (this.overrideGasPrice) {
|
||||
return this.overrideGasPrice;
|
||||
}
|
||||
if (typeof bumpPercent === 'undefined') {
|
||||
bumpPercent = this.chainId === ChainId.BSC ? undefined : 50;
|
||||
}
|
||||
return super.getGasPriceParams(speed, bumpPercent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply 20% premium from the calculated fee from UI, applies 5% fee from relayer to prevent arbitrage from refund
|
||||
*/
|
||||
async calculateWithdrawalFeeViaRelayer(
|
||||
params: GetWithdrawalFeeViaRelayerInput & { premium?: number },
|
||||
): Promise<HexadecimalStringifiedNumber> {
|
||||
const fees = await super.calculateWithdrawalFeeViaRelayer(params);
|
||||
|
||||
const premium = params.premium || (params.txType === 'user_withdrawal' ? 20 : 5);
|
||||
|
||||
return bump(fees, premium).toHexString();
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
export * from './feeOracleV4';
|
||||
export * from './feeOracleV5';
|
||||
export * from './feeOracleV6';
|
||||
export * from './tokenPriceOracle';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { MultiCall } from './contracts/MulticallAbi';
|
||||
import { Multicall3 } from './contracts/MulticallAbi';
|
||||
import { ITornadoPriceOracle, Token, TokenPrices, TokenSymbol } from './types';
|
||||
import { MulticallAbi, OffchainOracleAbi } from './contracts';
|
||||
import { getMultiCallContract, getOffchainOracleContract } from './contracts/factories';
|
||||
@ -49,9 +49,10 @@ export class TokenPriceOracle implements ITornadoPriceOracle {
|
||||
rpcUrl: string,
|
||||
private tokens: Token[] = tornadoTokens,
|
||||
private defaultTokenPrices: TokenPrices = defaultTornadoTokenPrices,
|
||||
chainId?: ChainId,
|
||||
) {
|
||||
this.provider = new ethers.providers.JsonRpcProvider(rpcUrl);
|
||||
this.oracle = getOffchainOracleContract(this.provider);
|
||||
this.oracle = getOffchainOracleContract(this.provider, chainId);
|
||||
this.multiCall = getMultiCallContract(this.provider);
|
||||
}
|
||||
|
||||
@ -65,10 +66,11 @@ export class TokenPriceOracle implements ITornadoPriceOracle {
|
||||
* @param {Token[]} [tokens] Tokens array
|
||||
* @returns Valid structure to provide to MultiCall contract
|
||||
*/
|
||||
private prepareCallData(tokens: Token[] = this.tokens): MultiCall.CallStruct[] {
|
||||
private prepareCallData(tokens: Token[] = this.tokens): Multicall3.Call3Struct[] {
|
||||
return tokens.map((token) => ({
|
||||
to: this.oracle.address,
|
||||
data: this.oracle.interface.encodeFunctionData('getRateToEth', [token.tokenAddress, true]),
|
||||
target: this.oracle.address,
|
||||
allowFailure: true,
|
||||
callData: this.oracle.interface.encodeFunctionData('getRateToEth', [token.tokenAddress, true]),
|
||||
}));
|
||||
}
|
||||
|
||||
@ -82,17 +84,17 @@ export class TokenPriceOracle implements ITornadoPriceOracle {
|
||||
if (!tokens?.length) return {};
|
||||
|
||||
const callData = this.prepareCallData(tokens);
|
||||
const { results, success } = await this.multiCall.multicall(callData);
|
||||
const results = await this.multiCall.callStatic.aggregate3(callData);
|
||||
const prices: TokenPrices = {};
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
const tokenSymbol = tokens[i].symbol.toLowerCase() as TokenSymbol;
|
||||
if (!success[i]) {
|
||||
if (!results[i].success) {
|
||||
if (this.defaultTokenPrices[tokenSymbol]) prices[tokenSymbol] = this.defaultTokenPrices[tokenSymbol];
|
||||
continue;
|
||||
}
|
||||
|
||||
const decodedRate = defaultAbiCoder.decode(['uint256'], results[i]).toString();
|
||||
const decodedRate = defaultAbiCoder.decode(['uint256'], results[i].returnData).toString();
|
||||
const tokenDecimals = BigNumber.from(10).pow(tokens[i].decimals);
|
||||
const ethDecimals = BigNumber.from(10).pow(18);
|
||||
const price = BigNumber.from(decodedRate).mul(tokenDecimals).div(ethDecimals);
|
||||
|
14
src/types.ts
14
src/types.ts
@ -1,13 +1,19 @@
|
||||
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';
|
||||
|
||||
// Type for big hexadecimal numbers, like 0x1eff87f47e37a0
|
||||
export type HexadecimalStringifiedNumber = string;
|
||||
|
||||
export type LegacyGasPriceKey = GasPriceKey;
|
||||
export type GasPriceParams = GetTxGasParamsRes;
|
||||
export type LegacyGasPriceKey = 'instant' | 'fast' | 'standard' | 'low';
|
||||
export type GasPriceParams =
|
||||
| {
|
||||
gasPrice: string;
|
||||
}
|
||||
| {
|
||||
maxFeePerGas: string;
|
||||
maxPriorityFeePerGas: string;
|
||||
};
|
||||
export type LegacyGasPrices = {
|
||||
[gasPriceType in LegacyGasPriceKey]: number;
|
||||
};
|
||||
@ -111,4 +117,6 @@ export type GetWithdrawalFeeViaRelayerInput = {
|
||||
tokenPriceInEth?: HexadecimalStringifiedNumber | string; // Token (currency) price in ETH wei, if withdrawing non-native currency
|
||||
predefinedGasPrice?: HexadecimalStringifiedNumber; // Predefined gas price for withdrawal tx (wont be calculated again in function)
|
||||
predefinedGasLimit?: number; // Predefined gas limit for withdrawal tx (wont be calculated again in function)
|
||||
bumpGasLimitPercent?: number; // Gas limit bump percent to prioritize transaction (recenlty used)
|
||||
bumpGasPricePercent?: number; // Gas price bump percent to prioritize transaction (rarely used)
|
||||
};
|
||||
|
35
yarn.lock
35
yarn.lock
@ -369,15 +369,6 @@
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@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"
|
||||
|
||||
"@tornado/tornado-config@^2.0.0":
|
||||
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#52bbc179ecb2385f71b4d56e060b68e7dd6fb8b4"
|
||||
@ -478,13 +469,6 @@ array-back@^4.0.1, array-back@^4.0.2:
|
||||
resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e"
|
||||
integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==
|
||||
|
||||
axios@^0.21.2:
|
||||
version "0.21.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
|
||||
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.0"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
@ -495,7 +479,7 @@ bech32@1.1.4:
|
||||
resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
|
||||
integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==
|
||||
|
||||
bignumber.js@^9.0.0, bignumber.js@^9.1.1:
|
||||
bignumber.js@^9.1.1:
|
||||
version "9.1.1"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6"
|
||||
integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==
|
||||
@ -567,11 +551,6 @@ chokidar@^3.5.2:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
clone@2.x:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
|
||||
integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
|
||||
|
||||
color-convert@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||
@ -718,11 +697,6 @@ find-replace@^3.0.0:
|
||||
dependencies:
|
||||
array-back "^3.0.1"
|
||||
|
||||
follow-redirects@^1.14.0:
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||
|
||||
fs-extra@^7.0.0:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
|
||||
@ -901,13 +875,6 @@ ms@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
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"
|
||||
|
||||
nodemon@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.0.1.tgz#affe822a2c5f21354466b2fc8ae83277d27dadc7"
|
||||
|
Loading…
x
Reference in New Issue
Block a user