@instadapp/interop-x 0.0.0-dev.c696e38 → 0.0.0-dev.cb34b2e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/package.json +9 -2
  2. package/dist/src/abi/aaveV2Resolver.json +832 -0
  3. package/dist/src/abi/balanceResolver.json +211 -0
  4. package/dist/src/abi/index.js +6 -0
  5. package/dist/src/abi/instList.json +232 -0
  6. package/dist/src/api/index.js +7 -0
  7. package/dist/src/constants/addresses.js +7 -1
  8. package/dist/src/constants/capPerChain.js +8 -0
  9. package/dist/src/constants/index.js +2 -0
  10. package/dist/src/constants/tokens.js +44 -44
  11. package/dist/src/constants/wrappedNativeToken.js +8 -0
  12. package/dist/src/crons/index.js +3 -0
  13. package/dist/src/crons/prices.js +16 -0
  14. package/dist/src/db/models/transaction.js +4 -0
  15. package/dist/src/errors/index.js +30 -0
  16. package/dist/src/gnosis/actions/aaveV2/source.js +2 -1
  17. package/dist/src/gnosis/actions/aaveV2/target.js +5 -3
  18. package/dist/src/index.js +2 -1
  19. package/dist/src/providers/index.js +17 -0
  20. package/dist/src/providers/retry-provider.js +45 -0
  21. package/dist/src/services/Prices.js +74 -0
  22. package/dist/src/services/index.js +8 -0
  23. package/dist/src/tasks/InteropX/{ProcessSubmitSubmitEvents.js → ProcessSubmitEvents.js} +106 -14
  24. package/dist/src/tasks/InteropX/ProcessValidateEvents.js +30 -10
  25. package/dist/src/tasks/InteropX/SyncLogExecuteEvents.js +113 -0
  26. package/dist/src/tasks/InteropX/SyncLogSubmitEvents.js +2 -1
  27. package/dist/src/tasks/InteropX/SyncLogValidateEvents.js +5 -4
  28. package/dist/src/tasks/index.js +7 -5
  29. package/dist/src/typechain/AaveV2Resolver.js +2 -0
  30. package/dist/src/typechain/BalanceResolver.js +2 -0
  31. package/dist/src/typechain/InstList.js +2 -0
  32. package/dist/src/typechain/factories/AaveV2Resolver__factory.js +1191 -0
  33. package/dist/src/typechain/factories/BalanceResolver__factory.js +228 -0
  34. package/dist/src/typechain/factories/InstList__factory.js +249 -0
  35. package/dist/src/typechain/factories/index.js +7 -1
  36. package/dist/src/typechain/index.js +7 -1
  37. package/dist/src/utils/async.js +18 -0
  38. package/dist/src/utils/dsa.js +24 -0
  39. package/dist/src/utils/formatting.js +67 -0
  40. package/dist/src/utils/gnosis.js +87 -0
  41. package/dist/src/utils/http.js +10 -0
  42. package/dist/src/utils/index.js +22 -220
  43. package/dist/src/utils/interop.js +16 -0
  44. package/dist/src/utils/tokens.js +22 -0
  45. package/dist/src/utils/validate.js +111 -0
  46. package/dist/src/utils/web3.js +93 -0
  47. package/package.json +9 -2
  48. package/src/abi/aaveV2Resolver.json +832 -0
  49. package/src/abi/balanceResolver.json +211 -0
  50. package/src/abi/index.ts +6 -0
  51. package/src/abi/instList.json +232 -0
  52. package/src/api/index.ts +8 -0
  53. package/src/constants/addresses.ts +18 -2
  54. package/src/constants/capPerChain.ts +5 -0
  55. package/src/constants/index.ts +2 -0
  56. package/src/constants/tokens.ts +44 -44
  57. package/src/constants/wrappedNativeToken.ts +5 -0
  58. package/src/crons/index.ts +1 -0
  59. package/src/crons/prices.ts +12 -0
  60. package/src/db/models/transaction.ts +21 -0
  61. package/src/errors/index.ts +26 -0
  62. package/src/gnosis/actions/aaveV2/source.ts +2 -1
  63. package/src/gnosis/actions/aaveV2/target.ts +13 -3
  64. package/src/index.ts +1 -0
  65. package/src/providers/index.ts +1 -0
  66. package/src/providers/retry-provider.ts +51 -0
  67. package/src/services/Prices.ts +89 -0
  68. package/src/services/index.ts +1 -0
  69. package/src/tasks/InteropX/{ProcessSubmitSubmitEvents.ts → ProcessSubmitEvents.ts} +133 -20
  70. package/src/tasks/InteropX/ProcessValidateEvents.ts +42 -19
  71. package/src/tasks/InteropX/SyncLogExecuteEvents.ts +161 -0
  72. package/src/tasks/InteropX/SyncLogSubmitEvents.ts +5 -6
  73. package/src/tasks/InteropX/SyncLogValidateEvents.ts +8 -9
  74. package/src/tasks/index.ts +8 -5
  75. package/src/typechain/AaveV2Resolver.ts +1017 -0
  76. package/src/typechain/BalanceResolver.ts +266 -0
  77. package/src/typechain/InstList.ts +402 -0
  78. package/src/typechain/factories/AaveV2Resolver__factory.ts +1198 -0
  79. package/src/typechain/factories/BalanceResolver__factory.ts +235 -0
  80. package/src/typechain/factories/InstList__factory.ts +253 -0
  81. package/src/typechain/factories/index.ts +3 -0
  82. package/src/typechain/index.ts +6 -0
  83. package/src/utils/async.ts +22 -0
  84. package/src/utils/dsa.ts +30 -0
  85. package/src/utils/formatting.ts +68 -0
  86. package/src/utils/gnosis.ts +166 -0
  87. package/src/utils/http.ts +6 -0
  88. package/src/utils/index.ts +9 -365
  89. package/src/utils/interop.ts +28 -0
  90. package/src/utils/tokens.ts +21 -0
  91. package/src/utils/validate.ts +174 -0
  92. package/src/utils/web3.ts +132 -0
