Skip to content

Commit 0ad4186

Browse files
committed
feat: zero hf accounts logic
1 parent 0a8833e commit 0ad4186

File tree

4 files changed

+77
-6
lines changed

4 files changed

+77
-6
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"axios-retry": "^4.5.0",
4141
"date-fns": "^4.1.0",
4242
"di-at-home": "^0.0.7",
43+
"es-toolkit": "^1.39.10",
4344
"esbuild": "^0.25.9",
4445
"husky": "^9.1.7",
4546
"lint-staged": "^16.1.6",

src/services/Scanner.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
} from "@gearbox-protocol/sdk";
99
import {
1010
AbstractCreditAccountService,
11+
AddressSet,
1112
hexEq,
1213
MAX_UINT256,
1314
PERCENTAGE_FACTOR,
@@ -19,13 +20,15 @@ import {
1920
iCreditManagerV3Abi,
2021
iPartialLiquidationBotV3Abi,
2122
} from "@gearbox-protocol/types/abi";
23+
import { throttle } from "es-toolkit";
2224
import type { Address, Block, HttpTransportConfig, PublicClient } from "viem";
2325
import { createPublicClient, getContract, http } from "viem";
2426
import type { Config } from "../config/index.js";
2527
import { DI } from "../di.js";
2628
import { type ILogger, Logger } from "../log/index.js";
2729
import type Client from "./Client.js";
2830
import type { ILiquidatorService } from "./liquidate/index.js";
31+
import type { INotifier } from "./notifier/index.js";
2932

3033
const RESTAKING_CMS: Partial<Record<NetworkType, Address>> = {
3134
Mainnet:
@@ -51,6 +54,9 @@ export class Scanner {
5154
@DI.Inject(DI.CreditAccountService)
5255
caService!: ICreditAccountsService;
5356

57+
@DI.Inject(DI.Notifier)
58+
notifier!: INotifier;
59+
5460
#processing: bigint | null = null;
5561
#restakingCMAddr?: Address;
5662
#restakingMinHF?: bigint;
@@ -59,6 +65,14 @@ export class Scanner {
5965
#minHealthFactor = 0n;
6066
#unwatch?: () => void;
6167

68+
constructor() {
69+
this.#notifyOnZeroHFAccounts = throttle(
70+
this.#notifyOnZeroHFAccounts,
71+
1000 * 60 * 5,
72+
{ edges: ["leading"] },
73+
);
74+
}
75+
6276
public async launch(): Promise<void> {
6377
await this.liquidatorService.launch();
6478
if (this.config.restakingWorkaround) {
@@ -161,7 +175,7 @@ export class Scanner {
161175
this.config.liquidationMode !== "deleverage" &&
162176
!this.config.updateReservePrices,
163177
};
164-
accounts = await this.caService.getCreditAccounts(queue, blockNumber);
178+
accounts = await this.#getAllCreditAccounts(queue, blockNumber);
165179
}
166180
if (this.config.restakingWorkaround) {
167181
const before = accounts.length;
@@ -214,6 +228,46 @@ export class Scanner {
214228
}
215229
}
216230

231+
async #getAllCreditAccounts(
232+
queue: GetCreditAccountsOptions,
233+
blockNumber?: bigint,
234+
): Promise<CreditAccountData[]> {
235+
let accounts = await this.caService.getCreditAccounts(queue, blockNumber);
236+
let zeroHFAccs = accounts.filter(ca => ca.healthFactor === 0n);
237+
238+
if (zeroHFAccs.length > 0) {
239+
this.log.warn(
240+
`found ${zeroHFAccs.length} accounts with HF=0 on first attempt, retrying`,
241+
);
242+
accounts = await this.caService.getCreditAccounts(queue, blockNumber);
243+
zeroHFAccs = accounts.filter(ca => ca.healthFactor === 0n);
244+
245+
if (zeroHFAccs.length > 0) {
246+
this.log.warn(
247+
`found ${zeroHFAccs.length} accounts with HF=0 on second attempt, skipping them`,
248+
);
249+
accounts = accounts.filter(ca => ca.healthFactor !== 0n);
250+
251+
const badTokens = new AddressSet();
252+
for (const ca of zeroHFAccs) {
253+
for (const token of ca.tokens) {
254+
if (!token.success) {
255+
badTokens.add(token.token);
256+
}
257+
}
258+
}
259+
const badTokensStr = badTokens
260+
.asArray()
261+
.map(t => this.caService.sdk.tokensMeta.get(t)?.symbol)
262+
.join(", ");
263+
this.log.warn(`bad tokens: ${badTokensStr}`);
264+
this.#notifyOnZeroHFAccounts(zeroHFAccs.length, badTokensStr);
265+
}
266+
}
267+
268+
return accounts;
269+
}
270+
217271
async #setupRestakingWorkaround(): Promise<void> {
218272
this.#restakingCMAddr = RESTAKING_CMS[this.config.network];
219273

@@ -350,6 +404,13 @@ export class Scanner {
350404
return result;
351405
}
352406

407+
#notifyOnZeroHFAccounts = (count: number, badTokens: string): void => {
408+
this.notifier.alert({
409+
plain: `found ${count} accounts with HF=0, bad tokens: ${badTokens}`,
410+
markdown: `found ${count} accounts with HF=0, bad tokens: ${badTokens}`,
411+
});
412+
};
413+
353414
public get lastUpdated(): bigint {
354415
return this.#lastUpdated;
355416
}

src/services/liquidate/AbstractLiquidator.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@ import { ierc20MetadataAbi } from "@gearbox-protocol/types/abi";
1010
import type { OptimisticResult } from "@gearbox-protocol/types/optimist";
1111
import type { Address, TransactionReceipt } from "viem";
1212

13-
import type {
14-
CommonSchema,
15-
Config,
16-
LiqduiatorConfig,
17-
} from "../../config/index.js";
13+
import type { CommonSchema, LiqduiatorConfig } from "../../config/index.js";
1814
import { DI } from "../../di.js";
1915
import { ErrorHandler } from "../../errors/index.js";
2016
import type { ILogger } from "../../log/index.js";

yarn.lock

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1789,6 +1789,7 @@ __metadata:
17891789
axios-retry: "npm:^4.5.0"
17901790
date-fns: "npm:^4.1.0"
17911791
di-at-home: "npm:^0.0.7"
1792+
es-toolkit: "npm:^1.39.10"
17921793
esbuild: "npm:^0.25.9"
17931794
husky: "npm:^9.1.7"
17941795
lint-staged: "npm:^16.1.6"
@@ -3865,6 +3866,18 @@ __metadata:
38653866
languageName: node
38663867
linkType: hard
38673868

3869+
"es-toolkit@npm:^1.39.10":
3870+
version: 1.39.10
3871+
resolution: "es-toolkit@npm:1.39.10"
3872+
dependenciesMeta:
3873+
"@trivago/prettier-plugin-sort-imports@4.3.0":
3874+
unplugged: true
3875+
prettier-plugin-sort-re-exports@0.0.1:
3876+
unplugged: true
3877+
checksum: 10c0/244dd6be25bc8c7af9f085f5b9aae08169eca760fc7d4735020f8f711b6a572e0bf205400326fa85a7924e20747d315756dba1b3a5f0d2887231374ec3651a98
3878+
languageName: node
3879+
linkType: hard
3880+
38683881
"esbuild@npm:^0.25.0, esbuild@npm:^0.25.9, esbuild@npm:~0.25.0":
38693882
version: 0.25.9
38703883
resolution: "esbuild@npm:0.25.9"

0 commit comments

Comments
 (0)