@gearbox-protocol/sdk 8.28.4 → 8.29.1
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.
|
@@ -49,6 +49,7 @@ class AccountOpener extends import_sdk.SDKConstruct {
|
|
|
49
49
|
#faucet;
|
|
50
50
|
#poolDepositMultiplier;
|
|
51
51
|
#minDebtMultiplier;
|
|
52
|
+
#allowMint;
|
|
52
53
|
constructor(service, options_ = {}) {
|
|
53
54
|
super(service.sdk);
|
|
54
55
|
const {
|
|
@@ -56,9 +57,11 @@ class AccountOpener extends import_sdk.SDKConstruct {
|
|
|
56
57
|
depositorKey,
|
|
57
58
|
faucet,
|
|
58
59
|
poolDepositMultiplier = 30000n,
|
|
59
|
-
minDebtMultiplier = 10100n
|
|
60
|
+
minDebtMultiplier = 10100n,
|
|
61
|
+
allowMint = false
|
|
60
62
|
} = options_;
|
|
61
63
|
this.#service = service;
|
|
64
|
+
this.#allowMint = allowMint;
|
|
62
65
|
this.#logger = (0, import_sdk.childLogger)("AccountOpener", service.sdk.logger);
|
|
63
66
|
this.#anvil = (0, import_createAnvilClient.createAnvilClient)({
|
|
64
67
|
chain: service.sdk.provider.chain,
|
|
@@ -244,6 +247,27 @@ class AccountOpener extends import_sdk.SDKConstruct {
|
|
|
244
247
|
},
|
|
245
248
|
"looking for open strategy"
|
|
246
249
|
);
|
|
250
|
+
let borrowerBalance = await this.#anvil.readContract({
|
|
251
|
+
address: underlying,
|
|
252
|
+
abi: import_iERC20.ierc20Abi,
|
|
253
|
+
functionName: "balanceOf",
|
|
254
|
+
args: [borrower.address]
|
|
255
|
+
});
|
|
256
|
+
if (borrowerBalance < minDebt) {
|
|
257
|
+
this.#logger?.warn(
|
|
258
|
+
`borrower balance in underlying: ${this.sdk.tokensMeta.formatBN(underlying, borrowerBalance)} is less than the minimum debt: ${this.sdk.tokensMeta.formatBN(underlying, minDebt)}`
|
|
259
|
+
);
|
|
260
|
+
if (this.#allowMint) {
|
|
261
|
+
borrowerBalance = await this.#tryMint(
|
|
262
|
+
underlying,
|
|
263
|
+
borrower,
|
|
264
|
+
minDebt - borrowerBalance
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
this.#logger?.debug(
|
|
269
|
+
`borrower balance in underlying: ${this.sdk.tokensMeta.formatBN(underlying, borrowerBalance)} ${this.sdk.tokensMeta.symbol(underlying)}`
|
|
270
|
+
);
|
|
247
271
|
const strategy = await this.sdk.routerFor(cm).findOpenStrategyPath({
|
|
248
272
|
creditManager: cm.creditManager,
|
|
249
273
|
expectedBalances,
|
|
@@ -359,12 +383,24 @@ class AccountOpener extends import_sdk.SDKConstruct {
|
|
|
359
383
|
try {
|
|
360
384
|
const amnt = this.sdk.tokensMeta.formatBN(pool.underlying, amount) + " " + this.sdk.tokensMeta.symbol(pool.underlying);
|
|
361
385
|
this.#logger?.debug(`depositing ${amnt} into pool ${poolName}`);
|
|
362
|
-
|
|
386
|
+
let allowance = await this.#anvil.readContract({
|
|
363
387
|
address: underlying,
|
|
364
388
|
abi: import_iERC20.ierc20Abi,
|
|
365
389
|
functionName: "balanceOf",
|
|
366
390
|
args: [depositor.address]
|
|
367
391
|
});
|
|
392
|
+
if (allowance < amount) {
|
|
393
|
+
this.#logger?.warn(
|
|
394
|
+
`depositor balance in underlying: ${this.sdk.tokensMeta.formatBN(pool.underlying, allowance)} is less than the amount to deposit: ${amnt}`
|
|
395
|
+
);
|
|
396
|
+
if (this.#allowMint) {
|
|
397
|
+
allowance = await this.#tryMint(
|
|
398
|
+
underlying,
|
|
399
|
+
depositor,
|
|
400
|
+
amount - allowance
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
368
404
|
this.#logger?.debug(
|
|
369
405
|
`depositor balance in underlying: ${this.sdk.tokensMeta.formatBN(pool.underlying, allowance)}`
|
|
370
406
|
);
|
|
@@ -417,6 +453,78 @@ class AccountOpener extends import_sdk.SDKConstruct {
|
|
|
417
453
|
};
|
|
418
454
|
}
|
|
419
455
|
}
|
|
456
|
+
/**
|
|
457
|
+
* Tries to mint tokens, returns the balance after attempt (success or not)
|
|
458
|
+
* @param token
|
|
459
|
+
* @param dest
|
|
460
|
+
* @param amount
|
|
461
|
+
*/
|
|
462
|
+
async #tryMint(token, dest, amount) {
|
|
463
|
+
const symbol = this.sdk.tokensMeta.symbol(token);
|
|
464
|
+
const amnt = this.sdk.tokensMeta.formatBN(token, amount);
|
|
465
|
+
try {
|
|
466
|
+
await this.#mint(token, dest, amount);
|
|
467
|
+
} catch (e) {
|
|
468
|
+
this.#logger?.warn(
|
|
469
|
+
`failed to mint ${amnt} ${symbol} to ${dest.address}: ${e}`
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
return await this.#anvil.readContract({
|
|
473
|
+
address: token,
|
|
474
|
+
abi: import_iERC20.ierc20Abi,
|
|
475
|
+
functionName: "balanceOf",
|
|
476
|
+
args: [dest.address]
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
async #mint(token, dest, amount) {
|
|
480
|
+
const symbol = this.sdk.tokensMeta.symbol(token);
|
|
481
|
+
const amnt = this.sdk.tokensMeta.formatBN(token, amount);
|
|
482
|
+
this.#logger?.warn(`minting ${amnt} ${symbol} to ${dest.address}`);
|
|
483
|
+
const owner = await this.#anvil.readContract({
|
|
484
|
+
address: token,
|
|
485
|
+
abi: import_abi.iOwnableAbi,
|
|
486
|
+
functionName: "owner"
|
|
487
|
+
});
|
|
488
|
+
this.#logger?.warn(`owner of ${symbol}: ${owner}`);
|
|
489
|
+
await this.#anvil.impersonateAccount({ address: owner });
|
|
490
|
+
await this.#anvil.setBalance({
|
|
491
|
+
address: owner,
|
|
492
|
+
value: (0, import_viem.parseEther)("100")
|
|
493
|
+
});
|
|
494
|
+
let hash = await this.#anvil.writeContract({
|
|
495
|
+
account: owner,
|
|
496
|
+
address: token,
|
|
497
|
+
abi: (0, import_viem.parseAbi)(["function mint(uint256 amount) external returns (bool)"]),
|
|
498
|
+
functionName: "mint",
|
|
499
|
+
args: [amount],
|
|
500
|
+
chain: this.#anvil.chain
|
|
501
|
+
});
|
|
502
|
+
this.#logger?.debug(`mint ${amnt} ${symbol} to ${owner} in tx ${hash}`);
|
|
503
|
+
let receipt = await this.#anvil.waitForTransactionReceipt({ hash });
|
|
504
|
+
if (receipt.status === "reverted") {
|
|
505
|
+
throw new Error(
|
|
506
|
+
`failed to mint ${amnt} ${symbol} to ${owner} in tx ${hash}: reverted`
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
hash = await this.#anvil.writeContract({
|
|
510
|
+
account: owner,
|
|
511
|
+
address: token,
|
|
512
|
+
abi: import_iERC20.ierc20Abi,
|
|
513
|
+
functionName: "transfer",
|
|
514
|
+
args: [dest.address, amount],
|
|
515
|
+
chain: this.#anvil.chain
|
|
516
|
+
});
|
|
517
|
+
this.#logger?.debug(
|
|
518
|
+
`transfer ${amnt} ${symbol} from ${owner} to ${dest.address} in tx ${hash}`
|
|
519
|
+
);
|
|
520
|
+
receipt = await this.#anvil.waitForTransactionReceipt({ hash });
|
|
521
|
+
if (receipt.status === "reverted") {
|
|
522
|
+
throw new Error(
|
|
523
|
+
`failed to transfer ${amnt} ${symbol} from ${owner} to ${dest.address} in tx ${hash}: reverted`
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
await this.#anvil.stopImpersonatingAccount({ address: owner });
|
|
527
|
+
}
|
|
420
528
|
/**
|
|
421
529
|
* Creates borrower wallet,
|
|
422
530
|
* Sets ETH balance,
|
|
@@ -52,7 +52,25 @@ const ADDRESS_PROVIDER_BLOCK = {
|
|
|
52
52
|
Lisk: 18934260n
|
|
53
53
|
// arbitrary not deployed yet
|
|
54
54
|
};
|
|
55
|
-
const BLOCK_DURATION_LOCAL = {
|
|
55
|
+
const BLOCK_DURATION_LOCAL = {
|
|
56
|
+
Mainnet: 12050,
|
|
57
|
+
Arbitrum: 260,
|
|
58
|
+
Optimism: 2e3,
|
|
59
|
+
Base: 2010,
|
|
60
|
+
Sonic: 910,
|
|
61
|
+
// New networks
|
|
62
|
+
MegaETH: 10,
|
|
63
|
+
// <10ms/block, on testnet
|
|
64
|
+
Monad: 1e3,
|
|
65
|
+
// on testnet
|
|
66
|
+
Berachain: 1900,
|
|
67
|
+
Avalanche: 1700,
|
|
68
|
+
BNB: 3e3,
|
|
69
|
+
WorldChain: 2e3,
|
|
70
|
+
Etherlink: 1e3,
|
|
71
|
+
Hemi: 12e3,
|
|
72
|
+
Lisk: 2e3
|
|
73
|
+
};
|
|
56
74
|
const BLOCK_DURATION = Object.values(import_chain.chains).reduce(
|
|
57
75
|
(acc, chain) => {
|
|
58
76
|
const blockTime = chain.blockTime || BLOCK_DURATION_LOCAL[chain.network] || 0;
|
|
@@ -66,7 +84,9 @@ const BLOCK_DURATION = Object.values(import_chain.chains).reduce(
|
|
|
66
84
|
const RAMP_TIME = 30 * 24 * 60 * 60 * 1.2;
|
|
67
85
|
const RAMP_DURATION_BY_NETWORK = import_mappers.TypedObjectUtils.entries(BLOCK_DURATION).reduce(
|
|
68
86
|
(acc, [n, duration]) => {
|
|
69
|
-
|
|
87
|
+
if (duration !== 0) {
|
|
88
|
+
acc[n] = BigInt(Math.floor(RAMP_TIME / duration));
|
|
89
|
+
}
|
|
70
90
|
return acc;
|
|
71
91
|
},
|
|
72
92
|
{}
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
BaseError,
|
|
3
3
|
erc20Abi,
|
|
4
4
|
isAddress,
|
|
5
|
+
parseAbi,
|
|
5
6
|
parseEther,
|
|
6
7
|
parseEventLogs
|
|
7
8
|
} from "viem";
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
SDKConstruct,
|
|
20
21
|
sendRawTx
|
|
21
22
|
} from "../sdk/index.js";
|
|
22
|
-
import { iDegenNftv2Abi } from "./abi.js";
|
|
23
|
+
import { iDegenNftv2Abi, iOwnableAbi } from "./abi.js";
|
|
23
24
|
import { claimFromFaucet } from "./claimFromFaucet.js";
|
|
24
25
|
import { createAnvilClient } from "./createAnvilClient.js";
|
|
25
26
|
const DIRECT_TRANSFERS_QUOTA = 10000n;
|
|
@@ -41,6 +42,7 @@ class AccountOpener extends SDKConstruct {
|
|
|
41
42
|
#faucet;
|
|
42
43
|
#poolDepositMultiplier;
|
|
43
44
|
#minDebtMultiplier;
|
|
45
|
+
#allowMint;
|
|
44
46
|
constructor(service, options_ = {}) {
|
|
45
47
|
super(service.sdk);
|
|
46
48
|
const {
|
|
@@ -48,9 +50,11 @@ class AccountOpener extends SDKConstruct {
|
|
|
48
50
|
depositorKey,
|
|
49
51
|
faucet,
|
|
50
52
|
poolDepositMultiplier = 30000n,
|
|
51
|
-
minDebtMultiplier = 10100n
|
|
53
|
+
minDebtMultiplier = 10100n,
|
|
54
|
+
allowMint = false
|
|
52
55
|
} = options_;
|
|
53
56
|
this.#service = service;
|
|
57
|
+
this.#allowMint = allowMint;
|
|
54
58
|
this.#logger = childLogger("AccountOpener", service.sdk.logger);
|
|
55
59
|
this.#anvil = createAnvilClient({
|
|
56
60
|
chain: service.sdk.provider.chain,
|
|
@@ -236,6 +240,27 @@ class AccountOpener extends SDKConstruct {
|
|
|
236
240
|
},
|
|
237
241
|
"looking for open strategy"
|
|
238
242
|
);
|
|
243
|
+
let borrowerBalance = await this.#anvil.readContract({
|
|
244
|
+
address: underlying,
|
|
245
|
+
abi: ierc20Abi,
|
|
246
|
+
functionName: "balanceOf",
|
|
247
|
+
args: [borrower.address]
|
|
248
|
+
});
|
|
249
|
+
if (borrowerBalance < minDebt) {
|
|
250
|
+
this.#logger?.warn(
|
|
251
|
+
`borrower balance in underlying: ${this.sdk.tokensMeta.formatBN(underlying, borrowerBalance)} is less than the minimum debt: ${this.sdk.tokensMeta.formatBN(underlying, minDebt)}`
|
|
252
|
+
);
|
|
253
|
+
if (this.#allowMint) {
|
|
254
|
+
borrowerBalance = await this.#tryMint(
|
|
255
|
+
underlying,
|
|
256
|
+
borrower,
|
|
257
|
+
minDebt - borrowerBalance
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
this.#logger?.debug(
|
|
262
|
+
`borrower balance in underlying: ${this.sdk.tokensMeta.formatBN(underlying, borrowerBalance)} ${this.sdk.tokensMeta.symbol(underlying)}`
|
|
263
|
+
);
|
|
239
264
|
const strategy = await this.sdk.routerFor(cm).findOpenStrategyPath({
|
|
240
265
|
creditManager: cm.creditManager,
|
|
241
266
|
expectedBalances,
|
|
@@ -351,12 +376,24 @@ class AccountOpener extends SDKConstruct {
|
|
|
351
376
|
try {
|
|
352
377
|
const amnt = this.sdk.tokensMeta.formatBN(pool.underlying, amount) + " " + this.sdk.tokensMeta.symbol(pool.underlying);
|
|
353
378
|
this.#logger?.debug(`depositing ${amnt} into pool ${poolName}`);
|
|
354
|
-
|
|
379
|
+
let allowance = await this.#anvil.readContract({
|
|
355
380
|
address: underlying,
|
|
356
381
|
abi: ierc20Abi,
|
|
357
382
|
functionName: "balanceOf",
|
|
358
383
|
args: [depositor.address]
|
|
359
384
|
});
|
|
385
|
+
if (allowance < amount) {
|
|
386
|
+
this.#logger?.warn(
|
|
387
|
+
`depositor balance in underlying: ${this.sdk.tokensMeta.formatBN(pool.underlying, allowance)} is less than the amount to deposit: ${amnt}`
|
|
388
|
+
);
|
|
389
|
+
if (this.#allowMint) {
|
|
390
|
+
allowance = await this.#tryMint(
|
|
391
|
+
underlying,
|
|
392
|
+
depositor,
|
|
393
|
+
amount - allowance
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
360
397
|
this.#logger?.debug(
|
|
361
398
|
`depositor balance in underlying: ${this.sdk.tokensMeta.formatBN(pool.underlying, allowance)}`
|
|
362
399
|
);
|
|
@@ -409,6 +446,78 @@ class AccountOpener extends SDKConstruct {
|
|
|
409
446
|
};
|
|
410
447
|
}
|
|
411
448
|
}
|
|
449
|
+
/**
|
|
450
|
+
* Tries to mint tokens, returns the balance after attempt (success or not)
|
|
451
|
+
* @param token
|
|
452
|
+
* @param dest
|
|
453
|
+
* @param amount
|
|
454
|
+
*/
|
|
455
|
+
async #tryMint(token, dest, amount) {
|
|
456
|
+
const symbol = this.sdk.tokensMeta.symbol(token);
|
|
457
|
+
const amnt = this.sdk.tokensMeta.formatBN(token, amount);
|
|
458
|
+
try {
|
|
459
|
+
await this.#mint(token, dest, amount);
|
|
460
|
+
} catch (e) {
|
|
461
|
+
this.#logger?.warn(
|
|
462
|
+
`failed to mint ${amnt} ${symbol} to ${dest.address}: ${e}`
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
return await this.#anvil.readContract({
|
|
466
|
+
address: token,
|
|
467
|
+
abi: ierc20Abi,
|
|
468
|
+
functionName: "balanceOf",
|
|
469
|
+
args: [dest.address]
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
async #mint(token, dest, amount) {
|
|
473
|
+
const symbol = this.sdk.tokensMeta.symbol(token);
|
|
474
|
+
const amnt = this.sdk.tokensMeta.formatBN(token, amount);
|
|
475
|
+
this.#logger?.warn(`minting ${amnt} ${symbol} to ${dest.address}`);
|
|
476
|
+
const owner = await this.#anvil.readContract({
|
|
477
|
+
address: token,
|
|
478
|
+
abi: iOwnableAbi,
|
|
479
|
+
functionName: "owner"
|
|
480
|
+
});
|
|
481
|
+
this.#logger?.warn(`owner of ${symbol}: ${owner}`);
|
|
482
|
+
await this.#anvil.impersonateAccount({ address: owner });
|
|
483
|
+
await this.#anvil.setBalance({
|
|
484
|
+
address: owner,
|
|
485
|
+
value: parseEther("100")
|
|
486
|
+
});
|
|
487
|
+
let hash = await this.#anvil.writeContract({
|
|
488
|
+
account: owner,
|
|
489
|
+
address: token,
|
|
490
|
+
abi: parseAbi(["function mint(uint256 amount) external returns (bool)"]),
|
|
491
|
+
functionName: "mint",
|
|
492
|
+
args: [amount],
|
|
493
|
+
chain: this.#anvil.chain
|
|
494
|
+
});
|
|
495
|
+
this.#logger?.debug(`mint ${amnt} ${symbol} to ${owner} in tx ${hash}`);
|
|
496
|
+
let receipt = await this.#anvil.waitForTransactionReceipt({ hash });
|
|
497
|
+
if (receipt.status === "reverted") {
|
|
498
|
+
throw new Error(
|
|
499
|
+
`failed to mint ${amnt} ${symbol} to ${owner} in tx ${hash}: reverted`
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
hash = await this.#anvil.writeContract({
|
|
503
|
+
account: owner,
|
|
504
|
+
address: token,
|
|
505
|
+
abi: ierc20Abi,
|
|
506
|
+
functionName: "transfer",
|
|
507
|
+
args: [dest.address, amount],
|
|
508
|
+
chain: this.#anvil.chain
|
|
509
|
+
});
|
|
510
|
+
this.#logger?.debug(
|
|
511
|
+
`transfer ${amnt} ${symbol} from ${owner} to ${dest.address} in tx ${hash}`
|
|
512
|
+
);
|
|
513
|
+
receipt = await this.#anvil.waitForTransactionReceipt({ hash });
|
|
514
|
+
if (receipt.status === "reverted") {
|
|
515
|
+
throw new Error(
|
|
516
|
+
`failed to transfer ${amnt} ${symbol} from ${owner} to ${dest.address} in tx ${hash}: reverted`
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
await this.#anvil.stopImpersonatingAccount({ address: owner });
|
|
520
|
+
}
|
|
412
521
|
/**
|
|
413
522
|
* Creates borrower wallet,
|
|
414
523
|
* Sets ETH balance,
|
|
@@ -27,7 +27,25 @@ const ADDRESS_PROVIDER_BLOCK = {
|
|
|
27
27
|
Lisk: 18934260n
|
|
28
28
|
// arbitrary not deployed yet
|
|
29
29
|
};
|
|
30
|
-
const BLOCK_DURATION_LOCAL = {
|
|
30
|
+
const BLOCK_DURATION_LOCAL = {
|
|
31
|
+
Mainnet: 12050,
|
|
32
|
+
Arbitrum: 260,
|
|
33
|
+
Optimism: 2e3,
|
|
34
|
+
Base: 2010,
|
|
35
|
+
Sonic: 910,
|
|
36
|
+
// New networks
|
|
37
|
+
MegaETH: 10,
|
|
38
|
+
// <10ms/block, on testnet
|
|
39
|
+
Monad: 1e3,
|
|
40
|
+
// on testnet
|
|
41
|
+
Berachain: 1900,
|
|
42
|
+
Avalanche: 1700,
|
|
43
|
+
BNB: 3e3,
|
|
44
|
+
WorldChain: 2e3,
|
|
45
|
+
Etherlink: 1e3,
|
|
46
|
+
Hemi: 12e3,
|
|
47
|
+
Lisk: 2e3
|
|
48
|
+
};
|
|
31
49
|
const BLOCK_DURATION = Object.values(CHAINS).reduce(
|
|
32
50
|
(acc, chain) => {
|
|
33
51
|
const blockTime = chain.blockTime || BLOCK_DURATION_LOCAL[chain.network] || 0;
|
|
@@ -41,7 +59,9 @@ const BLOCK_DURATION = Object.values(CHAINS).reduce(
|
|
|
41
59
|
const RAMP_TIME = 30 * 24 * 60 * 60 * 1.2;
|
|
42
60
|
const RAMP_DURATION_BY_NETWORK = TypedObjectUtils.entries(BLOCK_DURATION).reduce(
|
|
43
61
|
(acc, [n, duration]) => {
|
|
44
|
-
|
|
62
|
+
if (duration !== 0) {
|
|
63
|
+
acc[n] = BigInt(Math.floor(RAMP_TIME / duration));
|
|
64
|
+
}
|
|
45
65
|
return acc;
|
|
46
66
|
},
|
|
47
67
|
{}
|