@@ -0,0 +1,26 @@
1
+ export class UnsupportedChaindIdError extends Error {
2
+ constructor(chainId: any) {
3
+ super(`Unsupported chainId: ${chainId}`);
4
+ }
5
+ }
6
+
7
+ export class LiquidityError extends Error {
8
+ constructor(message?: string) {
9
+ super(message || "Not enough liquidity");
10
+ Object.setPrototypeOf(this, new.target.prototype);
11
+ }
12
+ }
13
+
14
+ export class InvalidChaindIdError extends Error {
15
+ constructor(message?: string) {
16
+ super(message || "Invalid chain id");
17
+ Object.setPrototypeOf(this, new.target.prototype);
18
+ }
19
+ }
20
+
21
+ export class LowLiquidityError extends Error {
22
+ constructor(message?: string) {
23
+ super(message || "Low liquidity");
24
+ Object.setPrototypeOf(this, new.target.prototype);
25
+ }
26
+ }
@@ -2,6 +2,7 @@ import abi from "@/abi";
2
2
  import config from "@/config";
3
3
  import { addresses } from "@/constants";
4
4
  import { Transaction } from "@/db";
5
+ import { JsonRpcRetryProvider } from "@/providers";
5
6
  import { InteropX } from "@/typechain";
6
7
  import { ChainId } from "@/types";
7
8
  import { encodeConnectorMethod, getContract, getRpcProviderUrl } from "@/utils";
@@ -25,7 +26,7 @@ export default async function (transaction: Transaction) {
25
26
  metadata,
26
27
  } = transaction.submitEvent;
27
28
 
