@gearbox-protocol/sdk 14.12.0-next.57 → 14.12.0-next.59
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/cjs/abi/ILiquidationCompressorV313.js +43 -1
- package/dist/cjs/abi/IWithdrawalCompressorV313.js +71 -41
- package/dist/cjs/dev/claimDSToken.js +85 -6
- package/dist/cjs/dev/withdrawalUtils.js +173 -119
- package/dist/cjs/sdk/accounts/liquidations/LiquidationsService.js +27 -43
- package/dist/cjs/sdk/accounts/liquidations/constants.js +1 -1
- package/dist/cjs/sdk/accounts/liquidations/helpers.js +4 -2
- package/dist/cjs/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.js +12 -0
- package/dist/cjs/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +10 -0
- package/dist/cjs/sdk/accounts/withdrawal-compressor/addresses.js +1 -1
- package/dist/esm/abi/ILiquidationCompressorV313.js +43 -1
- package/dist/esm/abi/IWithdrawalCompressorV313.js +71 -41
- package/dist/esm/dev/claimDSToken.js +86 -7
- package/dist/esm/dev/withdrawalUtils.js +173 -119
- package/dist/esm/sdk/accounts/liquidations/LiquidationsService.js +29 -45
- package/dist/esm/sdk/accounts/liquidations/constants.js +1 -1
- package/dist/esm/sdk/accounts/liquidations/helpers.js +4 -2
- package/dist/esm/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.js +12 -0
- package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +10 -0
- package/dist/esm/sdk/accounts/withdrawal-compressor/addresses.js +1 -1
- package/dist/types/abi/ILiquidationCompressorV313.d.ts +36 -1
- package/dist/types/abi/IWithdrawalCompressorV313.d.ts +62 -38
- package/dist/types/dev/withdrawalUtils.d.ts +9 -5
- package/dist/types/sdk/accounts/liquidations/helpers.d.ts +8 -1
- package/dist/types/sdk/accounts/liquidations/types.d.ts +27 -5
- package/dist/types/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.d.ts +3 -3
- package/dist/types/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.d.ts +62 -38
- package/dist/types/sdk/accounts/withdrawal-compressor/types.d.ts +10 -0
- package/package.json +1 -1
|
@@ -12,23 +12,56 @@ let viem = require("viem");
|
|
|
12
12
|
const MIDAS_VAULT_ADMIN = "0x2ACB4BdCbEf02f81BF713b696Ac26390d7f79A12";
|
|
13
13
|
const iVersionAbi = (0, viem.parseAbi)(["function contractType() external view returns (bytes32)"]);
|
|
14
14
|
/**
|
|
15
|
+
* Common part of Midas and Securitize redeemers
|
|
16
|
+
*/
|
|
17
|
+
const iRedeemerAbi = (0, viem.parseAbi)(["function gateway() external view returns (address)"]);
|
|
18
|
+
/**
|
|
15
19
|
* Functions of external Midas redemption vault contract that are not declared
|
|
16
20
|
* in integrations-v3's IMidasRedemptionVault interface
|
|
17
21
|
*/
|
|
18
22
|
const iMidasRedemptionVaultExtAbi = (0, viem.parseAbi)(["function requestRedeemer() external view returns (address)", "function safeApproveRequest(uint256 requestId, uint256 newMTokenRate) external"]);
|
|
19
23
|
/**
|
|
20
|
-
* Makes pending delayed withdrawals
|
|
24
|
+
* Makes pending delayed withdrawals claimable on an anvil fork.
|
|
25
|
+
*
|
|
26
|
+
* Accepts either a credit account, in which case all its pending withdrawals are
|
|
27
|
+
* fulfilled, or a single redeemer. The latter is the only way to reach redeemers
|
|
28
|
+
* that were transferred away from a credit account during a liquidation: they are
|
|
29
|
+
* dropped from the gateway's pending sets, so the compressor no longer reports them.
|
|
21
30
|
*
|
|
22
31
|
* Replicates the `_fulfillWithdrawal` logic from periphery-v3 Foundry tests
|
|
23
32
|
* (WithdrawalCompressorMidasRWA.t.sol, WithdrawalCompressorSecuritize.t.sol)
|
|
24
33
|
* using anvil cheatcodes. Assumes the version 313 of WithdrawalCompressor.
|
|
25
34
|
*
|
|
26
35
|
* @param anvil
|
|
27
|
-
* @param
|
|
28
|
-
* @param
|
|
36
|
+
* @param address credit account or redeemer
|
|
37
|
+
* @param options
|
|
38
|
+
*/
|
|
39
|
+
async function makePendingWithdrawalsClaimable(anvil, address, options) {
|
|
40
|
+
const { logger } = options || {};
|
|
41
|
+
if (await getContractType(anvil, address) === "CREDIT_ACCOUNT") await fulfillCreditAccountWithdrawals(anvil, address, logger);
|
|
42
|
+
else await fulfillRedeemer(anvil, address, logger);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns the decoded `contractType` of a contract, or `undefined` when it does
|
|
46
|
+
* not implement it (redeemers, for example)
|
|
47
|
+
*/
|
|
48
|
+
async function getContractType(anvil, address) {
|
|
49
|
+
try {
|
|
50
|
+
const cType = await anvil.readContract({
|
|
51
|
+
address,
|
|
52
|
+
abi: iVersionAbi,
|
|
53
|
+
functionName: "contractType"
|
|
54
|
+
});
|
|
55
|
+
return (0, viem.hexToString)(cType, { size: 32 });
|
|
56
|
+
} catch {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Fulfills all pending withdrawals of a credit account, as reported by the
|
|
62
|
+
* withdrawal compressor
|
|
29
63
|
*/
|
|
30
|
-
async function
|
|
31
|
-
const { logger, timeWarp = false } = options || {};
|
|
64
|
+
async function fulfillCreditAccountWithdrawals(anvil, creditAccount, logger) {
|
|
32
65
|
const compressor = require_sdk_accounts_withdrawal_compressor_addresses.getWithdrawalCompressorAddress(require_sdk_chain_chains.getNetworkType(anvil.chain.id));
|
|
33
66
|
if (!compressor) throw new Error(`no withdrawal compressor for chain ${anvil.chain.id}`);
|
|
34
67
|
if (compressor.version !== 313) logger?.warn(`withdrawal compressor version is ${compressor.version}, this helper assumes 313`);
|
|
@@ -40,19 +73,8 @@ async function makePendingWithdrawalsClaimable(anvil, creditAccount, options) {
|
|
|
40
73
|
});
|
|
41
74
|
logger?.debug(`found ${pending.length} pending withdrawals for credit account ${creditAccount}`);
|
|
42
75
|
if (pending.length === 0) return;
|
|
43
|
-
if (timeWarp) {
|
|
44
|
-
const maxClaimableAt = pending.reduce((max, p) => p.claimableAt > max ? p.claimableAt : max, 0n);
|
|
45
|
-
if (maxClaimableAt > 0n) {
|
|
46
|
-
logger?.debug(`warping time to ${maxClaimableAt + 1n}`);
|
|
47
|
-
await anvil.evmMineDetailed(maxClaimableAt + 1n);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
76
|
for (const w of pending) {
|
|
51
|
-
const cType = (
|
|
52
|
-
address: w.withdrawalPhantomToken,
|
|
53
|
-
abi: iVersionAbi,
|
|
54
|
-
functionName: "contractType"
|
|
55
|
-
}), { size: 32 });
|
|
77
|
+
const cType = await getContractType(anvil, w.withdrawalPhantomToken);
|
|
56
78
|
logger?.debug(`fulfilling withdrawal in phantom token ${w.withdrawalPhantomToken} with contract type ${cType}`);
|
|
57
79
|
switch (cType) {
|
|
58
80
|
case "PHANTOM_TOKEN::MIDAS_REDEMPTION":
|
|
@@ -61,7 +83,7 @@ async function makePendingWithdrawalsClaimable(anvil, creditAccount, options) {
|
|
|
61
83
|
case "PHANTOM_TOKEN::SECURITIZE_RD":
|
|
62
84
|
await fulfillSecuritizeWithdrawal(anvil, creditAccount, w.withdrawalPhantomToken, logger);
|
|
63
85
|
break;
|
|
64
|
-
default: logger?.warn(`unsupported withdrawal phantom token type ${cType},
|
|
86
|
+
default: logger?.warn(`unsupported withdrawal phantom token type ${cType}, skipping`);
|
|
65
87
|
}
|
|
66
88
|
}
|
|
67
89
|
const [claimableAfter, pendingAfter] = await anvil.readContract({
|
|
@@ -73,29 +95,72 @@ async function makePendingWithdrawalsClaimable(anvil, creditAccount, options) {
|
|
|
73
95
|
logger?.debug(`after fulfillment: ${claimableAfter.length} claimable, ${pendingAfter.length} still pending withdrawals`);
|
|
74
96
|
}
|
|
75
97
|
/**
|
|
76
|
-
* Fulfills a
|
|
77
|
-
*
|
|
78
|
-
|
|
98
|
+
* Fulfills the redemption request held by a single redeemer, dispatching on the
|
|
99
|
+
* type of the gateway that deployed it
|
|
100
|
+
*/
|
|
101
|
+
async function fulfillRedeemer(anvil, redeemer, logger) {
|
|
102
|
+
const gateway = await anvil.readContract({
|
|
103
|
+
address: redeemer,
|
|
104
|
+
abi: iRedeemerAbi,
|
|
105
|
+
functionName: "gateway"
|
|
106
|
+
});
|
|
107
|
+
const cType = await getContractType(anvil, gateway);
|
|
108
|
+
logger?.debug(`fulfilling redeemer ${redeemer} of gateway ${gateway} with contract type ${cType}`);
|
|
109
|
+
switch (cType) {
|
|
110
|
+
case "GATEWAY::MIDAS":
|
|
111
|
+
await fulfillMidasRedeemer(anvil, redeemer, logger);
|
|
112
|
+
break;
|
|
113
|
+
case "GATEWAY::SECURITIZE_REDEMPTION":
|
|
114
|
+
await fulfillSecuritizeRedeemer(anvil, redeemer, logger);
|
|
115
|
+
break;
|
|
116
|
+
default: throw new Error(`unsupported gateway type ${cType} of redeemer ${redeemer}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Fulfills all pending Midas redemption requests of a credit account
|
|
79
121
|
*/
|
|
80
122
|
async function fulfillMidasWithdrawal(anvil, creditAccount, withdrawalPhantomToken, logger) {
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
abi: require_dev_withdrawalAbi.midasRedemptionVaultPhantomTokenAbi,
|
|
86
|
-
functionName: "gateway"
|
|
87
|
-
}, {
|
|
88
|
-
address: withdrawalPhantomToken,
|
|
89
|
-
abi: require_dev_withdrawalAbi.midasRedemptionVaultPhantomTokenAbi,
|
|
90
|
-
functionName: "underlying"
|
|
91
|
-
}]
|
|
123
|
+
const gateway = await anvil.readContract({
|
|
124
|
+
address: withdrawalPhantomToken,
|
|
125
|
+
abi: require_dev_withdrawalAbi.midasRedemptionVaultPhantomTokenAbi,
|
|
126
|
+
functionName: "gateway"
|
|
92
127
|
});
|
|
93
|
-
const
|
|
128
|
+
const redeemers = await anvil.readContract({
|
|
94
129
|
address: gateway,
|
|
95
130
|
abi: require_dev_withdrawalAbi.midasGatewayAbi,
|
|
96
|
-
functionName: "
|
|
131
|
+
functionName: "pendingRedeemers",
|
|
132
|
+
args: [creditAccount]
|
|
133
|
+
});
|
|
134
|
+
logger?.debug(`midas: gateway ${gateway}, ${redeemers.length} pending redeemers`);
|
|
135
|
+
for (const redeemer of redeemers) await fulfillMidasRedeemer(anvil, redeemer, logger);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Fulfills a single Midas redemption request:
|
|
139
|
+
* funds the vault's request redeemer with tokenOut and approves the request
|
|
140
|
+
* on the Midas redemption vault on behalf of the vault admin
|
|
141
|
+
*/
|
|
142
|
+
async function fulfillMidasRedeemer(anvil, redeemer, logger) {
|
|
143
|
+
const [midasRedemptionVault, tokenOut, requestId] = await anvil.multicall({
|
|
144
|
+
allowFailure: false,
|
|
145
|
+
contracts: [
|
|
146
|
+
{
|
|
147
|
+
address: redeemer,
|
|
148
|
+
abi: require_dev_withdrawalAbi.midasRedeemerAbi,
|
|
149
|
+
functionName: "midasRedemptionVault"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
address: redeemer,
|
|
153
|
+
abi: require_dev_withdrawalAbi.midasRedeemerAbi,
|
|
154
|
+
functionName: "quoteToken"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
address: redeemer,
|
|
158
|
+
abi: require_dev_withdrawalAbi.midasRedeemerAbi,
|
|
159
|
+
functionName: "requestId"
|
|
160
|
+
}
|
|
161
|
+
]
|
|
97
162
|
});
|
|
98
|
-
const [mTokenDataFeed, requestRedeemer, tokenOutDecimals
|
|
163
|
+
const [mTokenDataFeed, requestRedeemer, tokenOutDecimals] = await anvil.multicall({
|
|
99
164
|
allowFailure: false,
|
|
100
165
|
contracts: [
|
|
101
166
|
{
|
|
@@ -112,12 +177,6 @@ async function fulfillMidasWithdrawal(anvil, creditAccount, withdrawalPhantomTok
|
|
|
112
177
|
address: tokenOut,
|
|
113
178
|
abi: viem.erc20Abi,
|
|
114
179
|
functionName: "decimals"
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
address: gateway,
|
|
118
|
-
abi: require_dev_withdrawalAbi.midasGatewayAbi,
|
|
119
|
-
functionName: "pendingRedeemers",
|
|
120
|
-
args: [creditAccount]
|
|
121
180
|
}
|
|
122
181
|
]
|
|
123
182
|
});
|
|
@@ -126,63 +185,48 @@ async function fulfillMidasWithdrawal(anvil, creditAccount, withdrawalPhantomTok
|
|
|
126
185
|
abi: require_dev_withdrawalAbi.iMidasDataFeedAbi,
|
|
127
186
|
functionName: "getDataInBase18"
|
|
128
187
|
});
|
|
129
|
-
logger?.debug(`midas:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
});
|
|
163
|
-
if ((await anvil.waitForTransactionReceipt({
|
|
164
|
-
hash,
|
|
165
|
-
pollingInterval: 100
|
|
166
|
-
})).status !== "success") throw new Error(`midas: safeApproveRequest tx ${hash} reverted`);
|
|
167
|
-
await anvil.stopImpersonatingAccount({ address: MIDAS_VAULT_ADMIN });
|
|
168
|
-
}
|
|
188
|
+
logger?.debug(`midas: redeemer ${redeemer}, vault ${midasRedemptionVault}, tokenOut ${tokenOut}, mToken rate ${mTokenRate}`);
|
|
189
|
+
const topUp = 1000000n * 10n ** BigInt(tokenOutDecimals);
|
|
190
|
+
const requestRedeemerBalance = await anvil.readContract({
|
|
191
|
+
address: tokenOut,
|
|
192
|
+
abi: viem.erc20Abi,
|
|
193
|
+
functionName: "balanceOf",
|
|
194
|
+
args: [requestRedeemer]
|
|
195
|
+
});
|
|
196
|
+
logger?.debug(`midas: dealing ${topUp} of tokenOut ${tokenOut} to request redeemer ${requestRedeemer}`);
|
|
197
|
+
await anvil.deal({
|
|
198
|
+
erc20: tokenOut,
|
|
199
|
+
account: requestRedeemer,
|
|
200
|
+
amount: requestRedeemerBalance + topUp
|
|
201
|
+
});
|
|
202
|
+
logger?.debug(`midas: approving request ${requestId} of redeemer ${redeemer} as vault admin ${MIDAS_VAULT_ADMIN}`);
|
|
203
|
+
await anvil.impersonateAccount({ address: MIDAS_VAULT_ADMIN });
|
|
204
|
+
await anvil.setBalance({
|
|
205
|
+
address: MIDAS_VAULT_ADMIN,
|
|
206
|
+
value: (0, viem.parseEther)("100")
|
|
207
|
+
});
|
|
208
|
+
const hash = await anvil.writeContract({
|
|
209
|
+
chain: anvil.chain,
|
|
210
|
+
address: midasRedemptionVault,
|
|
211
|
+
account: MIDAS_VAULT_ADMIN,
|
|
212
|
+
abi: iMidasRedemptionVaultExtAbi,
|
|
213
|
+
functionName: "safeApproveRequest",
|
|
214
|
+
args: [requestId, mTokenRate]
|
|
215
|
+
});
|
|
216
|
+
if ((await anvil.waitForTransactionReceipt({
|
|
217
|
+
hash,
|
|
218
|
+
pollingInterval: 100
|
|
219
|
+
})).status !== "success") throw new Error(`midas: safeApproveRequest tx ${hash} reverted`);
|
|
220
|
+
await anvil.stopImpersonatingAccount({ address: MIDAS_VAULT_ADMIN });
|
|
169
221
|
}
|
|
170
222
|
/**
|
|
171
|
-
* Fulfills
|
|
172
|
-
* funds the first redeemer of the credit account with stablecoins
|
|
223
|
+
* Fulfills all unclaimed Securitize redemption requests of a credit account
|
|
173
224
|
*/
|
|
174
225
|
async function fulfillSecuritizeWithdrawal(anvil, creditAccount, withdrawalPhantomToken, logger) {
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
abi: require_dev_withdrawalAbi.securitizeRedemptionPhantomTokenAbi,
|
|
180
|
-
functionName: "redemptionGateway"
|
|
181
|
-
}, {
|
|
182
|
-
address: withdrawalPhantomToken,
|
|
183
|
-
abi: require_dev_withdrawalAbi.securitizeRedemptionPhantomTokenAbi,
|
|
184
|
-
functionName: "stableCoinToken"
|
|
185
|
-
}]
|
|
226
|
+
const redemptionGateway = await anvil.readContract({
|
|
227
|
+
address: withdrawalPhantomToken,
|
|
228
|
+
abi: require_dev_withdrawalAbi.securitizeRedemptionPhantomTokenAbi,
|
|
229
|
+
functionName: "redemptionGateway"
|
|
186
230
|
});
|
|
187
231
|
const redeemers = await anvil.readContract({
|
|
188
232
|
address: redemptionGateway,
|
|
@@ -190,36 +234,46 @@ async function fulfillSecuritizeWithdrawal(anvil, creditAccount, withdrawalPhant
|
|
|
190
234
|
functionName: "getUnclaimedRedeemers",
|
|
191
235
|
args: [creditAccount]
|
|
192
236
|
});
|
|
193
|
-
logger?.debug(`securitize: gateway ${redemptionGateway},
|
|
237
|
+
logger?.debug(`securitize: gateway ${redemptionGateway}, ${redeemers.length} unclaimed redeemers`);
|
|
194
238
|
if (redeemers.length === 0) {
|
|
195
239
|
logger?.warn(`securitize: no unclaimed redeemers found for credit account ${creditAccount}`);
|
|
196
240
|
return;
|
|
197
241
|
}
|
|
198
|
-
for (const redeemer of redeemers)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
amount: redeemerBalance + redemptionValue
|
|
221
|
-
});
|
|
242
|
+
for (const redeemer of redeemers) await fulfillSecuritizeRedeemer(anvil, redeemer, logger);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Fulfills a single Securitize redemption request:
|
|
246
|
+
* funds the redeemer with stablecoins
|
|
247
|
+
*/
|
|
248
|
+
async function fulfillSecuritizeRedeemer(anvil, redeemer, logger) {
|
|
249
|
+
const [stableCoinToken, redemptionValue] = await anvil.multicall({
|
|
250
|
+
allowFailure: false,
|
|
251
|
+
contracts: [{
|
|
252
|
+
address: redeemer,
|
|
253
|
+
abi: require_dev_withdrawalAbi.securitizeRedeemerAbi,
|
|
254
|
+
functionName: "stableCoinToken"
|
|
255
|
+
}, {
|
|
256
|
+
address: redeemer,
|
|
257
|
+
abi: require_dev_withdrawalAbi.securitizeRedeemerAbi,
|
|
258
|
+
functionName: "getCurrentRedemptionValue"
|
|
259
|
+
}]
|
|
260
|
+
});
|
|
261
|
+
if (redemptionValue === 0n) {
|
|
262
|
+
logger?.debug(`securitize: skipping redeemer ${redeemer} with zero redemption value`);
|
|
263
|
+
return;
|
|
222
264
|
}
|
|
265
|
+
const redeemerBalance = await anvil.readContract({
|
|
266
|
+
address: stableCoinToken,
|
|
267
|
+
abi: viem.erc20Abi,
|
|
268
|
+
functionName: "balanceOf",
|
|
269
|
+
args: [redeemer]
|
|
270
|
+
});
|
|
271
|
+
logger?.debug(`securitize: dealing ${redemptionValue} of stablecoin ${stableCoinToken} to redeemer ${redeemer}`);
|
|
272
|
+
await anvil.deal({
|
|
273
|
+
erc20: stableCoinToken,
|
|
274
|
+
account: redeemer,
|
|
275
|
+
amount: redeemerBalance + redemptionValue
|
|
276
|
+
});
|
|
223
277
|
}
|
|
224
278
|
//#endregion
|
|
225
279
|
exports.makePendingWithdrawalsClaimable = makePendingWithdrawalsClaimable;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_abi_ILiquidationCompressorV313 = require("../../../abi/ILiquidationCompressorV313.js");
|
|
3
|
-
const require_abi_iPhantomToken = require("../../../abi/iPhantomToken.js");
|
|
4
3
|
const require_sdk_utils_AddressSet = require("../../utils/AddressSet.js");
|
|
4
|
+
const require_sdk_utils_bytes32ToString = require("../../utils/bytes32ToString.js");
|
|
5
5
|
const require_sdk_constants_addresses = require("../../constants/addresses.js");
|
|
6
6
|
const require_sdk_constants_math = require("../../constants/math.js");
|
|
7
7
|
require("../../constants/index.js");
|
|
@@ -16,7 +16,6 @@ const require_sdk_market_rwa_securitize_constants = require("../../market/rwa/se
|
|
|
16
16
|
const require_sdk_market_rwa_securitize_SecuritizeLiquidatorContract = require("../../market/rwa/securitize/SecuritizeLiquidatorContract.js");
|
|
17
17
|
require("../../market/rwa/securitize/index.js");
|
|
18
18
|
const require_sdk_accounts_liquidations_constants = require("./constants.js");
|
|
19
|
-
const require_abi_rwa_iRWAGateway = require("../../../abi/rwa/iRWAGateway.js");
|
|
20
19
|
const require_sdk_accounts_liquidations_helpers = require("./helpers.js");
|
|
21
20
|
//#region src/sdk/accounts/liquidations/LiquidationsService.ts
|
|
22
21
|
/**
|
|
@@ -66,20 +65,21 @@ var LiquidationsService = class extends require_sdk_base_SDKConstruct.SDKConstru
|
|
|
66
65
|
return {
|
|
67
66
|
...account,
|
|
68
67
|
repaymentAmount: {
|
|
69
|
-
token: account.totalValue.token,
|
|
70
|
-
balance: data.
|
|
68
|
+
token: require_sdk_utils_hex.hexEq(data.requiredToken, "0x0000000000000000000000000000000000000000") ? account.totalValue.token : data.requiredToken,
|
|
69
|
+
balance: data.requiredAmount
|
|
71
70
|
},
|
|
72
71
|
isDelayed: data.expectedOutputs.some((o) => o.delayed),
|
|
73
72
|
receivedAssets: require_sdk_accounts_liquidations_helpers.toReceivedAssets(data.expectedOutputs),
|
|
74
73
|
isLiquidatorEligible: data.isLiquidatorEligible,
|
|
74
|
+
isCreditAccountFrozen: data.isCreditAccountFrozen,
|
|
75
75
|
kycProtocol: data.kycProtocol || void 0,
|
|
76
76
|
kycToken: require_sdk_utils_hex.hexEq(data.kycToken, "0x0000000000000000000000000000000000000000") ? void 0 : data.kycToken,
|
|
77
77
|
approve: require_sdk_accounts_liquidations_helpers.toLiquidationApproval({
|
|
78
78
|
target: data.liquidationCall.target,
|
|
79
79
|
creditFacade: suite.creditFacade.address,
|
|
80
80
|
creditManager: ca.creditManager,
|
|
81
|
-
token:
|
|
82
|
-
amount: data.
|
|
81
|
+
token: data.requiredToken,
|
|
82
|
+
amount: data.requiredAmount
|
|
83
83
|
})
|
|
84
84
|
};
|
|
85
85
|
}
|
|
@@ -107,56 +107,39 @@ var LiquidationsService = class extends require_sdk_base_SDKConstruct.SDKConstru
|
|
|
107
107
|
* {@inheritDoc ILiquidationsService.loadRWALiquidators}
|
|
108
108
|
**/
|
|
109
109
|
async loadRWALiquidators() {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
contracts: phantomTokens.map(({ addr }) => ({
|
|
119
|
-
address: addr,
|
|
120
|
-
abi: require_abi_iPhantomToken.iPhantomTokenAbi,
|
|
121
|
-
functionName: "getPhantomTokenInfo"
|
|
122
|
-
})),
|
|
123
|
-
allowFailure: false,
|
|
124
|
-
batchSize: 0
|
|
125
|
-
});
|
|
126
|
-
const gateways = phantomTokens.map(({ contractType }, i) => ({
|
|
127
|
-
gateway: ptResp[i][0],
|
|
128
|
-
contractType
|
|
129
|
-
}));
|
|
130
|
-
const gwResp = await this.client.multicall({
|
|
131
|
-
contracts: gateways.map(({ gateway }) => ({
|
|
132
|
-
address: gateway,
|
|
133
|
-
abi: require_abi_rwa_iRWAGateway.iRWAGatewayAbi,
|
|
134
|
-
functionName: "transferMaster"
|
|
110
|
+
const configurators = this.sdk.marketRegister.marketConfigurators;
|
|
111
|
+
if (configurators.length === 0) return;
|
|
112
|
+
const resp = await this.client.multicall({
|
|
113
|
+
contracts: configurators.map((mc) => ({
|
|
114
|
+
address: require_sdk_accounts_liquidations_constants.LIQUIDATION_COMPRESSOR_V313_ADDRESS,
|
|
115
|
+
abi: require_abi_ILiquidationCompressorV313.iLiquidationCompressorV313Abi,
|
|
116
|
+
functionName: "getRWALiquidators",
|
|
117
|
+
args: [mc.address]
|
|
135
118
|
})),
|
|
136
119
|
allowFailure: false,
|
|
137
120
|
batchSize: 0
|
|
138
121
|
});
|
|
139
|
-
const
|
|
140
|
-
liquidator: gwResp[i],
|
|
141
|
-
contractType
|
|
142
|
-
}));
|
|
143
|
-
for (const ref of refs) this.#createRWALiquidator(ref);
|
|
122
|
+
for (const info of resp.flat()) this.#createRWALiquidator(info);
|
|
144
123
|
}
|
|
145
124
|
/**
|
|
146
125
|
* Instantiates the liquidator contract, which registers it and labels its
|
|
147
126
|
* address (see `BaseContract`).
|
|
148
127
|
*
|
|
149
|
-
* @param
|
|
128
|
+
* @param info - Liquidator discovered by the compressor. The same gateway
|
|
129
|
+
* can be configured in several credit managers, so duplicates are expected
|
|
130
|
+
* and skipped.
|
|
150
131
|
**/
|
|
151
|
-
#createRWALiquidator(
|
|
152
|
-
const
|
|
132
|
+
#createRWALiquidator(info) {
|
|
133
|
+
const liquidator = info.liquidatorAddress;
|
|
153
134
|
if (this.sdk.getContract(liquidator)) return;
|
|
154
|
-
switch (contractType) {
|
|
155
|
-
case require_sdk_market_rwa_securitize_constants.
|
|
135
|
+
switch (require_sdk_utils_bytes32ToString.bytes32ToString(info.contractType)) {
|
|
136
|
+
case require_sdk_market_rwa_securitize_constants.RWA_LIQUIDATOR_SECURITIZE:
|
|
156
137
|
new require_sdk_market_rwa_securitize_SecuritizeLiquidatorContract.SecuritizeLiquidatorContract(this.sdk, liquidator);
|
|
138
|
+
this.logger?.debug(`registered Securitize liquidator ${liquidator}`);
|
|
157
139
|
return;
|
|
158
|
-
case require_sdk_market_rwa_midas_constants.
|
|
140
|
+
case require_sdk_market_rwa_midas_constants.RWA_LIQUIDATOR_MIDAS:
|
|
159
141
|
new require_sdk_market_rwa_midas_MidasLiquidatorContract.MidasLiquidatorContract(this.sdk, liquidator);
|
|
142
|
+
this.logger?.debug(`registered Midas liquidator ${liquidator}`);
|
|
160
143
|
return;
|
|
161
144
|
}
|
|
162
145
|
}
|
|
@@ -251,7 +234,8 @@ var LiquidationsService = class extends require_sdk_base_SDKConstruct.SDKConstru
|
|
|
251
234
|
token: unwrappedUnderlying,
|
|
252
235
|
balance: require_sdk_accounts_liquidations_helpers.calcEstimatedProfit(ca.totalValue, liquidationDiscount)
|
|
253
236
|
},
|
|
254
|
-
isDelayed: ca.tokens.some((t) => t.balance > 10n && !!compressor?.getWithdrawalSourceToken(t.token))
|
|
237
|
+
isDelayed: ca.tokens.some((t) => t.balance > 10n && !!compressor?.getWithdrawalSourceToken(t.token)),
|
|
238
|
+
paused: suite.creditFacade.isPaused
|
|
255
239
|
};
|
|
256
240
|
}
|
|
257
241
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
//#region src/sdk/accounts/liquidations/constants.ts
|
|
3
|
-
const LIQUIDATION_COMPRESSOR_V313_ADDRESS = "
|
|
3
|
+
const LIQUIDATION_COMPRESSOR_V313_ADDRESS = "0xB70C4500a0afF02107eB983a348F22492fB6dC94";
|
|
4
4
|
//#endregion
|
|
5
5
|
exports.LIQUIDATION_COMPRESSOR_V313_ADDRESS = LIQUIDATION_COMPRESSOR_V313_ADDRESS;
|
|
@@ -76,14 +76,16 @@ function toLiquidatorWithdrawals(current, network) {
|
|
|
76
76
|
network,
|
|
77
77
|
sourceToken: w.token,
|
|
78
78
|
token: o.token,
|
|
79
|
-
amount: o.amount
|
|
79
|
+
amount: o.amount,
|
|
80
|
+
redeemer: w.redeemer
|
|
80
81
|
});
|
|
81
82
|
for (const w of current.pending) for (const o of w.expectedOutputs) rows.push({
|
|
82
83
|
network,
|
|
83
84
|
sourceToken: w.token,
|
|
84
85
|
token: o.token,
|
|
85
86
|
amount: o.amount,
|
|
86
|
-
claimableAt: w.claimableAt
|
|
87
|
+
claimableAt: w.claimableAt,
|
|
88
|
+
redeemer: w.redeemer
|
|
87
89
|
});
|
|
88
90
|
return rows;
|
|
89
91
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_sdk_utils_AddressMap = require("../../utils/AddressMap.js");
|
|
3
|
+
require("../../constants/addresses.js");
|
|
4
|
+
require("../../constants/index.js");
|
|
5
|
+
const require_sdk_utils_hex = require("../../utils/hex.js");
|
|
3
6
|
require("../../utils/index.js");
|
|
4
7
|
const require_sdk_base_BaseContract = require("../../base/BaseContract.js");
|
|
5
8
|
require("../../base/index.js");
|
|
@@ -201,6 +204,13 @@ function toRequestableWithdrawal(resp) {
|
|
|
201
204
|
};
|
|
202
205
|
}
|
|
203
206
|
/**
|
|
207
|
+
* Normalizes the redeemer of a withdrawal: legacy compressors do not report
|
|
208
|
+
* one, and v313+ uses the zero address for "not applicable".
|
|
209
|
+
**/
|
|
210
|
+
function toRedeemer(redeemer) {
|
|
211
|
+
return !redeemer || require_sdk_utils_hex.hexEq(redeemer, "0x0000000000000000000000000000000000000000") ? void 0 : redeemer;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
204
214
|
* Normalizes a claimable withdrawal. The intent is decoded from `extraData`
|
|
205
215
|
* only when `creditManager` is provided (it is required to build
|
|
206
216
|
* {@link DelayedIntentExtended} and is only meaningful for credit account
|
|
@@ -218,6 +228,7 @@ function toClaimableWithdrawal(w, creditManager) {
|
|
|
218
228
|
withdrawalTokenSpent: w.withdrawalTokenSpent,
|
|
219
229
|
outputs: [...w.outputs],
|
|
220
230
|
claimCalls: [...w.claimCalls],
|
|
231
|
+
redeemer: toRedeemer(w.redeemer),
|
|
221
232
|
intent
|
|
222
233
|
};
|
|
223
234
|
}
|
|
@@ -236,6 +247,7 @@ function toPendingWithdrawal(w, creditManager) {
|
|
|
236
247
|
withdrawalPhantomToken: w.withdrawalPhantomToken,
|
|
237
248
|
expectedOutputs: [...w.expectedOutputs],
|
|
238
249
|
claimableAt: w.claimableAt,
|
|
250
|
+
redeemer: toRedeemer(w.redeemer),
|
|
239
251
|
intent
|
|
240
252
|
};
|
|
241
253
|
}
|
|
@@ -79,6 +79,11 @@ const iExternalWithdrawalsBatchAbi = [{
|
|
|
79
79
|
internalType: "bytes"
|
|
80
80
|
}]
|
|
81
81
|
},
|
|
82
|
+
{
|
|
83
|
+
name: "redeemer",
|
|
84
|
+
type: "address",
|
|
85
|
+
internalType: "address"
|
|
86
|
+
},
|
|
82
87
|
{
|
|
83
88
|
name: "extraData",
|
|
84
89
|
type: "bytes",
|
|
@@ -127,6 +132,11 @@ const iExternalWithdrawalsBatchAbi = [{
|
|
|
127
132
|
type: "uint256",
|
|
128
133
|
internalType: "uint256"
|
|
129
134
|
},
|
|
135
|
+
{
|
|
136
|
+
name: "redeemer",
|
|
137
|
+
type: "address",
|
|
138
|
+
internalType: "address"
|
|
139
|
+
},
|
|
130
140
|
{
|
|
131
141
|
name: "extraData",
|
|
132
142
|
type: "bytes",
|
|
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
//#region src/sdk/accounts/withdrawal-compressor/addresses.ts
|
|
3
3
|
const WITHDRAWAL_COMPRESSORS = {
|
|
4
4
|
Mainnet: {
|
|
5
|
-
address: "
|
|
5
|
+
address: "0x6FA0c5404C31D0161bb39Cc1311aac998A38ecD5",
|
|
6
6
|
version: 313
|
|
7
7
|
},
|
|
8
8
|
Monad: {
|
|
@@ -46,7 +46,12 @@ const iLiquidationCompressorV313Abi = [
|
|
|
46
46
|
internalType: "struct LiquidationData",
|
|
47
47
|
components: [
|
|
48
48
|
{
|
|
49
|
-
name: "
|
|
49
|
+
name: "requiredToken",
|
|
50
|
+
type: "address",
|
|
51
|
+
internalType: "address"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "requiredAmount",
|
|
50
55
|
type: "uint256",
|
|
51
56
|
internalType: "uint256"
|
|
52
57
|
},
|
|
@@ -101,6 +106,11 @@ const iLiquidationCompressorV313Abi = [
|
|
|
101
106
|
type: "bool",
|
|
102
107
|
internalType: "bool"
|
|
103
108
|
},
|
|
109
|
+
{
|
|
110
|
+
name: "isCreditAccountFrozen",
|
|
111
|
+
type: "bool",
|
|
112
|
+
internalType: "bool"
|
|
113
|
+
},
|
|
104
114
|
{
|
|
105
115
|
name: "kycProtocol",
|
|
106
116
|
type: "string",
|
|
@@ -115,6 +125,38 @@ const iLiquidationCompressorV313Abi = [
|
|
|
115
125
|
}],
|
|
116
126
|
stateMutability: "nonpayable"
|
|
117
127
|
},
|
|
128
|
+
{
|
|
129
|
+
type: "function",
|
|
130
|
+
name: "getRWALiquidators",
|
|
131
|
+
inputs: [{
|
|
132
|
+
name: "marketConfigurator",
|
|
133
|
+
type: "address",
|
|
134
|
+
internalType: "address"
|
|
135
|
+
}],
|
|
136
|
+
outputs: [{
|
|
137
|
+
name: "",
|
|
138
|
+
type: "tuple[]",
|
|
139
|
+
internalType: "struct RWALiquidatorInfo[]",
|
|
140
|
+
components: [
|
|
141
|
+
{
|
|
142
|
+
name: "gateway",
|
|
143
|
+
type: "address",
|
|
144
|
+
internalType: "address"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "liquidatorAddress",
|
|
148
|
+
type: "address",
|
|
149
|
+
internalType: "address"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: "contractType",
|
|
153
|
+
type: "bytes32",
|
|
154
|
+
internalType: "bytes32"
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}],
|
|
158
|
+
stateMutability: "view"
|
|
159
|
+
},
|
|
118
160
|
{
|
|
119
161
|
type: "function",
|
|
120
162
|
name: "version",
|