@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.
Files changed (29) hide show
  1. package/dist/cjs/abi/ILiquidationCompressorV313.js +43 -1
  2. package/dist/cjs/abi/IWithdrawalCompressorV313.js +71 -41
  3. package/dist/cjs/dev/claimDSToken.js +85 -6
  4. package/dist/cjs/dev/withdrawalUtils.js +173 -119
  5. package/dist/cjs/sdk/accounts/liquidations/LiquidationsService.js +27 -43
  6. package/dist/cjs/sdk/accounts/liquidations/constants.js +1 -1
  7. package/dist/cjs/sdk/accounts/liquidations/helpers.js +4 -2
  8. package/dist/cjs/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.js +12 -0
  9. package/dist/cjs/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +10 -0
  10. package/dist/cjs/sdk/accounts/withdrawal-compressor/addresses.js +1 -1
  11. package/dist/esm/abi/ILiquidationCompressorV313.js +43 -1
  12. package/dist/esm/abi/IWithdrawalCompressorV313.js +71 -41
  13. package/dist/esm/dev/claimDSToken.js +86 -7
  14. package/dist/esm/dev/withdrawalUtils.js +173 -119
  15. package/dist/esm/sdk/accounts/liquidations/LiquidationsService.js +29 -45
  16. package/dist/esm/sdk/accounts/liquidations/constants.js +1 -1
  17. package/dist/esm/sdk/accounts/liquidations/helpers.js +4 -2
  18. package/dist/esm/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.js +12 -0
  19. package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +10 -0
  20. package/dist/esm/sdk/accounts/withdrawal-compressor/addresses.js +1 -1
  21. package/dist/types/abi/ILiquidationCompressorV313.d.ts +36 -1
  22. package/dist/types/abi/IWithdrawalCompressorV313.d.ts +62 -38
  23. package/dist/types/dev/withdrawalUtils.d.ts +9 -5
  24. package/dist/types/sdk/accounts/liquidations/helpers.d.ts +8 -1
  25. package/dist/types/sdk/accounts/liquidations/types.d.ts +27 -5
  26. package/dist/types/sdk/accounts/withdrawal-compressor/AbstractWithdrawalCompressorContract.d.ts +3 -3
  27. package/dist/types/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.d.ts +62 -38
  28. package/dist/types/sdk/accounts/withdrawal-compressor/types.d.ts +10 -0
  29. 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 of a credit account claimable on an anvil fork.
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 creditAccount
28
- * @param logger
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 makePendingWithdrawalsClaimable(anvil, creditAccount, options) {
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 = (0, viem.hexToString)(await anvil.readContract({
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}, only time warp was applied`);
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 Midas redemption request:
77
- * funds the vault's request redeemer with tokenOut and approves the request
78
- * on the Midas redemption vault on behalf of the vault admin
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 [gateway, tokenOut] = await anvil.multicall({
82
- allowFailure: false,
83
- contracts: [{
84
- address: withdrawalPhantomToken,
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 midasRedemptionVault = await anvil.readContract({
128
+ const redeemers = await anvil.readContract({
94
129
  address: gateway,
95
130
  abi: require_dev_withdrawalAbi.midasGatewayAbi,
96
- functionName: "midasRedemptionVault"
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, redeemers] = await anvil.multicall({
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: gateway ${gateway}, vault ${midasRedemptionVault}, tokenOut ${tokenOut}, mToken rate ${mTokenRate}, ${redeemers.length} pending redeemers`);
130
- for (const redeemer of redeemers) {
131
- const topUp = 1000000n * 10n ** BigInt(tokenOutDecimals);
132
- const requestRedeemerBalance = await anvil.readContract({
133
- address: tokenOut,
134
- abi: viem.erc20Abi,
135
- functionName: "balanceOf",
136
- args: [requestRedeemer]
137
- });
138
- logger?.debug(`midas: dealing ${topUp} of tokenOut ${tokenOut} to request redeemer ${requestRedeemer}`);
139
- await anvil.deal({
140
- erc20: tokenOut,
141
- account: requestRedeemer,
142
- amount: requestRedeemerBalance + topUp
143
- });
144
- const requestId = await anvil.readContract({
145
- address: redeemer,
146
- abi: require_dev_withdrawalAbi.midasRedeemerAbi,
147
- functionName: "requestId"
148
- });
149
- logger?.debug(`midas: approving request ${requestId} of redeemer ${redeemer} as vault admin ${MIDAS_VAULT_ADMIN}`);
150
- await anvil.impersonateAccount({ address: MIDAS_VAULT_ADMIN });
151
- await anvil.setBalance({
152
- address: MIDAS_VAULT_ADMIN,
153
- value: (0, viem.parseEther)("100")
154
- });
155
- const hash = await anvil.writeContract({
156
- chain: anvil.chain,
157
- address: midasRedemptionVault,
158
- account: MIDAS_VAULT_ADMIN,
159
- abi: iMidasRedemptionVaultExtAbi,
160
- functionName: "safeApproveRequest",
161
- args: [requestId, mTokenRate]
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 a Securitize redemption request:
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 [redemptionGateway, stableCoinToken] = await anvil.multicall({
176
- allowFailure: false,
177
- contracts: [{
178
- address: withdrawalPhantomToken,
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}, stablecoin ${stableCoinToken}, ${redeemers.length} unclaimed redeemers`);
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
- const [redemptionValue, redeemerBalance] = await anvil.multicall({
200
- allowFailure: false,
201
- contracts: [{
202
- address: redeemer,
203
- abi: require_dev_withdrawalAbi.securitizeRedeemerAbi,
204
- functionName: "getCurrentRedemptionValue"
205
- }, {
206
- address: stableCoinToken,
207
- abi: viem.erc20Abi,
208
- functionName: "balanceOf",
209
- args: [redeemer]
210
- }]
211
- });
212
- if (redemptionValue === 0n) {
213
- logger?.debug(`securitize: skipping redeemer ${redeemer} with zero redemption value`);
214
- continue;
215
- }
216
- logger?.debug(`securitize: dealing ${redemptionValue} of stablecoin ${stableCoinToken} to redeemer ${redeemer}`);
217
- await anvil.deal({
218
- erc20: stableCoinToken,
219
- account: redeemer,
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.requiredUnderlyingAmount
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: suite.underlying,
82
- amount: data.requiredUnderlyingAmount
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
- await this.sdk.tokensMeta.loadTokenData();
111
- const phantomTokens = [];
112
- for (const meta of this.sdk.tokensMeta.phantomTokens.values()) switch (meta.contractType) {
113
- case require_sdk_market_rwa_securitize_constants.PHANTOM_TOKEN_SECURITIZE_REDEMPTION:
114
- case require_sdk_market_rwa_midas_constants.PHANTOM_TOKEN_MIDAS_REDEMPTION: phantomTokens.push(meta);
115
- }
116
- if (phantomTokens.length === 0) return;
117
- const ptResp = await this.client.multicall({
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 refs = gateways.map(({ contractType }, i) => ({
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 ref - Discovered liquidator address and its phantom token type
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(ref) {
152
- const { liquidator, contractType } = ref;
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.PHANTOM_TOKEN_SECURITIZE_REDEMPTION:
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.PHANTOM_TOKEN_MIDAS_REDEMPTION:
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 = "0x04c5c47c3b9e29ce98fdd27103fbb6a0815b1712";
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: "0x5c80d7e7b18eCb00Cc9FAd57c59eEC4eF7516597",
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: "requiredUnderlyingAmount",
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",