28
- const sourceChainProvider = new ethers.providers.JsonRpcProvider(
29
+ const sourceChainProvider = new JsonRpcRetryProvider(
29
30
  getRpcProviderUrl(sourceChainId as ChainId)
30
31
  );
31
32
  const sourceWallet = new ethers.Wallet(
@@ -2,7 +2,9 @@ import abi from "@/abi";
2
2
  import config from "@/config";
3
3
  import { addresses } from "@/constants";
4
4
  import { Transaction } from "@/db";
5
+ import { JsonRpcRetryProvider } from "@/providers";
5
6
  import { InteropX } from "@/typechain";
7
+ import { InstList } from "@/typechain/InstList";
6
8
  import { ChainId } from "@/types";
7
9
  import { encodeConnectorMethod, getContract, getRpcProviderUrl } from "@/utils";
8
10
  import { ethers } from "ethers";
@@ -26,15 +28,23 @@ export default async function (transaction: Transaction) {
26
28
  metadata,
27
29
  } = transaction.validateEvent;
28
30
 
29
- const targetChainProvider = new ethers.providers.JsonRpcProvider(
31
+ const targetChainProvider = new JsonRpcRetryProvider(
30
32
  getRpcProviderUrl(targetChainId as ChainId)
31
33
  );
32
34
  const targetWallet = new ethers.Wallet(
33
35
  config.privateKey,
34
36
  targetChainProvider
35
37
  );
38
+
39
+
40
+ const targetInstListContract = getContract<InstList>(
41
+ addresses[targetChainId].instList,
42
+ abi.instList,
43
+ targetChainProvider,
44
+ );
45
+
46
+ const targetDsaAddress = await targetInstListContract.accountAddr(targetDsaId)
36
47
  const dsaAddress = addresses[targetChainId].dsaAddress;
37
- const sourceUserAddress = Number(sourceDsaId) == 0 ? sourceSender : dsaAddress;
38
48
  const interopAddress = addresses[targetChainId].interopX;
39
49
  const contract = getContract<InteropX>(
40
50
  interopAddress,
@@ -60,7 +70,7 @@ export default async function (transaction: Transaction) {
60
70
  let spellDataBasicWithdraw = {
61
71
  connector: "BASIC-A",
62
72
  method: "withdraw",
63
- args: [supplyToken.targetToken, supplyToken.amount, sourceUserAddress, "0", "0"],
73
+ args: [supplyToken.targetToken, supplyToken.amount, targetDsaAddress, "0", "0"],
64
74
  };
65
75
 
66
76
  commonSpells.push({
package/src/index.ts CHANGED
@@ -82,6 +82,7 @@ import { startPeer, protocol, peerPool } from "@/net";
82
82
  import { startApiServer } from '@/api';
83
83
  import { Transaction } from './db';
84
84
  import { shortenHash } from './utils';
85
+ import './crons';
85
86
 
86
87
  async function main() {
87
88
 
@@ -0,0 +1 @@
1
+ export * from './retry-provider';
@@ -0,0 +1,51 @@
1
+ import { ethers } from "ethers";
2
+ import wait from "waait";
3
+ import Bluebird from "bluebird";
4
+
5
+ export interface RetryOptions {
6
+ delay?: number;
7
+ timeouts: number[];
8
+ }
9
+
10
+ export function promiseTimeout<T>(ms: number, promise: Promise<T>): Promise<T> {
11
+ return Bluebird.resolve(promise).timeout(ms);
12
+ }
13
+
14
+ export function retryOperation(
15
+ retriesLeft: number,
16
+ operation: () => Promise<any>,
17
+ options: RetryOptions
18
+ ) {
19
+ return new Promise((resolve, reject) => {
20
+ const { timeouts } = options;
21
+ // Find the timeout for this specific iteration
22
+ const timeout = timeouts[timeouts.length - retriesLeft];
23
+
24
+ // Wrap the original operation in a timeout
25
+ const execution = promiseTimeout(timeout, operation());
26
+
27
+ // If the promise is successful, resolve it and bubble the result up
28
+ return execution.then(resolve).catch((reason: any) => {
29
+ // If there are any retries left, we call the same retryOperation function again,
30
+ // but decrementing the number of retries left by 1
31
+ if (retriesLeft - 1 > 0) {
32
+ // Delay the new attempt slightly
33
+ return wait(options.delay || 50)
34
+ .then(retryOperation.bind(null, retriesLeft - 1, operation, options))
35
+ .then(resolve)
36
+ .catch(reject);
37
+ }
38
+ // Reject (and bubble the result up) if there are no more retries
39
+ return reject(reason);
40
+ });
41
+ });
42
+ }
43
+
44
+ export class JsonRpcRetryProvider extends ethers.providers.JsonRpcProvider {
45
+ public perform(method: string, params: any): Promise<any> {
46
+ const timeouts = [5_000, 10_000];
47
+ const operation = () => super.perform(method, params);
48
+
49
+ return retryOperation(2, operation, { timeouts, delay: 50 });
50
+ }
51
+ }
@@ -0,0 +1,89 @@
1
+ import Web3Utils from "web3-utils";
2
+ import path from "path";
3
+ import fs from "fs";
4
+ import { tokens } from "@/constants";
5
+ import expandHomeDir from "expand-home-dir";
6
+ import config from "@/config";
7
+ import { http } from "@/utils";
8
+
9
+ const basePath = expandHomeDir(`~/.interop-x/data/${config.publicAddress}/${config.staging ? 'staging' : ''}`);
10
+ const mainnetPricesFilePath = path.resolve(basePath, "./mainnetPrices.json");
11
+ const networkTokenPricesFilePath = path.resolve(basePath, "./networkTokenPrices.json");
12
+
13
+ class Prices {
14
+ private static mainnetPrices = {};
15
+
16
+ private static networkTokenPrices = {};
17
+
18
+ static async fetch() {
19
+
20
+ if (!fs.existsSync(mainnetPricesFilePath)) {
21
+ fs.writeFileSync(mainnetPricesFilePath, JSON.stringify({}));
22
+ }
23
+
24
+ if (!fs.existsSync(networkTokenPricesFilePath)) {
25
+ fs.writeFileSync(networkTokenPricesFilePath, JSON.stringify({}));
26
+ }
27
+
28
+ this.mainnetPrices = JSON.parse(fs.readFileSync(mainnetPricesFilePath, "utf8"));
29
+ this.networkTokenPrices = JSON.parse(fs.readFileSync(networkTokenPricesFilePath, "utf8"));
30
+
31
+ try {
32
+ const path = tokens["1"]
33
+ .filter((a) => a.symbol !== "ETH")
34
+ .map((token) => token.address)
35
+ .join(",");
36
+
37
+ const [response, ethResponse, avaxResponse, polygonResponse] =
38
+ await Promise.all([
39
+ http.get(
40
+ "https://api.coingecko.com/api/v3/simple/token_price/ethereum",
41
+ {
42
+ params: { contract_addresses: path, vs_currencies: "usd" },
43
+ }
44
+ ),
45
+ http.get("https://api.coingecko.com/api/v3/simple/price", {
46
+ params: { ids: "ethereum", vs_currencies: "usd" },
47
+ }),
48
+ http.get("https://api.coingecko.com/api/v3/simple/price", {
49
+ params: { ids: "avalanche-2", vs_currencies: "usd" },
50
+ }),
51
+ http.get("https://api.coingecko.com/api/v3/simple/price", {
52
+ params: { ids: "matic-network", vs_currencies: "usd" },
53
+ }),
54
+ ]);
55
+
56
+ this.networkTokenPrices = {
57
+ "1": ethResponse.data.ethereum.usd.toString(),
58
+ "137": polygonResponse.data["matic-network"].usd.toString(),
59
+ "43114": avaxResponse.data["avalanche-2"].usd.toString(),
60
+ };
61
+
62
+ const data = response.data;
63
+
64
+ for (const key in data) {
65
+ const _key = Web3Utils.toChecksumAddress(key);
66
+ if (!data[key].usd) continue;
67
+ this.mainnetPrices[_key] = data[key].usd.toString();
68
+ }
69
+
70
+ this.mainnetPrices["0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"] =
71
+ ethResponse.data.ethereum.usd.toString();
72
+ } catch (error) { }
73
+
74
+ fs.writeFileSync(mainnetPricesFilePath, JSON.stringify(this.mainnetPrices));
75
+ fs.writeFileSync(networkTokenPricesFilePath, JSON.stringify(this.networkTokenPrices));
76
+
77
+ return this.mainnetPrices;
78
+ }
79
+
80
+ static getMainnetPrices() {
81
+ return this.mainnetPrices;
82
+ }
83
+
84
+ static getNetworkTokenPrices() {
85
+ return this.networkTokenPrices;
86
+ }
87
+ }
88
+
89
+ export default Prices;
@@ -0,0 +1 @@
1
+ export { default as Prices } from './Prices';
@@ -5,12 +5,18 @@ import abi from "@/abi";
5
5
  import { Transaction } from "@/db";
6
6
  import {
7
7
  buildSignatureBytes,
8
+ chainIdToName,
9
+ generateGnosisSignatureMessage,
8
10
  generateGnosisTransaction,
9
- generateInteropTransactionHash,
11
+ getChainIdNativeSymbol,
10
12
  getContract,
13
+ getExplorerUrl,
11
14
  getRpcProviderUrl,
12
- LiquidityError,
13
15
  Signature,
16
+ validateChains,
17
+ validateLiquidityCap,
18
+ validateSourceLiquidity,
19
+ getGnosisSignatureAddress,
14
20
  } from "@/utils";
15
21
  import { addresses, blockConfirmations } from "@/constants";
16
22
  import { ChainId } from "@/types";
@@ -22,9 +28,13 @@ import { buildGnosisAction } from "@/gnosis";
22
28
  import { peerPool, protocol } from "@/net";
23
29
  import { LogDescription } from "ethers/lib/utils";
24
30
  import wait from "waait";
31
+ import { LiquidityError, UnsupportedChaindIdError } from "@/errors";
32
+ import { BigNumber } from "bignumber.js";
33
+ import dedent from "dedent";
34
+ import { JsonRpcRetryProvider } from "@/providers";
25
35
 
26
- class ProcessSubmitSubmitEvents extends BaseTask {
27
- sourceProvider: ethers.providers.JsonRpcProvider;
36
+ export default class ProcessSubmitEvents extends BaseTask {
37
+ sourceProvider: JsonRpcRetryProvider;
28
38
  sourceGnosisContract: GnosisSafe;
29
39
  sourceWallet: Wallet;
30
40
  chainId: ChainId;
@@ -33,7 +43,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
33
43
 
34
44
  constructor({ chainId }: { chainId: ChainId }) {
35
45
  super({
36
- logger: new Logger("InteropX::ProcessSubmitSubmitEvents"),
46
+ logger: new Logger("InteropX::ProcessSubmitEvents"),
37
47
  });
38
48
  this.chainId = chainId;
39
49
  }
@@ -73,6 +83,76 @@ class ProcessSubmitSubmitEvents extends BaseTask {
73
83
  transaction.sourceStatus = "proccessing";
74
84
  await transaction.save();
75
85
 
86
+ const { submitEvent: { position, sourceChainId, targetChainId } } = transaction;
87
+ try {
88
+ validateChains({ sourceChainId, targetChainId });
89
+ } catch (error) {
90
+ transaction.sourceErrors = [error.message];
91
+ transaction.sourceStatus = "failed";
92
+ transaction.targetStatus = "failed";
93
+ transaction.status = "failed";
94
+ await transaction.save();
95
+ return;
96
+ }
97
+
98
+ const walletBalance = (await this.sourceWallet.getBalance()).toString();
99
+ const currentGasPrice = (await this.sourceWallet.getGasPrice()).toString()
100
+
101
+ const minBalanceRequired = new BigNumber(currentGasPrice)
102
+ .multipliedBy(4_000_000)
103
+ .multipliedBy(2) // 2x balance
104
+
105
+ if (
106
+ new BigNumber(walletBalance).isLessThan(minBalanceRequired)
107
+ ) {
108
+ console.log(
109
+ dedent`Not enough balance in wallet ${getExplorerUrl(sourceChainId, '/address/' + this.sourceWallet.address)} on ${chainIdToName(sourceChainId)}
110
+ Balance: ${ethers.utils.parseEther(walletBalance)} ${getChainIdNativeSymbol(sourceChainId)}
111
+ Required Balance: ${ethers.utils.parseEther(minBalanceRequired.toString())}
112
+ Require more: ${ethers.utils.parseEther(minBalanceRequired.minus(walletBalance).toString())}`
113
+ );
114
+ transaction.sourceDelayUntil = moment().add({ minutes: 5 }).toDate();
115
+ transaction.sourceStatus = "pending";
116
+ await transaction.save();
117
+ return;
118
+ }
119
+
120
+ try {
121
+ await validateLiquidityCap(position, sourceChainId, targetChainId);
122
+ } catch (error) {
123
+ transaction.sourceErrors = [error.message];
124
+ transaction.sourceStatus = "failed";
125
+ transaction.targetStatus = "failed";
126
+ transaction.status = "failed";
127
+ await transaction.save();
128
+ return;
129
+ }
130
+
131
+ try {
132
+ await validateSourceLiquidity({
133
+ position,
134
+ sourceChainId,
135
+ sourceProvider: this.sourceProvider,
136
+ });
137
+ } catch (error) {
138
+ if (error instanceof UnsupportedChaindIdError) {
139
+ console.log(`Dropping transaction ${transaction.transactionHash}`);
140
+
141
+ transaction.sourceErrors = [error.message];
142
+ transaction.sourceStatus = "failed";
143
+ transaction.targetStatus = "failed";
144
+ transaction.status = "failed";
145
+ await transaction.save();
146
+ } else {
147
+ transaction.sourceStatus = "pending";
148
+ transaction.sourceDelayUntil = moment().add({ minutes: 5 }).toDate();
149
+ await transaction.save();
150
+
151
+ console.log("[validateSourceLiquidity][Warning]", error.message);
152
+ return;
153
+ }
154
+ }
155
+
76
156
  const ownersThreshold = await this.sourceGnosisContract.getThreshold();
77
157
  await wait(10000);
78
158
 
@@ -126,19 +206,36 @@ class ProcessSubmitSubmitEvents extends BaseTask {
126
206
  this.sourceGnosisContract
127
207
  );
128
208
 
129
- const owners = await this.sourceGnosisContract
130
- .getOwners()
131
- .then((owners) => owners.map((owner) => owner.toLowerCase()));
132
209
 
133
- const ownerPeerIds = peerPool.activePeers
134
- .filter((peer) => owners.includes(peer.publicAddress.toLowerCase()))
135
- .map((peer) => peer.id);
210
+ async function getGnosisOwnerPeerIds({
211
+ gnosisContract
212
+ }) {
213
+ const owners = await gnosisContract
214
+ .getOwners()
215
+ .then((owners) => owners.map((owner) => owner.toLowerCase()));
216
+
217
+ return peerPool.activePeers
218
+ .filter((peer) => owners.includes(peer.publicAddress.toLowerCase()))
219
+ .map((peer) => peer.id);
220
+ }
221
+
222
+ const ownerPeerIds = await getGnosisOwnerPeerIds({
223
+ gnosisContract: this.sourceGnosisContract,
224
+ });
136
225
 
137
226
  console.log(
138
- `Collecting signatures for execution ${transaction.transactionHash}`
227
+ `Collecting signatures for execution ${transaction.transactionHash} `
139
228
  );
140
229
 
141
230
  console.log(ownerPeerIds);
231
+
232
+ const message = generateGnosisSignatureMessage({
233
+ to: addresses[data.chainId].multisend,
234
+ data,
235
+ chainId: this.chainId,
236
+ safeTxGas: gnosisTx.safeTxGas,
237
+ nonce: gnosisTx.safeNonce,
238
+ });
142
239
 
143
240
  const signatures = await protocol.requestSignatures(
144
241
  {
@@ -151,9 +248,27 @@ class ProcessSubmitSubmitEvents extends BaseTask {
151
248
  ownerPeerIds
152
249
  );
153
250
 
154
- const validSignatures = signatures.filter(
155
- (s) => !!s.data && s.data !== "0x"
156
- ) as Signature[];
251
+ const validSignatures = signatures
252
+ .filter(
253
+ (s) => !!s.data && s.data !== "0x"
254
+ )
255
+ .filter((s) => {
256
+
257
+ try {
258
+
259
+ const address = getGnosisSignatureAddress({
260
+ message,
261
+ signature: s.data!,
262
+ chainId: this.chainId,
263
+ })
264
+
265
+ return address?.toLowerCase() === s.signer.toLowerCase();
266
+
267
+ } catch (error) {
268
+ return false
269
+ }
270
+
271
+ }) as Signature[];
157
272
 
158
273
  console.log({
159
274
  signatures,
@@ -172,7 +287,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
172
287
  await transaction.save();
173
288
  const errorMessage = signatures.find((s) => !!s.error)?.error;
174
289
  throw new Error(
175
- `Not enough signatures` + (errorMessage ? `: ${errorMessage}` : "")
290
+ `Not enough signatures` + (errorMessage ? `: ${errorMessage} ` : "")
176
291
  );
177
292
  }
178
293
 
@@ -220,7 +335,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
220
335
  receipt.logs.forEach((log) => {
221
336
  try {
222
337
  parsedLogs.push(this.sourceGnosisContract.interface.parseLog(log));
223
- } catch (e) {}
338
+ } catch (e) { }
224
339
  });
225
340
 
226
341
  if (parsedLogs.find((e) => e.name === "ExecutionSuccess")) {
@@ -247,7 +362,7 @@ class ProcessSubmitSubmitEvents extends BaseTask {
247
362
  async start(): Promise<void> {
248
363
  this.blockConfirmationsCount = blockConfirmations[this.chainId] + 1;
249
364
 
250
- this.sourceProvider = new ethers.providers.JsonRpcProvider(
365
+ this.sourceProvider = new JsonRpcRetryProvider(
251
366
  getRpcProviderUrl(this.chainId)
252
367
  );
253
368
 
@@ -265,5 +380,3 @@ class ProcessSubmitSubmitEvents extends BaseTask {
265
380
  await super.start();
266
381
  }
267
382
  }
268
-
269
- export default ProcessSubmitSubmitEvents;
@@ -5,11 +5,12 @@ import abi from "@/abi";
5
5
  import { Transaction } from "@/db";
6
6
  import {
7
7
  buildSignatureBytes,
8
+ generateGnosisSignatureMessage,
8
9
  generateGnosisTransaction,
9
- generateInteropTransactionHash,
10
10
  getContract,
11
+ getGnosisOwnerPeerIds,
12
+ getGnosisSignatureAddress,
11
13
  getRpcProviderUrl,
12
- LiquidityError,
13
14
  Signature,
14
15
  } from "@/utils";
15
16
  import { addresses, blockConfirmations } from "@/constants";
@@ -22,9 +23,11 @@ import { buildGnosisAction } from "@/gnosis";
22
23
  import { peerPool, protocol } from "@/net";
23
24
  import { LogDescription } from "ethers/lib/utils";
24
25
  import wait from "waait";
26
+ import { LiquidityError } from "@/errors";
27
+ import { JsonRpcRetryProvider } from "@/providers";
25
28
 
26
- class ProcessValidateEvents extends BaseTask {
27
- sourceProvider: ethers.providers.JsonRpcProvider;
29
+ export default class ProcessValidateEvents extends BaseTask {
30
+ sourceProvider: JsonRpcRetryProvider;
28
31
  chainId: ChainId;
29
32
  leadNodeOnly: boolean = true;
30
33
  blockConfirmationsCount: number = 12;
@@ -75,7 +78,7 @@ class ProcessValidateEvents extends BaseTask {
75
78
 
76
79
  const { sourceChainId, targetChainId } = transaction.validateEvent
77
80
 
78
- const targetProvider = new ethers.providers.JsonRpcProvider(
81
+ const targetProvider = new JsonRpcRetryProvider(
79
82
  getRpcProviderUrl(targetChainId as ChainId)
80
83
  );
81
84
 
@@ -141,13 +144,9 @@ class ProcessValidateEvents extends BaseTask {
141
144
  targetGnosisContract
142
145
  );
143
146
 
144
- const owners = await targetGnosisContract
145
- .getOwners()
146
- .then((owners) => owners.map((owner) => owner.toLowerCase()));
147
-
148
- const ownerPeerIds = peerPool.activePeers
149
- .filter((peer) => owners.includes(peer.publicAddress.toLowerCase()))
150
- .map((peer) => peer.id);
147
+ const ownerPeerIds = await getGnosisOwnerPeerIds({
148
+ gnosisContract: targetGnosisContract,
149
+ });
151
150
 
152
151
  console.log(
153
152
  `Collecting signatures for execution ${transaction.transactionHash}`
@@ -155,6 +154,14 @@ class ProcessValidateEvents extends BaseTask {
155
154
 
156
155
  console.log(ownerPeerIds);
157
156
 
157
+ const message = generateGnosisSignatureMessage({
158
+ to: addresses[data.chainId].multisend,
159
+ data,
160
+ chainId: this.chainId,
161
+ safeTxGas: gnosisTx.safeTxGas,
162
+ nonce: gnosisTx.safeNonce,
163
+ });
164
+
158
165
  const signatures = await protocol.requestSignatures(
159
166
  {
160
167
  type: "target",
@@ -166,9 +173,27 @@ class ProcessValidateEvents extends BaseTask {
166
173
  ownerPeerIds
167
174
  );
168
175
 
169
- const validSignatures = signatures.filter(
170
- (s) => !!s.data && s.data !== "0x"
171
- ) as Signature[];
176
+ const validSignatures = signatures
177
+ .filter(
178
+ (s) => !!s.data && s.data !== "0x"
179
+ )
180
+ .filter((s) => {
181
+
182
+ try {
183
+
184
+ const address = getGnosisSignatureAddress({
185
+ message,
186
+ signature: s.data!,
187
+ chainId: this.chainId,
188
+ })
189
+
190
+ return address?.toLowerCase() === s.signer.toLowerCase();
191
+
192
+ } catch (error) {
193
+ return false
194
+ }
195
+
196
+ }) as Signature[];
172
197
 
173
198
  console.log({
174
199
  signatures,
@@ -263,12 +288,10 @@ class ProcessValidateEvents extends BaseTask {
263
288
  async start(): Promise<void> {
264
289
  this.blockConfirmationsCount = blockConfirmations[this.chainId] + 1;
265
290
 
266
- this.sourceProvider = new ethers.providers.JsonRpcProvider(
291
+ this.sourceProvider = new JsonRpcRetryProvider(
267
292
  getRpcProviderUrl(this.chainId)
268
293
  );
269
294
 
270
295
  await super.start();
271
296
  }
272
- }
273
-
274
- export default ProcessValidateEvents;
297
+ }