Skip to content

Commit aaa3746

Browse files
committed
feat: support router v3 and v3.1 partial liquidators
1 parent 440c66c commit aaa3746

24 files changed

+978
-263
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727
"@commitlint/config-conventional": "^19.8.0",
2828
"@gearbox-protocol/eslint-config": "2.0.0-next.2",
2929
"@gearbox-protocol/liquidator-v2-contracts": "^2.4.0",
30+
"@gearbox-protocol/next-contracts": "npm:@gearbox-protocol/liquidator-v2-contracts@2.5.0-next.1",
3031
"@gearbox-protocol/prettier-config": "2.0.0",
31-
"@gearbox-protocol/sdk": "3.0.0-vfour.368",
32+
"@gearbox-protocol/sdk": "3.0.0-vfour.381",
3233
"@gearbox-protocol/types": "^1.14.6",
3334
"@types/node": "^22.13.14",
3435
"@uniswap/sdk-core": "^7.7.2",

src/config/env.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const envConfigMapping: Record<keyof ConfigSchema, string | string[]> = {
3131
ghoPartialLiquidatorAddress: "GHO_PARTIAL_LIQUIDATOR_ADDRESS",
3232
dolaPartialLiquidatorAddress: "DOLA_PARTIAL_LIQUIDATOR_ADDRESS",
3333
nexoPartialLiquidatorAddress: "NEXO_PARTIAL_LIQUIDATOR_ADDRESS",
34+
siloPartialLiquidatorAddress: "SILO_PARTIAL_LIQUIDATOR_ADDRESS",
3435
partialFallback: "PARTIAL_FALLBACK",
3536
privateKey: "PRIVATE_KEY",
3637
port: "PORT",

src/config/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
export { Config } from "./config.js";
2+
export type { ConfigSchema } from "./schema.js";
3+
export type { PartialV300ConfigSchema } from "./schema.js";

src/config/schema.ts

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,32 @@ const booleanLike = z
1313

1414
const bigintLike = z.any().transform(v => BigInt(v));
1515

16-
export const ConfigSchema = z.object({
16+
export const PartialV300ConfigSchema = z.object({
17+
/**
18+
* Address of deployed partial liquidator contract for all credit managers except for GHO- and DOLA- based
19+
*/
20+
aavePartialLiquidatorAddress: Address.optional(),
21+
/**
22+
* Address of deployed partial liquidator contract for GHO credit managers
23+
*/
24+
ghoPartialLiquidatorAddress: Address.optional(),
25+
/**
26+
* Address of deployed partial liquidator contract for DOLA credit managers
27+
*/
28+
dolaPartialLiquidatorAddress: Address.optional(),
29+
/**
30+
* Address of deployed partial liquidator contract for Nexo credit managers
31+
*/
32+
nexoPartialLiquidatorAddress: Address.optional(),
33+
/**
34+
* Address of deployed partial liquidator contract for Sonic credit managers
35+
*/
36+
siloPartialLiquidatorAddress: Address.optional(),
37+
});
38+
39+
export type PartialV300ConfigSchema = z.infer<typeof PartialV300ConfigSchema>;
40+
41+
export const ConfigSchema = PartialV300ConfigSchema.extend({
1742
/**
1843
* By default uses address provider from @gearbox-protocol/sdk
1944
* Use this option to override address provider
@@ -103,22 +128,7 @@ export const ConfigSchema = z.object({
103128
* Usage: deploy them once from local machine then pass the address to production service
104129
*/
105130
deployPartialLiquidatorContracts: booleanLike.pipe(z.boolean().optional()),
106-
/**
107-
* Address of deployed partial liquidator contract for all credit managers except for GHO- and DOLA- based
108-
*/
109-
aavePartialLiquidatorAddress: Address.optional(),
110-
/**
111-
* Address of deployed partial liquidator contract for GHO credit managers
112-
*/
113-
ghoPartialLiquidatorAddress: Address.optional(),
114-
/**
115-
* Address of deployed partial liquidator contract for DOLA credit managers
116-
*/
117-
dolaPartialLiquidatorAddress: Address.optional(),
118-
/**
119-
* Address of deployed partial liquidator contract for Nexo credit managers
120-
*/
121-
nexoPartialLiquidatorAddress: Address.optional(),
131+
122132
/**
123133
* Fallback to use full liquidator when partial liquidator fails
124134
*/

src/services/liquidate/SingularPartialLiquidator.ts

Lines changed: 25 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { iPartialLiquidatorAbi } from "@gearbox-protocol/liquidator-v2-contracts/abi";
22
import type { CreditAccountData } from "@gearbox-protocol/sdk";
3-
import { ADDRESS_0X0, AP_ROUTER, formatBN } from "@gearbox-protocol/sdk";
3+
import { formatBN, TypedObjectUtils } from "@gearbox-protocol/sdk";
44
import {
55
calcLiquidatableLTs,
66
createAnvilClient,
@@ -9,9 +9,10 @@ import {
99
import type { Address, SimulateContractReturnType } from "viem";
1010

1111
import { exceptionsAbis } from "../../data/index.js";
12-
import AAVELiquidatorContract from "./AAVELiquidatorContract.js";
13-
import GHOLiquidatorContract from "./GHOLiquidatorContract.js";
14-
import type PartialLiquidatorContract from "./PartialLiquidatorContract.js";
12+
import {
13+
createPartialLiquidators,
14+
type IPartialLiquidatorContract,
15+
} from "./partial/index.js";
1516
import SingularFullLiquidator from "./SingularFullLiquidator.js";
1617
import SingularLiquidator from "./SingularLiquidator.js";
1718
import type {
@@ -20,18 +21,14 @@ import type {
2021
PartialLiquidationPreviewWithFallback,
2122
} from "./types.js";
2223

23-
// currently there is no reliable way to get this from sdk
24-
const LEGACY_PL_BOT: Address = "0x0f06c2bD612Ee7D52d4bC76Ce3BD7E95247AF2a9";
25-
const NEXO_PL_BOT: Address = "0xc82020f1922AE56CCF25d5F2E2d6155E44583ef9";
26-
2724
export default class SingularPartialLiquidator extends SingularLiquidator<PartialLiquidationPreviewWithFallback> {
2825
protected readonly name = "partial";
2926
protected readonly adverb = "partially";
3027

3128
/**
3229
* mapping of credit manager address to deployed partial liquidator
3330
*/
34-
#liquidatorForCM: Record<Address, PartialLiquidatorContract> = {};
31+
#liquidatorForCM: Record<Address, IPartialLiquidatorContract> = {};
3532
#fallback?: SingularFullLiquidator;
3633

3734
public async launch(asFallback?: boolean): Promise<void> {
@@ -43,84 +40,33 @@ export default class SingularPartialLiquidator extends SingularLiquidator<Partia
4340
await this.#fallback.launch(true);
4441
}
4542

46-
const [router] = this.sdk.addressProvider.getLatestVersion(AP_ROUTER);
47-
48-
const aaveLiquidator = new AAVELiquidatorContract(
49-
"AAVE Partial Liquidator",
50-
router,
51-
LEGACY_PL_BOT,
52-
this.config.aavePartialLiquidatorAddress,
53-
);
54-
const nexoLiquidator = new AAVELiquidatorContract(
55-
"AAVE Nexo Partial Liquidator",
56-
router,
57-
NEXO_PL_BOT,
58-
this.config.nexoPartialLiquidatorAddress,
59-
);
60-
const ghoLiquidator = new GHOLiquidatorContract(
61-
router,
62-
LEGACY_PL_BOT,
63-
"GHO",
64-
);
65-
const dolaLiquidator = new GHOLiquidatorContract(
66-
router,
67-
LEGACY_PL_BOT,
68-
"DOLA",
69-
);
70-
// safe to use 0x0 because none of underlyings is 0x0, so no cms will be added
71-
const GHO =
72-
this.creditAccountService.sdk.tokensMeta.findBySymbol("GHO")?.addr ??
73-
ADDRESS_0X0;
74-
const DOLA =
75-
this.creditAccountService.sdk.tokensMeta.findBySymbol("DOLA")?.addr ??
76-
ADDRESS_0X0;
77-
78-
for (const cm of this.sdk.marketRegister.creditManagers) {
79-
switch (cm.underlying) {
80-
case GHO: {
81-
ghoLiquidator.addCreditManager(cm);
82-
this.#liquidatorForCM[cm.creditManager.address] = ghoLiquidator;
83-
break;
84-
}
85-
case DOLA: {
86-
dolaLiquidator.addCreditManager(cm);
87-
this.#liquidatorForCM[cm.creditManager.address] = dolaLiquidator;
88-
break;
89-
}
90-
default: {
91-
// identifying nexo (aka k3) credit managers
92-
if (cm.name.toLowerCase().includes("k3")) {
93-
nexoLiquidator.addCreditManager(cm);
94-
this.#liquidatorForCM[cm.creditManager.address] = nexoLiquidator;
95-
} else {
96-
aaveLiquidator.addCreditManager(cm);
97-
this.#liquidatorForCM[cm.creditManager.address] = aaveLiquidator;
98-
}
99-
}
100-
}
43+
this.#liquidatorForCM = createPartialLiquidators(this.sdk);
44+
const contracts = new Set<IPartialLiquidatorContract>();
45+
for (const [cm, contract] of TypedObjectUtils.entries(
46+
this.#liquidatorForCM,
47+
)) {
48+
this.logger.debug(
49+
`Will use ${contract.name} for ${this.sdk.provider.addressLabels.get(cm)}`,
50+
);
51+
contracts.add(contract);
10152
}
102-
53+
this.logger.debug(
54+
`Need to deploy ${contracts.size} partial liquidator contracts: ${Array.from(
55+
contracts,
56+
)
57+
.map(c => c.name)
58+
.join(", ")}`,
59+
);
10360
let expectedEnv: Record<string, string> = {};
104-
for (const contract of [
105-
aaveLiquidator,
106-
nexoLiquidator,
107-
ghoLiquidator,
108-
dolaLiquidator,
109-
]) {
110-
if (!contract.isSupported) {
111-
this.logger.info(
112-
`${contract.name} is not supported on ${this.config.network}`,
113-
);
114-
continue;
115-
}
61+
for (const contract of contracts) {
11662
await contract.deploy();
11763
await contract.configure();
11864
expectedEnv = {
11965
...expectedEnv,
120-
...Object.fromEntries([contract.envVariable]),
66+
...contract.envVariables,
12167
};
12268
}
123-
this.logger.info(expectedEnv, "expected env");
69+
this.logger.debug(expectedEnv, "expected env");
12470
}
12571

12672
public async makeLiquidatable(

0 commit comments

Comments
 (0)