@instadapp/interop-x 0.0.0-dev.f39d622 → 0.0.0-dev.f45bd03
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.
- package/dist/package.json +4 -2
- package/dist/src/abi/aaveV3Resolver.json +628 -0
- package/dist/src/abi/index.js +2 -0
- package/dist/src/constants/addresses.js +4 -2
- package/dist/src/db/models/transaction.js +1 -1
- package/dist/src/gnosis/actions/aaveV2/source.js +26 -1
- package/dist/src/gnosis/actions/aaveV2/target.js +16 -1
- package/dist/src/gnosis/actions/aaveV3/index.js +11 -0
- package/dist/src/gnosis/actions/aaveV3/source.js +74 -0
- package/dist/src/gnosis/actions/aaveV3/target.js +87 -0
- package/dist/src/gnosis/actions/index.js +2 -0
- package/dist/src/index.js +1 -1
- package/dist/src/providers/index.js +17 -0
- package/dist/src/providers/retry-provider.js +45 -0
- package/dist/src/tasks/InteropX/ProcessSubmitEvents.js +38 -10
- package/dist/src/tasks/InteropX/ProcessValidateEvents.js +28 -9
- package/dist/src/tasks/InteropX/SyncLogExecuteEvents.js +2 -1
- package/dist/src/tasks/InteropX/SyncLogSubmitEvents.js +2 -1
- package/dist/src/tasks/InteropX/SyncLogValidateEvents.js +2 -1
- package/dist/src/typechain/AaveV3Resolver.js +2 -0
- package/dist/src/typechain/factories/AaveV3Resolver__factory.js +887 -0
- package/dist/src/typechain/factories/index.js +3 -1
- package/dist/src/typechain/index.js +3 -1
- package/dist/src/utils/gnosis.js +42 -17
- package/dist/src/utils/validate.js +10 -14
- package/package.json +4 -2
- package/src/abi/aaveV3Resolver.json +628 -0
- package/src/abi/index.ts +2 -0
- package/src/constants/addresses.ts +6 -3
- package/src/db/models/transaction.ts +1 -1
- package/src/gnosis/actions/aaveV2/source.ts +58 -2
- package/src/gnosis/actions/aaveV2/target.ts +29 -2
- package/src/gnosis/actions/aaveV3/index.ts +9 -0
- package/src/gnosis/actions/aaveV3/source.ts +119 -0
- package/src/gnosis/actions/aaveV3/target.ts +142 -0
- package/src/gnosis/actions/index.ts +2 -0
- package/src/providers/index.ts +1 -0
- package/src/providers/retry-provider.ts +51 -0
- package/src/tasks/InteropX/ProcessSubmitEvents.ts +52 -13
- package/src/tasks/InteropX/ProcessValidateEvents.ts +39 -13
- package/src/tasks/InteropX/SyncLogExecuteEvents.ts +3 -2
- package/src/tasks/InteropX/SyncLogSubmitEvents.ts +3 -2
- package/src/tasks/InteropX/SyncLogValidateEvents.ts +3 -2
- package/src/typechain/AaveV3Resolver.ts +935 -0
- package/src/typechain/factories/AaveV3Resolver__factory.ts +894 -0
- package/src/typechain/factories/index.ts +1 -0
- package/src/typechain/index.ts +2 -0
- package/src/utils/gnosis.ts +75 -32
- package/src/utils/validate.ts +17 -19
@@ -2,12 +2,15 @@ import abi from "@/abi";
|
|
2
2
|
import config from "@/config";
|
3
3
|
import { addresses } from "@/constants";
|
4
4
|
import { Transaction } from "@/db";
|
5
|
-
import {
|
5
|
+
import { JsonRpcRetryProvider } from "@/providers";
|
6
|
+
import { AaveV2Resolver, InstList, InteropX } from "@/typechain";
|
6
7
|
import { ChainId } from "@/types";
|
7
8
|
import { encodeConnectorMethod, getContract, getRpcProviderUrl } from "@/utils";
|
8
9
|
import { ethers } from "ethers";
|
9
10
|
import { MetaTransaction, OperationType } from "ethers-multisend";
|
10
11
|
|
12
|
+
const safeUserRatioGap = "800000000000000000"
|
13
|
+
|
11
14
|
export default async function (transaction: Transaction) {
|
12
15
|
const transactions: MetaTransaction[] = [];
|
13
16
|
const logs: any[] = [];
|
@@ -25,13 +28,20 @@ export default async function (transaction: Transaction) {
|
|
25
28
|
metadata,
|
26
29
|
} = transaction.submitEvent;
|
27
30
|
|
28
|
-
const sourceChainProvider = new
|
31
|
+
const sourceChainProvider = new JsonRpcRetryProvider(
|
29
32
|
getRpcProviderUrl(sourceChainId as ChainId)
|
30
33
|
);
|
31
34
|
const sourceWallet = new ethers.Wallet(
|
32
35
|
config.privateKey,
|
33
36
|
sourceChainProvider
|
34
37
|
);
|
38
|
+
const targetChainProvider = new JsonRpcRetryProvider(
|
39
|
+
getRpcProviderUrl(targetChainId as ChainId)
|
40
|
+
);
|
41
|
+
const targetWallet = new ethers.Wallet(
|
42
|
+
config.privateKey,
|
43
|
+
targetChainProvider
|
44
|
+
);
|
35
45
|
const dsaAddress = addresses[sourceChainId].dsaAddress;
|
36
46
|
const sourceUserAddress =
|
37
47
|
Number(sourceDsaId) == 0 ? sourceSender : dsaAddress;
|
@@ -42,6 +52,52 @@ export default async function (transaction: Transaction) {
|
|
42
52
|
sourceWallet
|
43
53
|
);
|
44
54
|
|
55
|
+
const sourceResolverContract = getContract<AaveV2Resolver>(
|
56
|
+
addresses[sourceChainId].aaveV2Resolver,
|
57
|
+
abi.aaveV2Resolver,
|
58
|
+
sourceWallet
|
59
|
+
);
|
60
|
+
|
61
|
+
const targetResolverContract = getContract<AaveV2Resolver>(
|
62
|
+
addresses[targetChainId].aaveV2Resolver,
|
63
|
+
abi.aaveV2Resolver,
|
64
|
+
targetWallet
|
65
|
+
);
|
66
|
+
|
67
|
+
const sourceAavePosition = await sourceResolverContract.checkAavePosition(sourceUserAddress, position, safeUserRatioGap, false)
|
68
|
+
|
69
|
+
const userSourceAaveIsOk = sourceAavePosition.isOk;
|
70
|
+
|
71
|
+
if (!userSourceAaveIsOk) {
|
72
|
+
throw new Error("Source chain aave position is not safe to migrate.");
|
73
|
+
}
|
74
|
+
|
75
|
+
const targetInstListContract = getContract<InstList>(
|
76
|
+
addresses[targetChainId].instList,
|
77
|
+
abi.instList,
|
78
|
+
targetChainProvider,
|
79
|
+
);
|
80
|
+
|
81
|
+
const targetDsaAddress = await targetInstListContract.accountAddr(targetDsaId)
|
82
|
+
|
83
|
+
const targetAavePosition = await targetResolverContract
|
84
|
+
.checkAavePosition(targetDsaAddress, position, safeUserRatioGap, true)
|
85
|
+
|
86
|
+
const userTargetAaveIsOk = targetAavePosition.isOk;
|
87
|
+
|
88
|
+
if (!userTargetAaveIsOk) {
|
89
|
+
throw new Error("Target chain aave position will not be safe after migration.");
|
90
|
+
}
|
91
|
+
|
92
|
+
const targetAavePositionWithFee = await targetResolverContract
|
93
|
+
.checkAavePosition(targetDsaAddress, position, safeUserRatioGap, true);
|
94
|
+
|
95
|
+
const userTargetAaveIsOkWithFee = targetAavePositionWithFee.isOk;
|
96
|
+
|
97
|
+
if (!userTargetAaveIsOkWithFee) {
|
98
|
+
throw new Error("Target chain aave position will not be safe after migration due to minimum fee.");
|
99
|
+
}
|
100
|
+
|
45
101
|
const sourceSpells: any[] = [];
|
46
102
|
const commonSpells: any[] = [];
|
47
103
|
|
@@ -2,13 +2,15 @@ import abi from "@/abi";
|
|
2
2
|
import config from "@/config";
|
3
3
|
import { addresses } from "@/constants";
|
4
4
|
import { Transaction } from "@/db";
|
5
|
-
import {
|
5
|
+
import { JsonRpcRetryProvider } from "@/providers";
|
6
|
+
import { AaveV2Resolver, InteropX } from "@/typechain";
|
6
7
|
import { InstList } from "@/typechain/InstList";
|
7
8
|
import { ChainId } from "@/types";
|
8
9
|
import { encodeConnectorMethod, getContract, getRpcProviderUrl } from "@/utils";
|
9
10
|
import { ethers } from "ethers";
|
10
11
|
import { MetaTransaction, OperationType } from "ethers-multisend";
|
11
12
|
|
13
|
+
const safeUserRatioGap = "800000000000000000"
|
12
14
|
|
13
15
|
export default async function (transaction: Transaction) {
|
14
16
|
const transactions: MetaTransaction[] = [];
|
@@ -27,7 +29,7 @@ export default async function (transaction: Transaction) {
|
|
27
29
|
metadata,
|
28
30
|
} = transaction.validateEvent;
|
29
31
|
|
30
|
-
const targetChainProvider = new
|
32
|
+
const targetChainProvider = new JsonRpcRetryProvider(
|
31
33
|
getRpcProviderUrl(targetChainId as ChainId)
|
32
34
|
);
|
33
35
|
const targetWallet = new ethers.Wallet(
|
@@ -35,6 +37,11 @@ export default async function (transaction: Transaction) {
|
|
35
37
|
targetChainProvider
|
36
38
|
);
|
37
39
|
|
40
|
+
const targetResolverContract = getContract<AaveV2Resolver>(
|
41
|
+
addresses[targetChainId].aaveV2Resolver,
|
42
|
+
abi.aaveV2Resolver,
|
43
|
+
targetWallet
|
44
|
+
);
|
38
45
|
|
39
46
|
const targetInstListContract = getContract<InstList>(
|
40
47
|
addresses[targetChainId].instList,
|
@@ -43,6 +50,26 @@ export default async function (transaction: Transaction) {
|
|
43
50
|
);
|
44
51
|
|
45
52
|
const targetDsaAddress = await targetInstListContract.accountAddr(targetDsaId)
|
53
|
+
|
54
|
+
|
55
|
+
const targetAavePosition = await targetResolverContract
|
56
|
+
.checkAavePosition(targetDsaAddress, position, safeUserRatioGap, true)
|
57
|
+
|
58
|
+
const userTargetAaveIsOk = targetAavePosition.isOk;
|
59
|
+
|
60
|
+
if (!userTargetAaveIsOk) {
|
61
|
+
throw new Error("Target chain aave position will not be safe after migration.");
|
62
|
+
}
|
63
|
+
|
64
|
+
const targetAavePositionWithFee = await targetResolverContract
|
65
|
+
.checkAavePosition(targetDsaAddress, position, safeUserRatioGap, true);
|
66
|
+
|
67
|
+
const userTargetAaveIsOkWithFee = targetAavePositionWithFee.isOk;
|
68
|
+
|
69
|
+
if (!userTargetAaveIsOkWithFee) {
|
70
|
+
throw new Error("Target chain aave position will not be safe after migration due to minimum fee.");
|
71
|
+
}
|
72
|
+
|
46
73
|
const dsaAddress = addresses[targetChainId].dsaAddress;
|
47
74
|
const interopAddress = addresses[targetChainId].interopX;
|
48
75
|
const contract = getContract<InteropX>(
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Transaction } from "@/db";
|
2
|
+
import source from "./source";
|
3
|
+
import target from "./target";
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
export default async function (transaction: Transaction, type: 'source' | 'target') {
|
8
|
+
return type === 'source' ? source(transaction) : target(transaction);
|
9
|
+
}
|
@@ -0,0 +1,119 @@
|
|
1
|
+
import abi from "@/abi";
|
2
|
+
import config from "@/config";
|
3
|
+
import { addresses } from "@/constants";
|
4
|
+
import { Transaction } from "@/db";
|
5
|
+
import { JsonRpcRetryProvider } from "@/providers";
|
6
|
+
import { InteropX } from "@/typechain";
|
7
|
+
import { ChainId } from "@/types";
|
8
|
+
import { encodeConnectorMethod, getContract, getRpcProviderUrl } from "@/utils";
|
9
|
+
import { ethers } from "ethers";
|
10
|
+
import { MetaTransaction, OperationType } from "ethers-multisend";
|
11
|
+
|
12
|
+
export default async function (transaction: Transaction) {
|
13
|
+
const transactions: MetaTransaction[] = [];
|
14
|
+
const logs: any[] = [];
|
15
|
+
|
16
|
+
const {
|
17
|
+
position,
|
18
|
+
actionId,
|
19
|
+
actionIdHashHash,
|
20
|
+
sourceSender,
|
21
|
+
sourceDsaId,
|
22
|
+
targetDsaId,
|
23
|
+
sourceChainId,
|
24
|
+
targetChainId,
|
25
|
+
vnonce,
|
26
|
+
metadata,
|
27
|
+
} = transaction.submitEvent;
|
28
|
+
|
29
|
+
const sourceChainProvider = new JsonRpcRetryProvider(
|
30
|
+
getRpcProviderUrl(sourceChainId as ChainId)
|
31
|
+
);
|
32
|
+
const sourceWallet = new ethers.Wallet(
|
33
|
+
config.privateKey,
|
34
|
+
sourceChainProvider
|
35
|
+
);
|
36
|
+
const dsaAddress = addresses[sourceChainId].dsaAddress;
|
37
|
+
const sourceUserAddress =
|
38
|
+
Number(sourceDsaId) == 0 ? sourceSender : dsaAddress;
|
39
|
+
const interopAddress = addresses[sourceChainId].interopX;
|
40
|
+
const contract = getContract<InteropX>(
|
41
|
+
interopAddress,
|
42
|
+
abi.interopX,
|
43
|
+
sourceWallet
|
44
|
+
);
|
45
|
+
|
46
|
+
const sourceSpells: any[] = [];
|
47
|
+
const commonSpells: any[] = [];
|
48
|
+
|
49
|
+
for (const withdraw of position.withdraw) {
|
50
|
+
let spellData = {
|
51
|
+
connector: "AAVE-V3-A",
|
52
|
+
method: "payback",
|
53
|
+
args: [withdraw.sourceToken, withdraw.amount, "2", "0", "0"],
|
54
|
+
};
|
55
|
+
|
56
|
+
sourceSpells.push({
|
57
|
+
connector: spellData.connector,
|
58
|
+
data: encodeConnectorMethod(spellData),
|
59
|
+
});
|
60
|
+
|
61
|
+
let spellDataBasicWithdraw = {
|
62
|
+
connector: "BASIC-A",
|
63
|
+
method: "withdraw",
|
64
|
+
args: [withdraw.sourceToken, withdraw.amount, sourceUserAddress, "0", "0"],
|
65
|
+
};
|
66
|
+
|
67
|
+
commonSpells.push({
|
68
|
+
connector: spellDataBasicWithdraw.connector,
|
69
|
+
data: encodeConnectorMethod(spellDataBasicWithdraw),
|
70
|
+
});
|
71
|
+
}
|
72
|
+
|
73
|
+
for (const supply of position.supply) {
|
74
|
+
let spellDataWithdraw = {
|
75
|
+
connector: "AAVE-V3-A",
|
76
|
+
method: "withdraw",
|
77
|
+
args: [supply.sourceToken, supply.amount, "0", "0"],
|
78
|
+
};
|
79
|
+
|
80
|
+
sourceSpells.push({
|
81
|
+
connector: spellDataWithdraw.connector,
|
82
|
+
data: encodeConnectorMethod(spellDataWithdraw),
|
83
|
+
});
|
84
|
+
|
85
|
+
let spellDataBasicWithdraw = {
|
86
|
+
connector: "BASIC-A",
|
87
|
+
method: "withdraw",
|
88
|
+
args: [supply.sourceToken, supply.amount, dsaAddress, "0", "0"],
|
89
|
+
};
|
90
|
+
|
91
|
+
sourceSpells.push({
|
92
|
+
connector: spellDataBasicWithdraw.connector,
|
93
|
+
data: encodeConnectorMethod(spellDataBasicWithdraw),
|
94
|
+
});
|
95
|
+
}
|
96
|
+
|
97
|
+
const { data } = await contract.populateTransaction.sourceAction(
|
98
|
+
sourceSpells,
|
99
|
+
commonSpells,
|
100
|
+
position,
|
101
|
+
actionId,
|
102
|
+
sourceSender,
|
103
|
+
sourceDsaId,
|
104
|
+
targetDsaId,
|
105
|
+
sourceChainId,
|
106
|
+
targetChainId,
|
107
|
+
vnonce,
|
108
|
+
metadata
|
109
|
+
);
|
110
|
+
|
111
|
+
transactions.push({
|
112
|
+
to: interopAddress,
|
113
|
+
data: data!,
|
114
|
+
value: "0",
|
115
|
+
operation: OperationType.Call,
|
116
|
+
});
|
117
|
+
|
118
|
+
return { transactions, logs };
|
119
|
+
}
|
@@ -0,0 +1,142 @@
|
|
1
|
+
import abi from "@/abi";
|
2
|
+
import config from "@/config";
|
3
|
+
import { addresses } from "@/constants";
|
4
|
+
import { Transaction } from "@/db";
|
5
|
+
import { JsonRpcRetryProvider } from "@/providers";
|
6
|
+
import { InteropX } from "@/typechain";
|
7
|
+
import { InstList } from "@/typechain/InstList";
|
8
|
+
import { ChainId } from "@/types";
|
9
|
+
import { encodeConnectorMethod, getContract, getRpcProviderUrl } from "@/utils";
|
10
|
+
import { ethers } from "ethers";
|
11
|
+
import { MetaTransaction, OperationType } from "ethers-multisend";
|
12
|
+
|
13
|
+
|
14
|
+
export default async function (transaction: Transaction) {
|
15
|
+
const transactions: MetaTransaction[] = [];
|
16
|
+
const logs: any[] = [];
|
17
|
+
|
18
|
+
const {
|
19
|
+
sourceSpells,
|
20
|
+
position,
|
21
|
+
actionId,
|
22
|
+
sourceSender,
|
23
|
+
sourceDsaId,
|
24
|
+
targetDsaId,
|
25
|
+
sourceChainId,
|
26
|
+
targetChainId,
|
27
|
+
vnonce,
|
28
|
+
metadata,
|
29
|
+
} = transaction.validateEvent;
|
30
|
+
|
31
|
+
const targetChainProvider = new JsonRpcRetryProvider(
|
32
|
+
getRpcProviderUrl(targetChainId as ChainId)
|
33
|
+
);
|
34
|
+
const targetWallet = new ethers.Wallet(
|
35
|
+
config.privateKey,
|
36
|
+
targetChainProvider
|
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)
|
47
|
+
const dsaAddress = addresses[targetChainId].dsaAddress;
|
48
|
+
const interopAddress = addresses[targetChainId].interopX;
|
49
|
+
const contract = getContract<InteropX>(
|
50
|
+
interopAddress,
|
51
|
+
abi.interopX,
|
52
|
+
targetWallet
|
53
|
+
);
|
54
|
+
|
55
|
+
const targetSpells: any[] = [];
|
56
|
+
const commonSpells: any[] = [];
|
57
|
+
|
58
|
+
for (const supplyToken of position.supply) {
|
59
|
+
let spellData = {
|
60
|
+
connector: "AAVE-V3-A",
|
61
|
+
method: "deposit",
|
62
|
+
args: [supplyToken.targetToken, supplyToken.amount, "0", "0"],
|
63
|
+
};
|
64
|
+
|
65
|
+
targetSpells.push({
|
66
|
+
connector: spellData.connector,
|
67
|
+
data: encodeConnectorMethod(spellData),
|
68
|
+
});
|
69
|
+
|
70
|
+
let spellDataBasicWithdraw = {
|
71
|
+
connector: "BASIC-A",
|
72
|
+
method: "withdraw",
|
73
|
+
args: [supplyToken.targetToken, supplyToken.amount, targetDsaAddress, "0", "0"],
|
74
|
+
};
|
75
|
+
|
76
|
+
commonSpells.push({
|
77
|
+
connector: spellDataBasicWithdraw.connector,
|
78
|
+
data: encodeConnectorMethod(spellDataBasicWithdraw),
|
79
|
+
});
|
80
|
+
}
|
81
|
+
|
82
|
+
for (const withdrawToken of position.withdraw) {
|
83
|
+
|
84
|
+
let spellData = {
|
85
|
+
connector: "AAVE-V3-A",
|
86
|
+
method: "borrow",
|
87
|
+
args: [
|
88
|
+
withdrawToken.targetToken,
|
89
|
+
withdrawToken.amount,
|
90
|
+
"2",
|
91
|
+
"0",
|
92
|
+
"0",
|
93
|
+
],
|
94
|
+
};
|
95
|
+
|
96
|
+
targetSpells.push({
|
97
|
+
connector: spellData.connector,
|
98
|
+
data: encodeConnectorMethod(spellData),
|
99
|
+
});
|
100
|
+
|
101
|
+
let spellData2 = {
|
102
|
+
connector: "BASIC-A",
|
103
|
+
method: "withdraw",
|
104
|
+
args: [
|
105
|
+
withdrawToken.targetToken,
|
106
|
+
withdrawToken.amount,
|
107
|
+
dsaAddress,
|
108
|
+
"0",
|
109
|
+
"0",
|
110
|
+
],
|
111
|
+
};
|
112
|
+
|
113
|
+
targetSpells.push({
|
114
|
+
connector: spellData.connector,
|
115
|
+
data: encodeConnectorMethod(spellData2),
|
116
|
+
});
|
117
|
+
}
|
118
|
+
|
119
|
+
const { data } = await contract.populateTransaction.targetAction(
|
120
|
+
sourceSpells,
|
121
|
+
targetSpells,
|
122
|
+
commonSpells,
|
123
|
+
position,
|
124
|
+
actionId,
|
125
|
+
sourceSender,
|
126
|
+
sourceDsaId,
|
127
|
+
targetDsaId,
|
128
|
+
sourceChainId,
|
129
|
+
targetChainId,
|
130
|
+
vnonce,
|
131
|
+
metadata
|
132
|
+
);
|
133
|
+
|
134
|
+
transactions.push({
|
135
|
+
to: interopAddress,
|
136
|
+
data: data!,
|
137
|
+
value: "0",
|
138
|
+
operation: OperationType.Call,
|
139
|
+
});
|
140
|
+
|
141
|
+
return { transactions, logs }
|
142
|
+
}
|
@@ -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
|
+
}
|
@@ -6,6 +6,7 @@ import { Transaction } from "@/db";
|
|
6
6
|
import {
|
7
7
|
buildSignatureBytes,
|
8
8
|
chainIdToName,
|
9
|
+
generateGnosisSignatureMessage,
|
9
10
|
generateGnosisTransaction,
|
10
11
|
getChainIdNativeSymbol,
|
11
12
|
getContract,
|
@@ -15,6 +16,7 @@ import {
|
|
15
16
|
validateChains,
|
16
17
|
validateLiquidityCap,
|
17
18
|
validateSourceLiquidity,
|
19
|
+
getGnosisSignatureAddress,
|
18
20
|
} from "@/utils";
|
19
21
|
import { addresses, blockConfirmations } from "@/constants";
|
20
22
|
import { ChainId } from "@/types";
|
@@ -29,9 +31,10 @@ import wait from "waait";
|
|
29
31
|
import { LiquidityError, UnsupportedChaindIdError } from "@/errors";
|
30
32
|
import { BigNumber } from "bignumber.js";
|
31
33
|
import dedent from "dedent";
|
34
|
+
import { JsonRpcRetryProvider } from "@/providers";
|
32
35
|
|
33
36
|
export default class ProcessSubmitEvents extends BaseTask {
|
34
|
-
sourceProvider:
|
37
|
+
sourceProvider: JsonRpcRetryProvider;
|
35
38
|
sourceGnosisContract: GnosisSafe;
|
36
39
|
sourceWallet: Wallet;
|
37
40
|
chainId: ChainId;
|
@@ -142,6 +145,7 @@ export default class ProcessSubmitEvents extends BaseTask {
|
|
142
145
|
await transaction.save();
|
143
146
|
} else {
|
144
147
|
transaction.sourceStatus = "pending";
|
148
|
+
transaction.sourceErrors = [error.message];
|
145
149
|
transaction.sourceDelayUntil = moment().add({ minutes: 5 }).toDate();
|
146
150
|
await transaction.save();
|
147
151
|
|
@@ -203,19 +207,36 @@ export default class ProcessSubmitEvents extends BaseTask {
|
|
203
207
|
this.sourceGnosisContract
|
204
208
|
);
|
205
209
|
|
206
|
-
const owners = await this.sourceGnosisContract
|
207
|
-
.getOwners()
|
208
|
-
.then((owners) => owners.map((owner) => owner.toLowerCase()));
|
209
210
|
|
210
|
-
|
211
|
-
|
212
|
-
|
211
|
+
async function getGnosisOwnerPeerIds({
|
212
|
+
gnosisContract
|
213
|
+
}) {
|
214
|
+
const owners = await gnosisContract
|
215
|
+
.getOwners()
|
216
|
+
.then((owners) => owners.map((owner) => owner.toLowerCase()));
|
217
|
+
|
218
|
+
return peerPool.activePeers
|
219
|
+
.filter((peer) => owners.includes(peer.publicAddress.toLowerCase()))
|
220
|
+
.map((peer) => peer.id);
|
221
|
+
}
|
222
|
+
|
223
|
+
const ownerPeerIds = await getGnosisOwnerPeerIds({
|
224
|
+
gnosisContract: this.sourceGnosisContract,
|
225
|
+
});
|
213
226
|
|
214
227
|
console.log(
|
215
|
-
`Collecting signatures for execution ${transaction.transactionHash}`
|
228
|
+
`Collecting signatures for execution ${transaction.transactionHash} `
|
216
229
|
);
|
217
230
|
|
218
231
|
console.log(ownerPeerIds);
|
232
|
+
|
233
|
+
const message = generateGnosisSignatureMessage({
|
234
|
+
to: addresses[data.chainId].multisend,
|
235
|
+
data,
|
236
|
+
chainId: this.chainId,
|
237
|
+
safeTxGas: gnosisTx.safeTxGas,
|
238
|
+
nonce: gnosisTx.safeNonce,
|
239
|
+
});
|
219
240
|
|
220
241
|
const signatures = await protocol.requestSignatures(
|
221
242
|
{
|
@@ -228,9 +249,27 @@ export default class ProcessSubmitEvents extends BaseTask {
|
|
228
249
|
ownerPeerIds
|
229
250
|
);
|
230
251
|
|
231
|
-
const validSignatures = signatures
|
232
|
-
(
|
233
|
-
|
252
|
+
const validSignatures = signatures
|
253
|
+
.filter(
|
254
|
+
(s) => !!s.data && s.data !== "0x"
|
255
|
+
)
|
256
|
+
.filter((s) => {
|
257
|
+
|
258
|
+
try {
|
259
|
+
|
260
|
+
const address = getGnosisSignatureAddress({
|
261
|
+
message,
|
262
|
+
signature: s.data!,
|
263
|
+
chainId: this.chainId,
|
264
|
+
})
|
265
|
+
|
266
|
+
return address?.toLowerCase() === s.signer.toLowerCase();
|
267
|
+
|
268
|
+
} catch (error) {
|
269
|
+
return false
|
270
|
+
}
|
271
|
+
|
272
|
+
}) as Signature[];
|
234
273
|
|
235
274
|
console.log({
|
236
275
|
signatures,
|
@@ -249,7 +288,7 @@ export default class ProcessSubmitEvents extends BaseTask {
|
|
249
288
|
await transaction.save();
|
250
289
|
const errorMessage = signatures.find((s) => !!s.error)?.error;
|
251
290
|
throw new Error(
|
252
|
-
`Not enough signatures` + (errorMessage ? `: ${errorMessage}` : "")
|
291
|
+
`Not enough signatures` + (errorMessage ? `: ${errorMessage} ` : "")
|
253
292
|
);
|
254
293
|
}
|
255
294
|
|
@@ -324,7 +363,7 @@ export default class ProcessSubmitEvents extends BaseTask {
|
|
324
363
|
async start(): Promise<void> {
|
325
364
|
this.blockConfirmationsCount = blockConfirmations[this.chainId] + 1;
|
326
365
|
|
327
|
-
this.sourceProvider = new
|
366
|
+
this.sourceProvider = new JsonRpcRetryProvider(
|
328
367
|
getRpcProviderUrl(this.chainId)
|
329
368
|
);
|
330
369
|
|