From 8d735f4a9752b7ca782a73421faf310d7fb30677 Mon Sep 17 00:00:00 2001 From: nikdementev Date: Mon, 11 Oct 2021 19:06:41 +0300 Subject: [PATCH] feat: L2 (XDAI) transfer & withdrawal --- package.json | 2 +- src/abi/TornadoPool.json | 232 ++++++++++--- src/artifacts/TornadoPool.d.ts | 305 +++++++++++++++--- .../factories/TornadoPool__factory.ts | 226 ++++++++++--- src/constants/contracts.ts | 2 + src/constants/variables.ts | 4 + src/modules/api/api.validator.ts | 2 + src/modules/queue/transaction.processor.ts | 22 +- src/services/oracle.service.ts | 28 +- src/types/index.ts | 2 + yarn.lock | 15 +- 11 files changed, 683 insertions(+), 157 deletions(-) diff --git a/package.json b/package.json index c4d06c8..6aa20fd 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "bull": "^3.22.11", "class-validator": "^0.13.1", "ethers": "^5.4.1", - "gas-price-oracle": "^0.3.3", + "gas-price-oracle": "^0.4.0", "redis": "^3.1.2", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", diff --git a/src/abi/TornadoPool.json b/src/abi/TornadoPool.json index 1b3c911..1d257cb 100644 --- a/src/abi/TornadoPool.json +++ b/src/abi/TornadoPool.json @@ -20,30 +20,31 @@ "internalType": "address", "name": "_hasher", "type": "address" + }, + { + "internalType": "contract IERC6777", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_omniBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "_l1Unwrapper", + "type": "address" + }, + { + "internalType": "address", + "name": "_governance", + "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "account", - "type": "bytes" - } - ], - "name": "EncryptedAccount", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -190,6 +191,24 @@ "stateMutability": "pure", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimalWithdrawalAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maximumDepositAmount", + "type": "uint256" + } + ], + "name": "configureLimits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "currentRootIndex", @@ -235,6 +254,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "governance", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -273,7 +305,18 @@ "type": "function" }, { - "inputs": [], + "inputs": [ + { + "internalType": "uint256", + "name": "_minimalWithdrawalAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maximumDepositAmount", + "type": "uint256" + } + ], "name": "initialize", "outputs": [], "stateMutability": "nonpayable", @@ -317,6 +360,32 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "l1Unwrapper", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "levels", @@ -330,6 +399,32 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "maximumDepositAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimalWithdrawalAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "nextIndex", @@ -362,23 +457,59 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "omniBridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC6777", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenBridged", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { "components": [ { - "internalType": "bytes", - "name": "pubKey", - "type": "bytes" + "internalType": "address", + "name": "owner", + "type": "address" }, { "internalType": "bytes", - "name": "account", + "name": "publicKey", "type": "bytes" } ], - "internalType": "struct TornadoPool.Register", - "name": "args", + "internalType": "struct TornadoPool.Account", + "name": "_account", "type": "tuple" } ], @@ -392,18 +523,18 @@ { "components": [ { - "internalType": "bytes", - "name": "pubKey", - "type": "bytes" + "internalType": "address", + "name": "owner", + "type": "address" }, { "internalType": "bytes", - "name": "account", + "name": "publicKey", "type": "bytes" } ], - "internalType": "struct TornadoPool.Register", - "name": "_registerArgs", + "internalType": "struct TornadoPool.Account", + "name": "_account", "type": "tuple" }, { @@ -446,7 +577,7 @@ { "components": [ { - "internalType": "address payable", + "internalType": "address", "name": "recipient", "type": "address" }, @@ -456,7 +587,7 @@ "type": "int256" }, { - "internalType": "address payable", + "internalType": "address", "name": "relayer", "type": "address" }, @@ -474,6 +605,11 @@ "internalType": "bytes", "name": "encryptedOutput2", "type": "bytes" + }, + { + "internalType": "bool", + "name": "isL1Withdrawal", + "type": "bool" } ], "internalType": "struct TornadoPool.ExtData", @@ -483,7 +619,7 @@ ], "name": "registerAndTransact", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { @@ -505,6 +641,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC6777", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -547,7 +696,7 @@ { "components": [ { - "internalType": "address payable", + "internalType": "address", "name": "recipient", "type": "address" }, @@ -557,7 +706,7 @@ "type": "int256" }, { - "internalType": "address payable", + "internalType": "address", "name": "relayer", "type": "address" }, @@ -575,6 +724,11 @@ "internalType": "bytes", "name": "encryptedOutput2", "type": "bytes" + }, + { + "internalType": "bool", + "name": "isL1Withdrawal", + "type": "bool" } ], "internalType": "struct TornadoPool.ExtData", @@ -582,9 +736,9 @@ "type": "tuple" } ], - "name": "transaction", + "name": "transact", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { diff --git a/src/artifacts/TornadoPool.d.ts b/src/artifacts/TornadoPool.d.ts index 5fdb738..9c65951 100644 --- a/src/artifacts/TornadoPool.d.ts +++ b/src/artifacts/TornadoPool.d.ts @@ -12,7 +12,6 @@ import { BaseContract, ContractTransaction, Overrides, - PayableOverrides, CallOverrides, } from "ethers"; import { BytesLike } from "@ethersproject/bytes"; @@ -28,21 +27,30 @@ interface TornadoPoolInterface extends ethers.utils.Interface { "ROOT_HISTORY_SIZE()": FunctionFragment; "ZERO_VALUE()": FunctionFragment; "calculatePublicAmount(int256,uint256)": FunctionFragment; + "configureLimits(uint256,uint256)": FunctionFragment; "currentRootIndex()": FunctionFragment; "filledSubtrees(uint256)": FunctionFragment; "getLastRoot()": FunctionFragment; + "governance()": FunctionFragment; "hashLeftRight(bytes32,bytes32)": FunctionFragment; "hasher()": FunctionFragment; - "initialize()": FunctionFragment; + "initialize(uint256,uint256)": FunctionFragment; "isKnownRoot(bytes32)": FunctionFragment; "isSpent(bytes32)": FunctionFragment; + "l1Unwrapper()": FunctionFragment; + "lastBalance()": FunctionFragment; "levels()": FunctionFragment; + "maximumDepositAmount()": FunctionFragment; + "minimalWithdrawalAmount()": FunctionFragment; "nextIndex()": FunctionFragment; "nullifierHashes(bytes32)": FunctionFragment; + "omniBridge()": FunctionFragment; + "onTokenBridged(address,uint256,bytes)": FunctionFragment; "register(tuple)": FunctionFragment; "registerAndTransact(tuple,tuple,tuple)": FunctionFragment; "roots(uint256)": FunctionFragment; - "transaction(tuple,tuple)": FunctionFragment; + "token()": FunctionFragment; + "transact(tuple,tuple)": FunctionFragment; "verifier16()": FunctionFragment; "verifier2()": FunctionFragment; "verifyProof(tuple)": FunctionFragment; @@ -70,6 +78,10 @@ interface TornadoPoolInterface extends ethers.utils.Interface { functionFragment: "calculatePublicAmount", values: [BigNumberish, BigNumberish] ): string; + encodeFunctionData( + functionFragment: "configureLimits", + values: [BigNumberish, BigNumberish] + ): string; encodeFunctionData( functionFragment: "currentRootIndex", values?: undefined @@ -82,6 +94,10 @@ interface TornadoPoolInterface extends ethers.utils.Interface { functionFragment: "getLastRoot", values?: undefined ): string; + encodeFunctionData( + functionFragment: "governance", + values?: undefined + ): string; encodeFunctionData( functionFragment: "hashLeftRight", values: [BytesLike, BytesLike] @@ -89,27 +105,51 @@ interface TornadoPoolInterface extends ethers.utils.Interface { encodeFunctionData(functionFragment: "hasher", values?: undefined): string; encodeFunctionData( functionFragment: "initialize", - values?: undefined + values: [BigNumberish, BigNumberish] ): string; encodeFunctionData( functionFragment: "isKnownRoot", values: [BytesLike] ): string; encodeFunctionData(functionFragment: "isSpent", values: [BytesLike]): string; + encodeFunctionData( + functionFragment: "l1Unwrapper", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "lastBalance", + values?: undefined + ): string; encodeFunctionData(functionFragment: "levels", values?: undefined): string; + encodeFunctionData( + functionFragment: "maximumDepositAmount", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "minimalWithdrawalAmount", + values?: undefined + ): string; encodeFunctionData(functionFragment: "nextIndex", values?: undefined): string; encodeFunctionData( functionFragment: "nullifierHashes", values: [BytesLike] ): string; + encodeFunctionData( + functionFragment: "omniBridge", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "onTokenBridged", + values: [string, BigNumberish, BytesLike] + ): string; encodeFunctionData( functionFragment: "register", - values: [{ pubKey: BytesLike; account: BytesLike }] + values: [{ owner: string; publicKey: BytesLike }] ): string; encodeFunctionData( functionFragment: "registerAndTransact", values: [ - { pubKey: BytesLike; account: BytesLike }, + { owner: string; publicKey: BytesLike }, { proof: BytesLike; root: BytesLike; @@ -125,12 +165,14 @@ interface TornadoPoolInterface extends ethers.utils.Interface { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; } ] ): string; encodeFunctionData(functionFragment: "roots", values: [BigNumberish]): string; + encodeFunctionData(functionFragment: "token", values?: undefined): string; encodeFunctionData( - functionFragment: "transaction", + functionFragment: "transact", values: [ { proof: BytesLike; @@ -147,6 +189,7 @@ interface TornadoPoolInterface extends ethers.utils.Interface { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; } ] ): string; @@ -185,6 +228,10 @@ interface TornadoPoolInterface extends ethers.utils.Interface { functionFragment: "calculatePublicAmount", data: BytesLike ): Result; + decodeFunctionResult( + functionFragment: "configureLimits", + data: BytesLike + ): Result; decodeFunctionResult( functionFragment: "currentRootIndex", data: BytesLike @@ -197,6 +244,7 @@ interface TornadoPoolInterface extends ethers.utils.Interface { functionFragment: "getLastRoot", data: BytesLike ): Result; + decodeFunctionResult(functionFragment: "governance", data: BytesLike): Result; decodeFunctionResult( functionFragment: "hashLeftRight", data: BytesLike @@ -208,22 +256,41 @@ interface TornadoPoolInterface extends ethers.utils.Interface { data: BytesLike ): Result; decodeFunctionResult(functionFragment: "isSpent", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "l1Unwrapper", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "lastBalance", + data: BytesLike + ): Result; decodeFunctionResult(functionFragment: "levels", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "maximumDepositAmount", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "minimalWithdrawalAmount", + data: BytesLike + ): Result; decodeFunctionResult(functionFragment: "nextIndex", data: BytesLike): Result; decodeFunctionResult( functionFragment: "nullifierHashes", data: BytesLike ): Result; + decodeFunctionResult(functionFragment: "omniBridge", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "onTokenBridged", + data: BytesLike + ): Result; decodeFunctionResult(functionFragment: "register", data: BytesLike): Result; decodeFunctionResult( functionFragment: "registerAndTransact", data: BytesLike ): Result; decodeFunctionResult(functionFragment: "roots", data: BytesLike): Result; - decodeFunctionResult( - functionFragment: "transaction", - data: BytesLike - ): Result; + decodeFunctionResult(functionFragment: "token", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "transact", data: BytesLike): Result; decodeFunctionResult(functionFragment: "verifier16", data: BytesLike): Result; decodeFunctionResult(functionFragment: "verifier2", data: BytesLike): Result; decodeFunctionResult( @@ -233,13 +300,11 @@ interface TornadoPoolInterface extends ethers.utils.Interface { decodeFunctionResult(functionFragment: "zeros", data: BytesLike): Result; events: { - "EncryptedAccount(address,bytes)": EventFragment; "NewCommitment(bytes32,uint256,bytes)": EventFragment; "NewNullifier(bytes32)": EventFragment; "PublicKey(address,bytes)": EventFragment; }; - getEvent(nameOrSignatureOrTopic: "EncryptedAccount"): EventFragment; getEvent(nameOrSignatureOrTopic: "NewCommitment"): EventFragment; getEvent(nameOrSignatureOrTopic: "NewNullifier"): EventFragment; getEvent(nameOrSignatureOrTopic: "PublicKey"): EventFragment; @@ -305,6 +370,12 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise<[BigNumber]>; + configureLimits( + _minimalWithdrawalAmount: BigNumberish, + _maximumDepositAmount: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + currentRootIndex(overrides?: CallOverrides): Promise<[number]>; filledSubtrees( @@ -314,6 +385,8 @@ export class TornadoPool extends BaseContract { getLastRoot(overrides?: CallOverrides): Promise<[string]>; + governance(overrides?: CallOverrides): Promise<[string]>; + hashLeftRight( _left: BytesLike, _right: BytesLike, @@ -323,6 +396,8 @@ export class TornadoPool extends BaseContract { hasher(overrides?: CallOverrides): Promise<[string]>; initialize( + _minimalWithdrawalAmount: BigNumberish, + _maximumDepositAmount: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; @@ -336,8 +411,16 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise<[boolean]>; + l1Unwrapper(overrides?: CallOverrides): Promise<[string]>; + + lastBalance(overrides?: CallOverrides): Promise<[BigNumber]>; + levels(overrides?: CallOverrides): Promise<[number]>; + maximumDepositAmount(overrides?: CallOverrides): Promise<[BigNumber]>; + + minimalWithdrawalAmount(overrides?: CallOverrides): Promise<[BigNumber]>; + nextIndex(overrides?: CallOverrides): Promise<[number]>; nullifierHashes( @@ -345,13 +428,22 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise<[boolean]>; + omniBridge(overrides?: CallOverrides): Promise<[string]>; + + onTokenBridged( + _token: string, + _amount: BigNumberish, + _data: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + register( - args: { pubKey: BytesLike; account: BytesLike }, + _account: { owner: string; publicKey: BytesLike }, overrides?: Overrides & { from?: string | Promise } ): Promise; registerAndTransact( - _registerArgs: { pubKey: BytesLike; account: BytesLike }, + _account: { owner: string; publicKey: BytesLike }, _proofArgs: { proof: BytesLike; root: BytesLike; @@ -367,13 +459,16 @@ export class TornadoPool extends BaseContract { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; }, - overrides?: PayableOverrides & { from?: string | Promise } + overrides?: Overrides & { from?: string | Promise } ): Promise; roots(arg0: BigNumberish, overrides?: CallOverrides): Promise<[string]>; - transaction( + token(overrides?: CallOverrides): Promise<[string]>; + + transact( _args: { proof: BytesLike; root: BytesLike; @@ -389,8 +484,9 @@ export class TornadoPool extends BaseContract { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; }, - overrides?: PayableOverrides & { from?: string | Promise } + overrides?: Overrides & { from?: string | Promise } ): Promise; verifier16(overrides?: CallOverrides): Promise<[string]>; @@ -428,6 +524,12 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + configureLimits( + _minimalWithdrawalAmount: BigNumberish, + _maximumDepositAmount: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + currentRootIndex(overrides?: CallOverrides): Promise; filledSubtrees( @@ -437,6 +539,8 @@ export class TornadoPool extends BaseContract { getLastRoot(overrides?: CallOverrides): Promise; + governance(overrides?: CallOverrides): Promise; + hashLeftRight( _left: BytesLike, _right: BytesLike, @@ -446,6 +550,8 @@ export class TornadoPool extends BaseContract { hasher(overrides?: CallOverrides): Promise; initialize( + _minimalWithdrawalAmount: BigNumberish, + _maximumDepositAmount: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; @@ -456,19 +562,36 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + l1Unwrapper(overrides?: CallOverrides): Promise; + + lastBalance(overrides?: CallOverrides): Promise; + levels(overrides?: CallOverrides): Promise; + maximumDepositAmount(overrides?: CallOverrides): Promise; + + minimalWithdrawalAmount(overrides?: CallOverrides): Promise; + nextIndex(overrides?: CallOverrides): Promise; nullifierHashes(arg0: BytesLike, overrides?: CallOverrides): Promise; + omniBridge(overrides?: CallOverrides): Promise; + + onTokenBridged( + _token: string, + _amount: BigNumberish, + _data: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + register( - args: { pubKey: BytesLike; account: BytesLike }, + _account: { owner: string; publicKey: BytesLike }, overrides?: Overrides & { from?: string | Promise } ): Promise; registerAndTransact( - _registerArgs: { pubKey: BytesLike; account: BytesLike }, + _account: { owner: string; publicKey: BytesLike }, _proofArgs: { proof: BytesLike; root: BytesLike; @@ -484,13 +607,16 @@ export class TornadoPool extends BaseContract { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; }, - overrides?: PayableOverrides & { from?: string | Promise } + overrides?: Overrides & { from?: string | Promise } ): Promise; roots(arg0: BigNumberish, overrides?: CallOverrides): Promise; - transaction( + token(overrides?: CallOverrides): Promise; + + transact( _args: { proof: BytesLike; root: BytesLike; @@ -506,8 +632,9 @@ export class TornadoPool extends BaseContract { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; }, - overrides?: PayableOverrides & { from?: string | Promise } + overrides?: Overrides & { from?: string | Promise } ): Promise; verifier16(overrides?: CallOverrides): Promise; @@ -545,6 +672,12 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + configureLimits( + _minimalWithdrawalAmount: BigNumberish, + _maximumDepositAmount: BigNumberish, + overrides?: CallOverrides + ): Promise; + currentRootIndex(overrides?: CallOverrides): Promise; filledSubtrees( @@ -554,6 +687,8 @@ export class TornadoPool extends BaseContract { getLastRoot(overrides?: CallOverrides): Promise; + governance(overrides?: CallOverrides): Promise; + hashLeftRight( _left: BytesLike, _right: BytesLike, @@ -562,7 +697,11 @@ export class TornadoPool extends BaseContract { hasher(overrides?: CallOverrides): Promise; - initialize(overrides?: CallOverrides): Promise; + initialize( + _minimalWithdrawalAmount: BigNumberish, + _maximumDepositAmount: BigNumberish, + overrides?: CallOverrides + ): Promise; isKnownRoot(_root: BytesLike, overrides?: CallOverrides): Promise; @@ -571,8 +710,16 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + l1Unwrapper(overrides?: CallOverrides): Promise; + + lastBalance(overrides?: CallOverrides): Promise; + levels(overrides?: CallOverrides): Promise; + maximumDepositAmount(overrides?: CallOverrides): Promise; + + minimalWithdrawalAmount(overrides?: CallOverrides): Promise; + nextIndex(overrides?: CallOverrides): Promise; nullifierHashes( @@ -580,13 +727,22 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + omniBridge(overrides?: CallOverrides): Promise; + + onTokenBridged( + _token: string, + _amount: BigNumberish, + _data: BytesLike, + overrides?: CallOverrides + ): Promise; + register( - args: { pubKey: BytesLike; account: BytesLike }, + _account: { owner: string; publicKey: BytesLike }, overrides?: CallOverrides ): Promise; registerAndTransact( - _registerArgs: { pubKey: BytesLike; account: BytesLike }, + _account: { owner: string; publicKey: BytesLike }, _proofArgs: { proof: BytesLike; root: BytesLike; @@ -602,13 +758,16 @@ export class TornadoPool extends BaseContract { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; }, overrides?: CallOverrides ): Promise; roots(arg0: BigNumberish, overrides?: CallOverrides): Promise; - transaction( + token(overrides?: CallOverrides): Promise; + + transact( _args: { proof: BytesLike; root: BytesLike; @@ -624,6 +783,7 @@ export class TornadoPool extends BaseContract { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; }, overrides?: CallOverrides ): Promise; @@ -648,11 +808,6 @@ export class TornadoPool extends BaseContract { }; filters: { - EncryptedAccount( - owner?: string | null, - account?: null - ): TypedEventFilter<[string, string], { owner: string; account: string }>; - NewCommitment( commitment?: null, index?: null, @@ -689,6 +844,12 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + configureLimits( + _minimalWithdrawalAmount: BigNumberish, + _maximumDepositAmount: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + currentRootIndex(overrides?: CallOverrides): Promise; filledSubtrees( @@ -698,6 +859,8 @@ export class TornadoPool extends BaseContract { getLastRoot(overrides?: CallOverrides): Promise; + governance(overrides?: CallOverrides): Promise; + hashLeftRight( _left: BytesLike, _right: BytesLike, @@ -707,6 +870,8 @@ export class TornadoPool extends BaseContract { hasher(overrides?: CallOverrides): Promise; initialize( + _minimalWithdrawalAmount: BigNumberish, + _maximumDepositAmount: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; @@ -720,8 +885,16 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + l1Unwrapper(overrides?: CallOverrides): Promise; + + lastBalance(overrides?: CallOverrides): Promise; + levels(overrides?: CallOverrides): Promise; + maximumDepositAmount(overrides?: CallOverrides): Promise; + + minimalWithdrawalAmount(overrides?: CallOverrides): Promise; + nextIndex(overrides?: CallOverrides): Promise; nullifierHashes( @@ -729,13 +902,22 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + omniBridge(overrides?: CallOverrides): Promise; + + onTokenBridged( + _token: string, + _amount: BigNumberish, + _data: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + register( - args: { pubKey: BytesLike; account: BytesLike }, + _account: { owner: string; publicKey: BytesLike }, overrides?: Overrides & { from?: string | Promise } ): Promise; registerAndTransact( - _registerArgs: { pubKey: BytesLike; account: BytesLike }, + _account: { owner: string; publicKey: BytesLike }, _proofArgs: { proof: BytesLike; root: BytesLike; @@ -751,13 +933,16 @@ export class TornadoPool extends BaseContract { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; }, - overrides?: PayableOverrides & { from?: string | Promise } + overrides?: Overrides & { from?: string | Promise } ): Promise; roots(arg0: BigNumberish, overrides?: CallOverrides): Promise; - transaction( + token(overrides?: CallOverrides): Promise; + + transact( _args: { proof: BytesLike; root: BytesLike; @@ -773,8 +958,9 @@ export class TornadoPool extends BaseContract { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; }, - overrides?: PayableOverrides & { from?: string | Promise } + overrides?: Overrides & { from?: string | Promise } ): Promise; verifier16(overrides?: CallOverrides): Promise; @@ -813,6 +999,12 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + configureLimits( + _minimalWithdrawalAmount: BigNumberish, + _maximumDepositAmount: BigNumberish, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + currentRootIndex(overrides?: CallOverrides): Promise; filledSubtrees( @@ -822,6 +1014,8 @@ export class TornadoPool extends BaseContract { getLastRoot(overrides?: CallOverrides): Promise; + governance(overrides?: CallOverrides): Promise; + hashLeftRight( _left: BytesLike, _right: BytesLike, @@ -831,6 +1025,8 @@ export class TornadoPool extends BaseContract { hasher(overrides?: CallOverrides): Promise; initialize( + _minimalWithdrawalAmount: BigNumberish, + _maximumDepositAmount: BigNumberish, overrides?: Overrides & { from?: string | Promise } ): Promise; @@ -844,8 +1040,20 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + l1Unwrapper(overrides?: CallOverrides): Promise; + + lastBalance(overrides?: CallOverrides): Promise; + levels(overrides?: CallOverrides): Promise; + maximumDepositAmount( + overrides?: CallOverrides + ): Promise; + + minimalWithdrawalAmount( + overrides?: CallOverrides + ): Promise; + nextIndex(overrides?: CallOverrides): Promise; nullifierHashes( @@ -853,13 +1061,22 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; + omniBridge(overrides?: CallOverrides): Promise; + + onTokenBridged( + _token: string, + _amount: BigNumberish, + _data: BytesLike, + overrides?: Overrides & { from?: string | Promise } + ): Promise; + register( - args: { pubKey: BytesLike; account: BytesLike }, + _account: { owner: string; publicKey: BytesLike }, overrides?: Overrides & { from?: string | Promise } ): Promise; registerAndTransact( - _registerArgs: { pubKey: BytesLike; account: BytesLike }, + _account: { owner: string; publicKey: BytesLike }, _proofArgs: { proof: BytesLike; root: BytesLike; @@ -875,8 +1092,9 @@ export class TornadoPool extends BaseContract { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; }, - overrides?: PayableOverrides & { from?: string | Promise } + overrides?: Overrides & { from?: string | Promise } ): Promise; roots( @@ -884,7 +1102,9 @@ export class TornadoPool extends BaseContract { overrides?: CallOverrides ): Promise; - transaction( + token(overrides?: CallOverrides): Promise; + + transact( _args: { proof: BytesLike; root: BytesLike; @@ -900,8 +1120,9 @@ export class TornadoPool extends BaseContract { fee: BigNumberish; encryptedOutput1: BytesLike; encryptedOutput2: BytesLike; + isL1Withdrawal: boolean; }, - overrides?: PayableOverrides & { from?: string | Promise } + overrides?: Overrides & { from?: string | Promise } ): Promise; verifier16(overrides?: CallOverrides): Promise; diff --git a/src/artifacts/factories/TornadoPool__factory.ts b/src/artifacts/factories/TornadoPool__factory.ts index a5037de..1ae16e4 100644 --- a/src/artifacts/factories/TornadoPool__factory.ts +++ b/src/artifacts/factories/TornadoPool__factory.ts @@ -29,28 +29,29 @@ const _abi = [ name: "_hasher", type: "address", }, - ], - stateMutability: "nonpayable", - type: "constructor", - }, - { - anonymous: false, - inputs: [ { - indexed: true, - internalType: "address", - name: "owner", + internalType: "contract IERC6777", + name: "_token", type: "address", }, { - indexed: false, - internalType: "bytes", - name: "account", - type: "bytes", + internalType: "address", + name: "_omniBridge", + type: "address", + }, + { + internalType: "address", + name: "_l1Unwrapper", + type: "address", + }, + { + internalType: "address", + name: "_governance", + type: "address", }, ], - name: "EncryptedAccount", - type: "event", + stateMutability: "nonpayable", + type: "constructor", }, { anonymous: false, @@ -198,6 +199,24 @@ const _abi = [ stateMutability: "pure", type: "function", }, + { + inputs: [ + { + internalType: "uint256", + name: "_minimalWithdrawalAmount", + type: "uint256", + }, + { + internalType: "uint256", + name: "_maximumDepositAmount", + type: "uint256", + }, + ], + name: "configureLimits", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, { inputs: [], name: "currentRootIndex", @@ -243,6 +262,19 @@ const _abi = [ stateMutability: "view", type: "function", }, + { + inputs: [], + name: "governance", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, { inputs: [ { @@ -281,7 +313,18 @@ const _abi = [ type: "function", }, { - inputs: [], + inputs: [ + { + internalType: "uint256", + name: "_minimalWithdrawalAmount", + type: "uint256", + }, + { + internalType: "uint256", + name: "_maximumDepositAmount", + type: "uint256", + }, + ], name: "initialize", outputs: [], stateMutability: "nonpayable", @@ -325,6 +368,32 @@ const _abi = [ stateMutability: "view", type: "function", }, + { + inputs: [], + name: "l1Unwrapper", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "lastBalance", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, { inputs: [], name: "levels", @@ -338,6 +407,32 @@ const _abi = [ stateMutability: "view", type: "function", }, + { + inputs: [], + name: "maximumDepositAmount", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "minimalWithdrawalAmount", + outputs: [ + { + internalType: "uint256", + name: "", + type: "uint256", + }, + ], + stateMutability: "view", + type: "function", + }, { inputs: [], name: "nextIndex", @@ -370,23 +465,59 @@ const _abi = [ stateMutability: "view", type: "function", }, + { + inputs: [], + name: "omniBridge", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IERC6777", + name: "_token", + type: "address", + }, + { + internalType: "uint256", + name: "_amount", + type: "uint256", + }, + { + internalType: "bytes", + name: "_data", + type: "bytes", + }, + ], + name: "onTokenBridged", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, { inputs: [ { components: [ { - internalType: "bytes", - name: "pubKey", - type: "bytes", + internalType: "address", + name: "owner", + type: "address", }, { internalType: "bytes", - name: "account", + name: "publicKey", type: "bytes", }, ], - internalType: "struct TornadoPool.Register", - name: "args", + internalType: "struct TornadoPool.Account", + name: "_account", type: "tuple", }, ], @@ -400,18 +531,18 @@ const _abi = [ { components: [ { - internalType: "bytes", - name: "pubKey", - type: "bytes", + internalType: "address", + name: "owner", + type: "address", }, { internalType: "bytes", - name: "account", + name: "publicKey", type: "bytes", }, ], - internalType: "struct TornadoPool.Register", - name: "_registerArgs", + internalType: "struct TornadoPool.Account", + name: "_account", type: "tuple", }, { @@ -454,7 +585,7 @@ const _abi = [ { components: [ { - internalType: "address payable", + internalType: "address", name: "recipient", type: "address", }, @@ -464,7 +595,7 @@ const _abi = [ type: "int256", }, { - internalType: "address payable", + internalType: "address", name: "relayer", type: "address", }, @@ -483,6 +614,11 @@ const _abi = [ name: "encryptedOutput2", type: "bytes", }, + { + internalType: "bool", + name: "isL1Withdrawal", + type: "bool", + }, ], internalType: "struct TornadoPool.ExtData", name: "_extData", @@ -491,7 +627,7 @@ const _abi = [ ], name: "registerAndTransact", outputs: [], - stateMutability: "payable", + stateMutability: "nonpayable", type: "function", }, { @@ -513,6 +649,19 @@ const _abi = [ stateMutability: "view", type: "function", }, + { + inputs: [], + name: "token", + outputs: [ + { + internalType: "contract IERC6777", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, { inputs: [ { @@ -555,7 +704,7 @@ const _abi = [ { components: [ { - internalType: "address payable", + internalType: "address", name: "recipient", type: "address", }, @@ -565,7 +714,7 @@ const _abi = [ type: "int256", }, { - internalType: "address payable", + internalType: "address", name: "relayer", type: "address", }, @@ -584,15 +733,20 @@ const _abi = [ name: "encryptedOutput2", type: "bytes", }, + { + internalType: "bool", + name: "isL1Withdrawal", + type: "bool", + }, ], internalType: "struct TornadoPool.ExtData", name: "_extData", type: "tuple", }, ], - name: "transaction", + name: "transact", outputs: [], - stateMutability: "payable", + stateMutability: "nonpayable", type: "function", }, { diff --git a/src/constants/contracts.ts b/src/constants/contracts.ts index f7b8072..b4052fe 100644 --- a/src/constants/contracts.ts +++ b/src/constants/contracts.ts @@ -4,10 +4,12 @@ export const CONTRACT_NETWORKS: { [chainId in ChainId]: string } = { // [ChainId.MAINNET]: '0x8Bfac9EF3d73cE08C7CEC339C0fE3B2e57814c1E', [ChainId.GOERLI]: '0xE2D9aF526edeB16a02FBC3B68B0eB9B534f9c114', [ChainId.OPTIMISM]: '0xcd7318c299A82E887f5180EF865a4c350dFC9fe5', + [ChainId.XDAI]: '0xf7Ca3B0522A4Db061eEeaE4A086a79E48F2aCD25', }; export const RPC_LIST: { [chainId in ChainId]: string } = { // [ChainId.MAINNET]: 'https://mainnet.infura.io/v3/eb6a84e726614079948e0b1efce5baa5', [ChainId.GOERLI]: 'https://eth-goerli.alchemyapi.io/v2/hlSj0EqPUuLGyyTExs6UqFKnXDrc_eOh', [ChainId.OPTIMISM]: 'https://optimism-kovan.infura.io/v3/8f786b96d16046b78e0287fa61c6fcf8', + [ChainId.XDAI]: 'https://rpc.xdaichain.com', }; diff --git a/src/constants/variables.ts b/src/constants/variables.ts index a81de64..a439f0c 100644 --- a/src/constants/variables.ts +++ b/src/constants/variables.ts @@ -14,6 +14,10 @@ const NETWORKS_INFO: { [chainId in ChainId] } = { gasLimit: '', minimumBalance: '0.5', }, + [ChainId.XDAI]: { + gasLimit: BigNumber.from(2500000), + minimumBalance: '0.5', + }, }; const numbers = { diff --git a/src/modules/api/api.validator.ts b/src/modules/api/api.validator.ts index 97e3756..e056d62 100644 --- a/src/modules/api/api.validator.ts +++ b/src/modules/api/api.validator.ts @@ -22,6 +22,7 @@ const bytes32Type = { type: 'string', pattern: '^0x[a-fA-F0-9]{64}$' }; const externalAmountType = { type: 'string', pattern: '^(0x[a-fA-F0-9]{64}|-0x[a-fA-F0-9]{63})$' }; const encryptedOutputType = { type: 'string', pattern: '^0x[a-fA-F0-9]{312}$' }; const arrayType = { type: 'array', items: bytes32Type }; +const booleanType = { type: 'boolean' }; const transactionSchema = { type: 'object', @@ -35,6 +36,7 @@ const transactionSchema = { fee: bytes32Type, recipient: addressType, relayer: addressType, + isL1Withdrawal: booleanType, }, }, args: { diff --git a/src/modules/queue/transaction.processor.ts b/src/modules/queue/transaction.processor.ts index ebd0ff2..551521d 100644 --- a/src/modules/queue/transaction.processor.ts +++ b/src/modules/queue/transaction.processor.ts @@ -7,12 +7,12 @@ import { ConfigService } from '@nestjs/config'; import { InjectQueue, Process, Processor, OnQueueActive, OnQueueCompleted, OnQueueFailed } from '@nestjs/bull'; import { numbers, CONTRACT_ERRORS } from '@/constants'; -import { toWei, getToIntegerMultiplier } from '@/utilities'; +import { getToIntegerMultiplier } from '@/utilities'; import { GasPriceService, ProviderService } from '@/services'; import txMangerConfig from '@/config/txManager.config'; import { BaseProcessor } from './base.processor'; -import { ChainId, Transaction } from '@/types'; +import { Transaction } from '@/types'; @Injectable() @Processor('transaction') export class TransactionProcessor extends BaseProcessor { @@ -98,30 +98,19 @@ export class TransactionProcessor extends BaseProcessor { } async prepareTransaction({ extData, args }) { - const { chainId, address } = this.configService.get('base'); - const contract = this.providerService.getTornadoPool(); - const data = contract.interface.encodeFunctionData('transaction', [args, extData]); + const data = contract.interface.encodeFunctionData('transact', [args, extData]); let gasLimit = this.configService.get('base.gasLimit'); - // need because optimism has dynamic gas limit - if (chainId === ChainId.OPTIMISM) { - gasLimit = await contract.estimateGas.transaction(args, extData, { - from: address, - value: BigNumber.from(0)._hex, - gasPrice: toWei('0.015', 'gwei'), - }); - } - const { fast } = await this.gasPriceService.getGasPrice(); return { data, gasLimit, to: contract.address, - gasPrice: toWei(fast.toString(), 'gwei'), + gasPrice: fast, value: BigNumber.from(0)._hex, }; } @@ -133,6 +122,7 @@ export class TransactionProcessor extends BaseProcessor { // for withdrawals the amount is negative if (amount.isNegative()) { const integerMultiplier = getToIntegerMultiplier(serviceFee.withdrawal); + return BigNumber.from(amount) .mul(serviceFee.withdrawal * integerMultiplier) .div(numbers.ONE_HUNDRED * integerMultiplier); @@ -146,7 +136,7 @@ export class TransactionProcessor extends BaseProcessor { const { fast } = await this.gasPriceService.getGasPrice(); - const expense = BigNumber.from(toWei(fast.toString(), 'gwei')).mul(gasLimit); + const expense = BigNumber.from(fast).mul(gasLimit); const feePercent = this.getServiceFee(externalAmount); diff --git a/src/services/oracle.service.ts b/src/services/oracle.service.ts index cd69521..11de71b 100644 --- a/src/services/oracle.service.ts +++ b/src/services/oracle.service.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; +import { BigNumber } from 'ethers'; import { GasPriceOracle } from 'gas-price-oracle'; -import { GasPrice } from 'gas-price-oracle/lib/types'; import { ChainId } from '@/types'; -import { toWei } from '@/utilities'; import { RPC_LIST, numbers } from '@/constants'; +import { toWei } from '@/utilities'; @Injectable() export class GasPriceService { @@ -16,30 +16,24 @@ export class GasPriceService { this.chainId = this.configService.get('base.chainId'); } - async getGasPrice(): Promise { - if (this.chainId === ChainId.OPTIMISM) { - return GasPriceService.getOptimismPrice(); - } - - const TIMER = 10; + async getGasPrice() { + const TIMER = 3; const INTERVAL = TIMER * numbers.SECOND; const instance = new GasPriceOracle({ timeout: INTERVAL, - defaultRpc: RPC_LIST[ChainId.MAINNET], + defaultRpc: RPC_LIST[ChainId.XDAI], }); - return await instance.gasPrices(); - } + const fast = await instance.fetchGasPriceFromRpc(); - private static getOptimismPrice() { - const OPTIMISM_GAS = toWei('0.015', 'gwei').toNumber(); + const bnGas = BigNumber.from(toWei(String(fast), 'gwei')); return { - fast: OPTIMISM_GAS, - low: OPTIMISM_GAS, - instant: OPTIMISM_GAS, - standard: OPTIMISM_GAS, + instant: bnGas.mul(130).div(100).toHexString(), + fast: bnGas, + standard: bnGas.mul(85).div(100).toHexString(), + low: bnGas.mul(50).div(100).toHexString(), }; } } diff --git a/src/types/index.ts b/src/types/index.ts index 74ab913..ccb5070 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -4,11 +4,13 @@ import { BytesLike } from '@ethersproject/bytes'; const MAINNET_CHAIN_ID = 1; const GOERLI_CHAIN_ID = 5; const OPTIMISM_CHAIN_ID = 69; +const XDAI_CHAIN_ID = 100; export enum ChainId { MAINNET = MAINNET_CHAIN_ID, GOERLI = GOERLI_CHAIN_ID, OPTIMISM = OPTIMISM_CHAIN_ID, + XDAI = XDAI_CHAIN_ID, } export type ExtData = { diff --git a/yarn.lock b/yarn.lock index 140cbff..6cb1671 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3140,6 +3140,14 @@ gas-price-oracle@^0.3.3: axios "^0.19.2" bignumber.js "^9.0.0" +gas-price-oracle@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/gas-price-oracle/-/gas-price-oracle-0.4.0.tgz#1b8426bce92ebcff6cc98a0c5638769cb22417b1" + integrity sha512-5ct4VwTqTigD1V3EvUn513e41OIA+/Ubw0FITVfarw7AjVpg4LQSt9anRt+LcDU4+u+eMUEA3VP0VnvMN8nybA== + dependencies: + axios "^0.19.2" + bignumber.js "^9.0.0" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -5871,16 +5879,11 @@ utils-merge@1.0.1: resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@8.3.2, uuid@^8.3.0: +uuid@8.3.2, uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"