1- import {
2- type Address ,
3- decodeAbiParameters ,
4- encodeAbiParameters ,
5- stringToHex ,
6- } from "viem" ;
1+ import { encodeAbiParameters , stringToHex } from "viem" ;
72import { iBytecodeRepositoryAbi } from "../../abi/310/iBytecodeRepository.js" ;
8- import { peripheryCompressorAbi } from "../../abi/compressors/peripheryCompressor.js" ;
93import type { IGearboxSDKPlugin } from "../../sdk/index.js" ;
104import {
115 AddressMap ,
126 AP_BYTECODE_REPOSITORY ,
13- AP_PERIPHERY_COMPRESSOR ,
147 AP_TREASURY ,
158 BasePlugin ,
169 chains as CHAINS ,
1710 hexEq ,
18- isV300 ,
19- isV310 ,
20- TypedObjectUtils ,
21- VERSION_RANGE_310 ,
2211} from "../../sdk/index.js" ;
2312import { iPartialLiquidationBotV310Abi } from "./abi/iPartialLiquidationBotV310.js" ;
2413import {
@@ -27,88 +16,40 @@ import {
2716 PARTIAL_LIQUIDATION_BOT_DEPLOYER ,
2817 PARTIAL_LIQUIDATION_BOT_SALT ,
2918} from "./config.js" ;
30- import { PartialLiquidationBotV300Contract } from "./PartialLiquidationBotV300Contract.js" ;
3119import { PartialLiquidationBotV310Contract } from "./PartialLiquidationBotV310Contract.js" ;
3220import {
3321 BOT_PARAMS_ABI ,
22+ BOT_PARTIAL_LIQUIDATION ,
3423 type BotParameters ,
35- type BotState ,
3624 type BotsPluginState ,
3725 type BotsPluginStateHuman ,
38- LIQUIDATION_BOT_TYPES ,
3926 type MigrationBotState ,
4027} from "./types.js" ;
4128
42- export class UnsupportedBotVersionError extends Error {
43- public readonly state : BotState ;
44-
45- constructor ( state : BotState ) {
46- super (
47- `unsupported bot version ${ state . baseParams . version } for bot at ${ state . baseParams . addr } ` ,
48- ) ;
49- this . state = state ;
50- }
51- }
52-
53- export type PartialLiquidationBotContract =
54- | PartialLiquidationBotV300Contract
55- | PartialLiquidationBotV310Contract ;
56-
5729export class BotsPlugin
5830 extends BasePlugin < BotsPluginState >
5931 implements IGearboxSDKPlugin < BotsPluginState >
6032{
61- #botsByMarket ?: AddressMap < PartialLiquidationBotContract [ ] > ;
33+ #bots ?: AddressMap < PartialLiquidationBotV310Contract > ;
6234
6335 public get loaded ( ) : boolean {
64- return ! ! this . #botsByMarket;
36+ return ! ! this . #bots;
37+ }
38+
39+ public get bots ( ) : PartialLiquidationBotV310Contract [ ] {
40+ return this . #bots?. values ( ) ?? [ ] ;
6541 }
6642
6743 public async load ( force ?: boolean ) : Promise < BotsPluginState > {
6844 if ( ! force && this . loaded ) {
6945 return this . state ;
7046 }
71-
72- const [ pcAddr ] = this . sdk . addressProvider . mustGetLatest (
73- AP_PERIPHERY_COMPRESSOR ,
74- VERSION_RANGE_310 ,
75- ) ;
76- this . logger ?. debug ( `loading bots with periphery compressor ${ pcAddr } ` ) ;
77- const mcs = this . sdk . marketRegister . marketConfigurators . map (
78- mc => mc . address ,
79- ) ;
80-
81- const botsData = await this . client . multicall ( {
82- contracts : mcs . map (
83- mc =>
84- ( {
85- address : pcAddr ,
86- abi : peripheryCompressorAbi ,
87- functionName : "getBots" ,
88- args : [ mc ] ,
89- } ) as const ,
90- ) ,
91- allowFailure : false ,
92- } ) ;
93-
94- this . #botsByMarket = new AddressMap ( ) ;
95- for ( let i = 0 ; i < mcs . length ; i ++ ) {
96- const mc = mcs [ i ] ;
97- const marketBotData = botsData [ i ] ;
98- this . #loadStateMarketState( mc , marketBotData ) ;
99- }
100- return this . state ;
101- }
102-
103- public async findDeployedPartialLiquidationBots ( ) : Promise <
104- AddressMap < BotParameters >
105- > {
10647 const treasury = this . sdk . addressProvider . getAddress ( AP_TREASURY ) ;
10748 const bcr = this . sdk . addressProvider . getAddress ( AP_BYTECODE_REPOSITORY ) ;
10849 const configs = PARTIAL_LIQUIDATION_BOT_CONFIGS [ this . sdk . networkType ] ?? [ ] ;
109- const result = new AddressMap < BotParameters > ( ) ;
50+ this . #bots = new AddressMap < PartialLiquidationBotV310Contract > ( ) ;
11051 if ( ! configs . length ) {
111- return result ;
52+ return this . state ;
11253 }
11354 const deployedBots = await this . client . multicall ( {
11455 contracts : configs . map (
@@ -118,7 +59,7 @@ export class BotsPlugin
11859 abi : iBytecodeRepositoryAbi ,
11960 functionName : "computeAddress" ,
12061 args : [
121- stringToHex ( "BOT::PARTIAL_LIQUIDATION" , { size : 32 } ) ,
62+ stringToHex ( BOT_PARTIAL_LIQUIDATION , { size : 32 } ) ,
12263 310 ,
12364 encodeAbiParameters ( BOT_PARAMS_ABI , [
12465 treasury ,
@@ -170,116 +111,50 @@ export class BotsPlugin
170111 const serialized = serializedBots [ i ] ;
171112 const expected = expectedBots . mustGet ( botAddrs [ i ] ) ;
172113 if ( serialized . status === "success" ) {
173- const [
174- treasury ,
175- minHealthFactor ,
176- maxHealthFactor ,
177- premiumScaleFactor ,
178- feeScaleFactor ,
179- ] = decodeAbiParameters ( BOT_PARAMS_ABI , serialized . result ) ;
114+ const bot = new PartialLiquidationBotV310Contract ( this . sdk , {
115+ addr : botAddrs [ i ] ,
116+ version : BigInt ( 310 ) ,
117+ contractType : BOT_PARTIAL_LIQUIDATION ,
118+ serializedParams : serialized . result ,
119+ } ) ;
180120 if (
181121 ! hexEq ( treasury , expected . treasury ) ||
182- minHealthFactor !== expected . minHealthFactor ||
183- maxHealthFactor !== expected . maxHealthFactor ||
184- premiumScaleFactor !== expected . premiumScaleFactor ||
185- feeScaleFactor !== expected . feeScaleFactor
122+ bot . minHealthFactor !== expected . minHealthFactor ||
123+ bot . maxHealthFactor !== expected . maxHealthFactor ||
124+ bot . premiumScaleFactor !== expected . premiumScaleFactor ||
125+ bot . feeScaleFactor !== expected . feeScaleFactor
186126 ) {
187127 this . logger ?. error (
188128 `serialized bot ${ botAddrs [ i ] } does not match expected bot` ,
189129 serialized . error ,
190130 ) ;
191131 } else {
192- result . upsert ( botAddrs [ i ] , expected ) ;
132+ this . #bots . upsert ( botAddrs [ i ] , bot ) ;
193133 }
194134 }
195135 }
196- return result ;
197- }
198-
199- #loadStateMarketState( mc : Address , state : readonly BotState [ ] ) : void {
200- // for v300, assume that each market configurator has exactly 4 bots
201- // sort them by minHealthFactor and assign type based on index
202- const bots = state
203- . map ( state => this . #createBot( mc , state ) )
204- . sort ( ( a , b ) => a . minHealthFactor - b . minHealthFactor ) ;
205- if ( bots . length && isV300 ( Number ( bots [ 0 ] . version ) ) ) {
206- if ( bots . length !== 4 ) {
207- throw new Error ( `expected 4 bots v300 for market configurator ${ mc } ` ) ;
208- }
209- for ( let i = 0 ; i < bots . length ; i ++ ) {
210- ( bots [ i ] as PartialLiquidationBotV300Contract ) . botType =
211- LIQUIDATION_BOT_TYPES [ i ] ;
212- }
213- }
214- this . botsByMarket . upsert ( mc , bots ) ;
136+ return this . state ;
215137 }
216138
217139 public stateHuman ( raw ?: boolean ) : BotsPluginStateHuman {
218140 return {
219- bots : Object . fromEntries (
220- this . botsByMarket
221- . entries ( )
222- . map ( ( [ mc , bots ] ) => [
223- this . labelAddress ( mc ) ,
224- bots . map ( b => b . stateHuman ( raw ) ) ,
225- ] ) ,
226- ) ,
141+ bots : this . #bots?. values ( ) . map ( bot => bot . stateHuman ( raw ) ) ?? [ ] ,
227142 } ;
228143 }
229144
230- public get botsByMarket ( ) : AddressMap < PartialLiquidationBotContract [ ] > {
231- if ( ! this . #botsByMarket) {
232- throw new Error ( "bots plugin not loaded" ) ;
233- }
234- return this . #botsByMarket;
235- }
236-
237- public botsByMarketConfigurator (
238- mc : Address ,
239- ) : PartialLiquidationBotContract [ ] {
240- return this . botsByMarket . get ( mc ) ?? [ ] ;
241- }
242-
243- public get allBots ( ) : PartialLiquidationBotContract [ ] {
244- return this . botsByMarket . values ( ) . flat ( ) ;
245- }
246-
247145 public get state ( ) : BotsPluginState {
248146 return {
249- bots : TypedObjectUtils . fromEntries (
250- this . botsByMarket
251- . entries ( )
252- . map ( ( [ mc , bots ] ) => [ mc , bots . map ( b => b . state ) ] ) ,
253- ) ,
147+ bots : this . #bots?. values ( ) . map ( bot => bot . state ) ?? [ ] ,
254148 } ;
255149 }
256150
257151 public hydrate ( state : BotsPluginState ) : void {
258- this . #botsByMarket = new AddressMap ( ) ;
259- for ( const [ mc , botStates ] of TypedObjectUtils . entries ( state . bots ) ) {
260- this . #loadStateMarketState( mc , botStates ) ;
261- }
262- }
263-
264- #createBot(
265- marketConfigurator : Address ,
266- data : BotState ,
267- ) : PartialLiquidationBotContract {
268- const v = Number ( data . baseParams . version ) ;
269- if ( isV300 ( v ) ) {
270- return new PartialLiquidationBotV300Contract (
271- this . sdk ,
272- data ,
273- marketConfigurator ,
274- ) ;
275- } else if ( isV310 ( v ) ) {
276- return new PartialLiquidationBotV310Contract (
277- this . sdk ,
278- data ,
279- marketConfigurator ,
152+ this . #bots = new AddressMap ( ) ;
153+ for ( const botState of state . bots ) {
154+ this . #bots. upsert (
155+ botState . addr ,
156+ new PartialLiquidationBotV310Contract ( this . sdk , botState ) ,
280157 ) ;
281- } else {
282- throw new Error ( `unsupported bot version: ${ v } ` ) ;
283158 }
284159 }
285160
0 commit comments