curvance 4.0.3 → 4.1.0
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.
- package/README.md +595 -59
- package/dist/chains/arbitrum.d.ts.map +1 -1
- package/dist/chains/arbitrum.js +4 -2
- package/dist/chains/arbitrum.js.map +1 -1
- package/dist/chains/index.d.ts +4 -0
- package/dist/chains/index.d.ts.map +1 -1
- package/dist/chains/index.js +15 -0
- package/dist/chains/index.js.map +1 -1
- package/dist/chains/monad.d.ts.map +1 -1
- package/dist/chains/monad.js +4 -2
- package/dist/chains/monad.js.map +1 -1
- package/dist/chains/rpc.d.ts +57 -0
- package/dist/chains/rpc.d.ts.map +1 -0
- package/dist/chains/rpc.js +47 -0
- package/dist/chains/rpc.js.map +1 -0
- package/dist/classes/Api.d.ts +4 -3
- package/dist/classes/Api.d.ts.map +1 -1
- package/dist/classes/Api.js +7 -7
- package/dist/classes/Api.js.map +1 -1
- package/dist/classes/BorrowableCToken.d.ts +3 -2
- package/dist/classes/BorrowableCToken.d.ts.map +1 -1
- package/dist/classes/BorrowableCToken.js +6 -5
- package/dist/classes/BorrowableCToken.js.map +1 -1
- package/dist/classes/CToken.d.ts +11 -3
- package/dist/classes/CToken.d.ts.map +1 -1
- package/dist/classes/CToken.js +168 -116
- package/dist/classes/CToken.js.map +1 -1
- package/dist/classes/Calldata.d.ts +2 -2
- package/dist/classes/Calldata.d.ts.map +1 -1
- package/dist/classes/Calldata.js +2 -2
- package/dist/classes/Calldata.js.map +1 -1
- package/dist/classes/DexAggregators/IDexAgg.d.ts +2 -2
- package/dist/classes/DexAggregators/IDexAgg.d.ts.map +1 -1
- package/dist/classes/DexAggregators/Kuru.d.ts +2 -2
- package/dist/classes/DexAggregators/Kuru.d.ts.map +1 -1
- package/dist/classes/DexAggregators/Kuru.js +3 -4
- package/dist/classes/DexAggregators/Kuru.js.map +1 -1
- package/dist/classes/DexAggregators/KyberSwap.d.ts +2 -2
- package/dist/classes/DexAggregators/KyberSwap.d.ts.map +1 -1
- package/dist/classes/DexAggregators/KyberSwap.js +88 -9
- package/dist/classes/DexAggregators/KyberSwap.js.map +1 -1
- package/dist/classes/DexAggregators/MultiDexAgg.d.ts +2 -2
- package/dist/classes/DexAggregators/MultiDexAgg.d.ts.map +1 -1
- package/dist/classes/DexAggregators/MultiDexAgg.js +3 -3
- package/dist/classes/DexAggregators/MultiDexAgg.js.map +1 -1
- package/dist/classes/ERC20.d.ts +5 -3
- package/dist/classes/ERC20.d.ts.map +1 -1
- package/dist/classes/ERC20.js +20 -14
- package/dist/classes/ERC20.js.map +1 -1
- package/dist/classes/ERC4626.d.ts.map +1 -1
- package/dist/classes/ERC4626.js +3 -1
- package/dist/classes/ERC4626.js.map +1 -1
- package/dist/classes/Market.d.ts +13 -4
- package/dist/classes/Market.d.ts.map +1 -1
- package/dist/classes/Market.js +86 -28
- package/dist/classes/Market.js.map +1 -1
- package/dist/classes/NativeToken.d.ts +6 -3
- package/dist/classes/NativeToken.d.ts.map +1 -1
- package/dist/classes/NativeToken.js +11 -16
- package/dist/classes/NativeToken.js.map +1 -1
- package/dist/classes/OptimizerReader.d.ts +3 -3
- package/dist/classes/OptimizerReader.d.ts.map +1 -1
- package/dist/classes/OptimizerReader.js +1 -1
- package/dist/classes/OptimizerReader.js.map +1 -1
- package/dist/classes/OracleManager.d.ts +3 -3
- package/dist/classes/OracleManager.d.ts.map +1 -1
- package/dist/classes/OracleManager.js +1 -1
- package/dist/classes/OracleManager.js.map +1 -1
- package/dist/classes/PositionManager.d.ts +2 -2
- package/dist/classes/PositionManager.d.ts.map +1 -1
- package/dist/classes/PositionManager.js +4 -4
- package/dist/classes/PositionManager.js.map +1 -1
- package/dist/classes/ProtocolReader.d.ts +18 -4
- package/dist/classes/ProtocolReader.d.ts.map +1 -1
- package/dist/classes/ProtocolReader.js +177 -55
- package/dist/classes/ProtocolReader.js.map +1 -1
- package/dist/classes/Redstone.d.ts.map +1 -1
- package/dist/classes/Redstone.js +1 -2
- package/dist/classes/Redstone.js.map +1 -1
- package/dist/classes/Zapper.d.ts +4 -2
- package/dist/classes/Zapper.d.ts.map +1 -1
- package/dist/classes/Zapper.js +16 -14
- package/dist/classes/Zapper.js.map +1 -1
- package/dist/classes/index.d.ts +1 -1
- package/dist/classes/index.d.ts.map +1 -1
- package/dist/classes/index.js +6 -1
- package/dist/classes/index.js.map +1 -1
- package/dist/contracts/monad-mainnet.json +1 -1
- package/dist/feePolicy.d.ts +27 -1
- package/dist/feePolicy.d.ts.map +1 -1
- package/dist/feePolicy.js +10 -2
- package/dist/feePolicy.js.map +1 -1
- package/dist/helpers.d.ts +3 -1
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +34 -4
- package/dist/helpers.js.map +1 -1
- package/dist/integrations/snapshot.d.ts.map +1 -1
- package/dist/integrations/snapshot.js +4 -18
- package/dist/integrations/snapshot.js.map +1 -1
- package/dist/retry-provider.d.ts +81 -6
- package/dist/retry-provider.d.ts.map +1 -1
- package/dist/retry-provider.js +491 -37
- package/dist/retry-provider.js.map +1 -1
- package/dist/setup.d.ts +14 -3
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +56 -20
- package/dist/setup.js.map +1 -1
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -1
package/dist/classes/CToken.js
CHANGED
|
@@ -12,12 +12,10 @@ const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
|
12
12
|
const BaseCToken_json_1 = __importDefault(require("../abis/BaseCToken.json"));
|
|
13
13
|
const Redstone_1 = require("./Redstone");
|
|
14
14
|
const Zapper_1 = require("./Zapper");
|
|
15
|
-
const setup_1 = require("../setup");
|
|
16
15
|
const PositionManager_1 = require("./PositionManager");
|
|
17
16
|
const NativeToken_1 = require("./NativeToken");
|
|
18
17
|
const ERC4626_1 = require("./ERC4626");
|
|
19
18
|
const FormatConverter_1 = __importDefault(require("./FormatConverter"));
|
|
20
|
-
const chains_1 = require("../chains");
|
|
21
19
|
const EXCLUDED_ZAP_SYMBOLS = new Set([
|
|
22
20
|
'eBTC', 'earnAUSD', 'vUSD', 'syzUSD', 'ezETH', 'YZM', 'wsrUSD', 'sAUSD',
|
|
23
21
|
]);
|
|
@@ -44,12 +42,13 @@ const EXCLUDED_ZAP_SYMBOLS = new Set([
|
|
|
44
42
|
* docstring "primarily a sanity check rather than a security guarantee."
|
|
45
43
|
* Real MEV protection comes from SwapperLib._swapSafe, which oracle-prices
|
|
46
44
|
* the swap input and output and reverts if realized slippage exceeds the
|
|
47
|
-
* Swap.slippage parameter we pass
|
|
45
|
+
* Swap.slippage parameter we pass.
|
|
48
46
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
47
|
+
* Because _swapSafe measures value loss against the FULL input (pre-fee),
|
|
48
|
+
* the deterministic KyberSwap fee would consume feeBps of the user's MEV
|
|
49
|
+
* tolerance if not compensated. Each call site expands action.slippage by
|
|
50
|
+
* feeBps after quoting so the fee is absorbed and the user's chosen
|
|
51
|
+
* tolerance is preserved for actual MEV/routing variance.
|
|
53
52
|
*
|
|
54
53
|
* Asymmetry between leverage up and deleverage
|
|
55
54
|
* --------------------------------------------
|
|
@@ -75,16 +74,15 @@ const LEVERAGE = {
|
|
|
75
74
|
* the slippage buffers below — protects post-op position health, not
|
|
76
75
|
* in-op slippage. */
|
|
77
76
|
MAX_LEVERAGE_FACTOR: (0, decimal_js_1.default)(0.995),
|
|
78
|
-
/** Flat BPS buffer added to leverage-up
|
|
79
|
-
* Under single-oracle, the only forced loss
|
|
80
|
-
* rounding plus possible Redstone price drift between
|
|
81
|
-
* and
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* range, especially at L > 5 with low (1%) user slippage. */
|
|
77
|
+
/** Flat BPS buffer added to leverage-up DEX/swapSafe slippage tolerance.
|
|
78
|
+
* Under single-oracle, the only forced loss at the swap level comes from
|
|
79
|
+
* wei-level share rounding plus possible Redstone price drift between
|
|
80
|
+
* snapshot RPC and tx broadcast block. Both are small constants.
|
|
81
|
+
*
|
|
82
|
+
* Fee handling: each call site expands both action.slippage (by feeBps,
|
|
83
|
+
* so _swapSafe doesn't treat the fee as MEV) and contractSlippage (by
|
|
84
|
+
* (L-1) × feeBps, so checkSlippage doesn't fire from equity-fraction
|
|
85
|
+
* amplification). This buffer covers rounding/drift only. */
|
|
88
86
|
LEVERAGE_UP_BUFFER_BPS: 10n,
|
|
89
87
|
/** BPS overhead on full deleverage swap sizing — absolute terms.
|
|
90
88
|
* Oversizes the collateral→debt swap so DEX impact + drift doesn't
|
|
@@ -114,6 +112,8 @@ class CToken extends Calldata_1.Calldata {
|
|
|
114
112
|
nativeApy = (0, decimal_js_1.default)(0);
|
|
115
113
|
incentiveSupplyApy = (0, decimal_js_1.default)(0);
|
|
116
114
|
incentiveBorrowApy = (0, decimal_js_1.default)(0);
|
|
115
|
+
get signer() { return this.market.signer; }
|
|
116
|
+
get account() { return this.market.account; }
|
|
117
117
|
constructor(provider, address, cache, market) {
|
|
118
118
|
super();
|
|
119
119
|
this.provider = provider;
|
|
@@ -121,11 +121,11 @@ class CToken extends Calldata_1.Calldata {
|
|
|
121
121
|
this.contract = (0, helpers_1.contractSetup)(provider, address, BaseCToken_json_1.default);
|
|
122
122
|
this.cache = cache;
|
|
123
123
|
this.market = market;
|
|
124
|
-
const
|
|
124
|
+
const chainSettings = this.currentChainConfig;
|
|
125
125
|
const assetAddr = this.asset.address.toLowerCase();
|
|
126
|
-
this.isNativeVault =
|
|
127
|
-
this.isVault =
|
|
128
|
-
this.isWrappedNative =
|
|
126
|
+
this.isNativeVault = chainSettings.native_vaults.some(vault => vault.contract.toLowerCase() == assetAddr);
|
|
127
|
+
this.isVault = chainSettings.vaults.some(vault => vault.contract.toLowerCase() == assetAddr);
|
|
128
|
+
this.isWrappedNative = chainSettings.wrapped_native.toLowerCase() == assetAddr;
|
|
129
129
|
if (EXCLUDED_ZAP_SYMBOLS.has(this.asset.symbol)) {
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
@@ -143,6 +143,16 @@ class CToken extends Calldata_1.Calldata {
|
|
|
143
143
|
this.leverageTypes.push('simple');
|
|
144
144
|
this.zapTypes.push('simple');
|
|
145
145
|
}
|
|
146
|
+
get setup() { return this.market.setup; }
|
|
147
|
+
get currentChain() { return this.setup.chain; }
|
|
148
|
+
get currentChainConfig() { return (0, helpers_1.getChainConfig)(this.currentChain); }
|
|
149
|
+
requireSigner() { return (0, helpers_1.requireSigner)(this.signer); }
|
|
150
|
+
getAccountOrThrow(account = null) {
|
|
151
|
+
return (0, helpers_1.requireAccount)(account ?? this.account, this.signer);
|
|
152
|
+
}
|
|
153
|
+
getWriteContract() {
|
|
154
|
+
return (0, helpers_1.contractSetup)(this.requireSigner(), this.address, BaseCToken_json_1.default);
|
|
155
|
+
}
|
|
146
156
|
get adapters() { return this.cache.adapters; }
|
|
147
157
|
get borrowPaused() { return this.cache.borrowPaused; }
|
|
148
158
|
get collateralizationPaused() { return this.cache.collateralizationPaused; }
|
|
@@ -260,8 +270,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
260
270
|
return inUSD ? this.convertTokensToUsd(this.cache.userCollateral, false) : FormatConverter_1.default.bigIntToDecimal(this.cache.userCollateral, this.decimals);
|
|
261
271
|
}
|
|
262
272
|
async fetchUserCollateral(formatted = false) {
|
|
263
|
-
const
|
|
264
|
-
const collateral = await this.contract.collateralPosted(signer.address);
|
|
273
|
+
const collateral = await this.contract.collateralPosted(this.getAccountOrThrow());
|
|
265
274
|
this.cache.userCollateral = collateral;
|
|
266
275
|
return formatted ? (0, helpers_1.toDecimal)(collateral, this.decimals) : collateral;
|
|
267
276
|
}
|
|
@@ -285,13 +294,15 @@ class CToken extends Calldata_1.Calldata {
|
|
|
285
294
|
if (!this.isVault && !this.isNativeVault) {
|
|
286
295
|
throw new Error("CToken does not use a vault asset as its underlying asset");
|
|
287
296
|
}
|
|
288
|
-
return new ERC4626_1.ERC4626(this.provider, this.getAsset(false));
|
|
297
|
+
return new ERC4626_1.ERC4626(this.provider, this.getAsset(false), undefined, this.setup.contracts.OracleManager, this.signer);
|
|
289
298
|
}
|
|
290
299
|
async getVaultAsset(asErc20) {
|
|
291
300
|
return asErc20 ? await this.getUnderlyingVault().fetchAsset(true) : await this.getUnderlyingVault().fetchAsset(false);
|
|
292
301
|
}
|
|
293
302
|
getAsset(asErc20) {
|
|
294
|
-
return asErc20
|
|
303
|
+
return asErc20
|
|
304
|
+
? new ERC20_1.ERC20(this.provider, this.cache.asset.address, this.cache.asset, this.setup.contracts.OracleManager, this.signer)
|
|
305
|
+
: this.cache.asset.address;
|
|
295
306
|
}
|
|
296
307
|
getPrice(asset = false, lower = false, formatted = true) {
|
|
297
308
|
let price = asset ? this.cache.assetPrice : this.cache.sharePrice;
|
|
@@ -335,7 +346,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
335
346
|
return inUSD ? this.fetchConvertTokensToUsd(totalCollateral) : totalCollateral;
|
|
336
347
|
}
|
|
337
348
|
getPositionManager(type) {
|
|
338
|
-
const signer =
|
|
349
|
+
const signer = this.requireSigner();
|
|
339
350
|
let manager_contract = this.getPluginAddress(type, 'positionManager');
|
|
340
351
|
if (manager_contract == null) {
|
|
341
352
|
throw new Error("Plugin does not have an associated contract");
|
|
@@ -343,12 +354,12 @@ class CToken extends Calldata_1.Calldata {
|
|
|
343
354
|
return new PositionManager_1.PositionManager(manager_contract, signer, type);
|
|
344
355
|
}
|
|
345
356
|
getZapper(type) {
|
|
346
|
-
const signer =
|
|
357
|
+
const signer = this.requireSigner();
|
|
347
358
|
const zap_contract = this.getPluginAddress(type, 'zapper');
|
|
348
359
|
if (zap_contract == null) {
|
|
349
360
|
return null;
|
|
350
361
|
}
|
|
351
|
-
return new Zapper_1.Zapper(zap_contract, signer, type);
|
|
362
|
+
return new Zapper_1.Zapper(zap_contract, signer, type, this.setup);
|
|
352
363
|
}
|
|
353
364
|
async isZapAssetApproved(instructions, amount) {
|
|
354
365
|
if (instructions == 'none' || typeof instructions != 'object') {
|
|
@@ -357,8 +368,8 @@ class CToken extends Calldata_1.Calldata {
|
|
|
357
368
|
if (instructions.inputToken.toLowerCase() === helpers_1.NATIVE_ADDRESS.toLowerCase()) {
|
|
358
369
|
return true;
|
|
359
370
|
}
|
|
360
|
-
const signer =
|
|
361
|
-
const asset = new ERC20_1.ERC20(
|
|
371
|
+
const signer = this.requireSigner();
|
|
372
|
+
const asset = new ERC20_1.ERC20(this.provider, instructions.inputToken, undefined, undefined, signer);
|
|
362
373
|
const plugin = this.getPluginAddress(instructions.type, 'zapper');
|
|
363
374
|
const allowance = await asset.allowance(signer.address, plugin);
|
|
364
375
|
return allowance >= amount;
|
|
@@ -370,8 +381,8 @@ class CToken extends Calldata_1.Calldata {
|
|
|
370
381
|
if (instructions.inputToken.toLowerCase() === helpers_1.NATIVE_ADDRESS.toLowerCase()) {
|
|
371
382
|
return;
|
|
372
383
|
}
|
|
373
|
-
const signer =
|
|
374
|
-
const asset = new ERC20_1.ERC20(
|
|
384
|
+
const signer = this.requireSigner();
|
|
385
|
+
const asset = new ERC20_1.ERC20(this.provider, instructions.inputToken, undefined, undefined, signer);
|
|
375
386
|
const plugin = this.getPluginAddress(instructions.type, 'zapper');
|
|
376
387
|
return asset.approve(plugin, amount);
|
|
377
388
|
}
|
|
@@ -379,7 +390,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
379
390
|
if (plugin == 'none') {
|
|
380
391
|
return true;
|
|
381
392
|
}
|
|
382
|
-
const signer =
|
|
393
|
+
const signer = this.requireSigner();
|
|
383
394
|
const plugin_address = this.getPluginAddress(plugin, type);
|
|
384
395
|
if (plugin_address == null) {
|
|
385
396
|
throw new Error("Plugin does not have an associated contract");
|
|
@@ -391,7 +402,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
391
402
|
if (plugin_address == null) {
|
|
392
403
|
throw new Error("Plugin does not have an associated contract");
|
|
393
404
|
}
|
|
394
|
-
return this.
|
|
405
|
+
return this.getWriteContract().setDelegateApproval(plugin_address, true);
|
|
395
406
|
}
|
|
396
407
|
getPluginAddress(plugin, type) {
|
|
397
408
|
switch (type) {
|
|
@@ -402,10 +413,10 @@ class CToken extends Calldata_1.Calldata {
|
|
|
402
413
|
throw new Error("Plugin does not have a contract to map too");
|
|
403
414
|
}
|
|
404
415
|
const plugin_name = Zapper_1.zapperTypeToName.get(plugin);
|
|
405
|
-
if (!plugin_name || !
|
|
416
|
+
if (!plugin_name || !this.setup.contracts.zappers || !(plugin_name in this.setup.contracts.zappers)) {
|
|
406
417
|
throw new Error(`Plugin ${plugin_name} not found in zappers`);
|
|
407
418
|
}
|
|
408
|
-
return
|
|
419
|
+
return this.setup.contracts.zappers[plugin_name];
|
|
409
420
|
}
|
|
410
421
|
case 'positionManager': {
|
|
411
422
|
switch (plugin) {
|
|
@@ -419,8 +430,8 @@ class CToken extends Calldata_1.Calldata {
|
|
|
419
430
|
}
|
|
420
431
|
}
|
|
421
432
|
async getAllowance(check_contract, underlying = true) {
|
|
422
|
-
const signer =
|
|
423
|
-
const erc20 = new ERC20_1.ERC20(this.provider, underlying ? this.asset.address : this.address);
|
|
433
|
+
const signer = this.requireSigner();
|
|
434
|
+
const erc20 = new ERC20_1.ERC20(this.provider, underlying ? this.asset.address : this.address, undefined, undefined, this.signer);
|
|
424
435
|
const allowance = await erc20.allowance(signer.address, check_contract);
|
|
425
436
|
return allowance;
|
|
426
437
|
}
|
|
@@ -430,12 +441,12 @@ class CToken extends Calldata_1.Calldata {
|
|
|
430
441
|
* @returns tx
|
|
431
442
|
*/
|
|
432
443
|
async approveUnderlying(amount = null, target = null) {
|
|
433
|
-
const erc20 = new ERC20_1.ERC20(this.provider, this.asset.address);
|
|
444
|
+
const erc20 = new ERC20_1.ERC20(this.provider, this.asset.address, undefined, undefined, this.signer);
|
|
434
445
|
const tx = await erc20.approve(target ? target : this.address, amount);
|
|
435
446
|
return tx;
|
|
436
447
|
}
|
|
437
448
|
async approve(amount = null, spender) {
|
|
438
|
-
const erc20 = new ERC20_1.ERC20(this.provider, this.address);
|
|
449
|
+
const erc20 = new ERC20_1.ERC20(this.provider, this.address, undefined, undefined, this.signer);
|
|
439
450
|
const tx = await erc20.approve(spender, amount);
|
|
440
451
|
return tx;
|
|
441
452
|
}
|
|
@@ -506,10 +517,10 @@ class CToken extends Calldata_1.Calldata {
|
|
|
506
517
|
}
|
|
507
518
|
async transfer(receiver, amount) {
|
|
508
519
|
const shares = this.convertTokenInputToShares(amount);
|
|
509
|
-
return this.
|
|
520
|
+
return this.getWriteContract().transfer(receiver, shares);
|
|
510
521
|
}
|
|
511
522
|
async redeemCollateral(amount, receiver = null, owner = null) {
|
|
512
|
-
const signer =
|
|
523
|
+
const signer = this.requireSigner();
|
|
513
524
|
receiver ??= signer.address;
|
|
514
525
|
owner ??= signer.address;
|
|
515
526
|
const shares = this.convertTokenInputToShares(amount);
|
|
@@ -517,7 +528,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
517
528
|
return this.oracleRoute(calldata);
|
|
518
529
|
}
|
|
519
530
|
async postCollateral(amount) {
|
|
520
|
-
const signer =
|
|
531
|
+
const signer = this.requireSigner();
|
|
521
532
|
const shares = this.convertTokenInputToShares(amount);
|
|
522
533
|
const balance = await this.balanceOf(signer.address);
|
|
523
534
|
const collateral = await this.fetchUserCollateral();
|
|
@@ -530,14 +541,14 @@ class CToken extends Calldata_1.Calldata {
|
|
|
530
541
|
return tx;
|
|
531
542
|
}
|
|
532
543
|
async getZapBalance(zap) {
|
|
533
|
-
const signer =
|
|
544
|
+
const signer = this.requireSigner();
|
|
534
545
|
let asset;
|
|
535
546
|
if (typeof zap === 'object') {
|
|
536
547
|
if (zap.type === 'native-vault' || zap.type === 'native-simple' || zap.inputToken.toLowerCase() === helpers_1.NATIVE_ADDRESS.toLowerCase()) {
|
|
537
|
-
asset = new NativeToken_1.NativeToken(
|
|
548
|
+
asset = new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account);
|
|
538
549
|
}
|
|
539
550
|
else {
|
|
540
|
-
asset = new ERC20_1.ERC20(this.provider, zap.inputToken);
|
|
551
|
+
asset = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
|
|
541
552
|
}
|
|
542
553
|
}
|
|
543
554
|
else {
|
|
@@ -549,10 +560,10 @@ class CToken extends Calldata_1.Calldata {
|
|
|
549
560
|
asset = await this.getVaultAsset(true);
|
|
550
561
|
break;
|
|
551
562
|
case 'native-vault':
|
|
552
|
-
asset = new NativeToken_1.NativeToken(
|
|
563
|
+
asset = new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account);
|
|
553
564
|
break;
|
|
554
565
|
case 'native-simple':
|
|
555
|
-
asset = new NativeToken_1.NativeToken(
|
|
566
|
+
asset = new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account);
|
|
556
567
|
break;
|
|
557
568
|
default: throw new Error("Unsupported zap type for balance fetch");
|
|
558
569
|
}
|
|
@@ -570,7 +581,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
570
581
|
decimals = 18n;
|
|
571
582
|
}
|
|
572
583
|
else {
|
|
573
|
-
const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken);
|
|
584
|
+
const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
|
|
574
585
|
decimals = inputErc20.decimals ?? await inputErc20.contract.decimals();
|
|
575
586
|
}
|
|
576
587
|
}
|
|
@@ -634,8 +645,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
634
645
|
return bufferBps > 0n ? shares * (10000n - bufferBps) / 10000n : shares;
|
|
635
646
|
}
|
|
636
647
|
async maxRedemption(in_shares = false, bufferTime = 0n, breakdown = false) {
|
|
637
|
-
const
|
|
638
|
-
const data = await this.market.reader.maxRedemptionOf(signer.address, this, bufferTime);
|
|
648
|
+
const data = await this.market.reader.maxRedemptionOf(this.getAccountOrThrow(), this, bufferTime);
|
|
639
649
|
if (data.errorCodeHit) {
|
|
640
650
|
throw new Error(`Error fetching max redemption. Possible stale price or other issues...`);
|
|
641
651
|
}
|
|
@@ -661,14 +671,14 @@ class CToken extends Calldata_1.Calldata {
|
|
|
661
671
|
let tokens_exclude = [this.asset.address.toLocaleLowerCase()];
|
|
662
672
|
if (this.zapTypes.includes('native-vault')) {
|
|
663
673
|
tokens.push({
|
|
664
|
-
interface: new NativeToken_1.NativeToken(
|
|
674
|
+
interface: new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account),
|
|
665
675
|
type: 'native-vault'
|
|
666
676
|
});
|
|
667
677
|
tokens_exclude.push(helpers_1.EMPTY_ADDRESS, helpers_1.NATIVE_ADDRESS);
|
|
668
678
|
}
|
|
669
679
|
if (this.zapTypes.includes('native-simple')) {
|
|
670
680
|
tokens.push({
|
|
671
|
-
interface: new NativeToken_1.NativeToken(
|
|
681
|
+
interface: new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account),
|
|
672
682
|
type: 'native-simple'
|
|
673
683
|
});
|
|
674
684
|
if (!this.zapTypes.includes('native-vault')) {
|
|
@@ -684,13 +694,13 @@ class CToken extends Calldata_1.Calldata {
|
|
|
684
694
|
tokens_exclude.push(vault_asset.address.toLocaleLowerCase());
|
|
685
695
|
}
|
|
686
696
|
if (this.zapTypes.includes('simple')) {
|
|
687
|
-
let dexAggSearch = await
|
|
697
|
+
let dexAggSearch = await this.currentChainConfig.dexAgg.getAvailableTokens(this.provider, search, this.account);
|
|
688
698
|
tokens = tokens.concat(dexAggSearch.filter(token => !tokens_exclude.includes(token.interface.address.toLocaleLowerCase())));
|
|
689
699
|
// Add native MON as a zap option for any token with a simple zapper
|
|
690
700
|
// (not just wrapped native). The simple zapper handles wrapping + swapping.
|
|
691
701
|
if (!tokens_exclude.includes(helpers_1.NATIVE_ADDRESS.toLowerCase()) && !this.isWrappedNative) {
|
|
692
702
|
tokens.push({
|
|
693
|
-
interface: new NativeToken_1.NativeToken(
|
|
703
|
+
interface: new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account),
|
|
694
704
|
type: 'simple'
|
|
695
705
|
});
|
|
696
706
|
tokens_exclude.push(helpers_1.NATIVE_ADDRESS.toLowerCase());
|
|
@@ -705,9 +715,8 @@ class CToken extends Calldata_1.Calldata {
|
|
|
705
715
|
return tokens;
|
|
706
716
|
}
|
|
707
717
|
async hypotheticalRedemptionOf(amount) {
|
|
708
|
-
const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
|
|
709
718
|
const shares = this.convertTokenInputToShares(amount);
|
|
710
|
-
return this.market.reader.hypotheticalRedemptionOf(
|
|
719
|
+
return this.market.reader.hypotheticalRedemptionOf(this.getAccountOrThrow(), this, shares);
|
|
711
720
|
}
|
|
712
721
|
/**
|
|
713
722
|
* Single-RPC snapshot of fresh position state for leverage operations.
|
|
@@ -720,8 +729,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
720
729
|
* for full deleverage swap sizing).
|
|
721
730
|
*/
|
|
722
731
|
async _getLeverageSnapshot(borrow) {
|
|
723
|
-
const
|
|
724
|
-
const snapshot = await this.market.reader.getLeverageSnapshot(signer.address, this.address, borrow.address, 120n);
|
|
732
|
+
const snapshot = await this.market.reader.getLeverageSnapshot(this.getAccountOrThrow(), this.address, borrow.address, 120n);
|
|
725
733
|
if (snapshot.oracleError) {
|
|
726
734
|
throw new Error(`Oracle error fetching leverage snapshot for ${this.symbol}/${borrow.symbol}`);
|
|
727
735
|
}
|
|
@@ -764,13 +772,9 @@ class CToken extends Calldata_1.Calldata {
|
|
|
764
772
|
const borrowPrice = borrow.getPrice(true);
|
|
765
773
|
const rawDebtInUsd = notional.mul(newLeverage).sub(notional);
|
|
766
774
|
const borrowAmount = rawDebtInUsd.sub(currentDebt).div(borrowPrice);
|
|
767
|
-
|
|
768
|
-
// Fee preview: queried from the configured fee policy. Returned as
|
|
769
|
-
// ancillary fields so callers can display "you'll be charged $X in
|
|
770
|
-
// fees" without requiring the SDK's primary preview math (which
|
|
771
|
-
// preserves the equity-conservation invariant) to change.
|
|
775
|
+
// Fee preview: queried from the configured fee policy.
|
|
772
776
|
const borrowAssets = FormatConverter_1.default.decimalToBigInt(borrowAmount, borrow.asset.decimals);
|
|
773
|
-
const feeBps =
|
|
777
|
+
const feeBps = this.setup.feePolicy.getFeeBps({
|
|
774
778
|
operation: 'leverage-up',
|
|
775
779
|
inputToken: borrow.asset.address,
|
|
776
780
|
outputToken: this.asset.address,
|
|
@@ -780,6 +784,9 @@ class CToken extends Calldata_1.Calldata {
|
|
|
780
784
|
});
|
|
781
785
|
const feeAssets = borrowAmount.mul((0, decimal_js_1.default)(Number(feeBps))).div((0, decimal_js_1.default)(10000));
|
|
782
786
|
const feeUsd = feeAssets.mul(borrowPrice);
|
|
787
|
+
// Subtract fee from displayed collateral — the fee reduces swap
|
|
788
|
+
// output, so the user receives less collateral than rawDebtInUsd.
|
|
789
|
+
const newCollateralInUsd = notional.add(rawDebtInUsd).sub(feeUsd);
|
|
783
790
|
return {
|
|
784
791
|
borrowAmount,
|
|
785
792
|
newDebt: rawDebtInUsd,
|
|
@@ -814,7 +821,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
814
821
|
// (exact for partial; for full deleverage the actual swap is sized
|
|
815
822
|
// by leverageDown using the snapshot, but the preview is close enough
|
|
816
823
|
// for display purposes).
|
|
817
|
-
const feeBps = borrow ?
|
|
824
|
+
const feeBps = borrow ? this.setup.feePolicy.getFeeBps({
|
|
818
825
|
operation: 'leverage-down',
|
|
819
826
|
inputToken: this.asset.address,
|
|
820
827
|
outputToken: borrow.asset.address,
|
|
@@ -841,7 +848,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
841
848
|
}
|
|
842
849
|
async leverageUp(borrow, newLeverage, type, slippage_ = (0, decimal_js_1.default)(0.05), simulate = false) {
|
|
843
850
|
try {
|
|
844
|
-
|
|
851
|
+
this.requireSigner();
|
|
845
852
|
const slippage = this._leverageUpSlippage(FormatConverter_1.default.percentageToBps(slippage_), newLeverage);
|
|
846
853
|
const manager = this.getPositionManager(type);
|
|
847
854
|
let calldata;
|
|
@@ -850,7 +857,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
850
857
|
switch (type) {
|
|
851
858
|
case 'simple': {
|
|
852
859
|
const borrowAssets = FormatConverter_1.default.decimalToBigInt(borrowAmount, borrow.asset.decimals);
|
|
853
|
-
const feeBps =
|
|
860
|
+
const feeBps = this.setup.feePolicy.getFeeBps({
|
|
854
861
|
operation: 'leverage-up',
|
|
855
862
|
inputToken: borrow.asset.address,
|
|
856
863
|
outputToken: this.asset.address,
|
|
@@ -858,8 +865,27 @@ class CToken extends Calldata_1.Calldata {
|
|
|
858
865
|
currentLeverage: this.getLeverage() ?? (0, decimal_js_1.default)(1),
|
|
859
866
|
targetLeverage: newLeverage,
|
|
860
867
|
});
|
|
861
|
-
const feeReceiver = feeBps > 0n ?
|
|
862
|
-
const { action, quote } = await
|
|
868
|
+
const feeReceiver = feeBps > 0n ? this.setup.feePolicy.feeReceiver : undefined;
|
|
869
|
+
const { action, quote } = await this.currentChainConfig.dexAgg.quoteAction(manager.address, borrow.asset.address, this.asset.address, borrowAssets, slippage, feeBps, feeReceiver);
|
|
870
|
+
// _swapSafe measures value loss as (valueIn - valueOut) / valueIn
|
|
871
|
+
// where valueIn is the FULL input (pre-fee). KyberSwap deducts
|
|
872
|
+
// the fee before swapping, so _swapSafe sees feeBps as "slippage"
|
|
873
|
+
// even though it's a known, deterministic cost. Expand
|
|
874
|
+
// action.slippage by feeBps so the fee doesn't consume the user's
|
|
875
|
+
// MEV protection budget. The KyberSwap quote already used the
|
|
876
|
+
// user's raw slippage for minReturnAmount (DEX-level protection).
|
|
877
|
+
if (feeBps > 0n) {
|
|
878
|
+
action.slippage = FormatConverter_1.default.bpsToBpsWad(slippage + feeBps);
|
|
879
|
+
}
|
|
880
|
+
// The fee also reduces swap output, which checkSlippage sees
|
|
881
|
+
// as equity loss amplified by (L-1) — same pattern as
|
|
882
|
+
// deleverage. Expand the contract-level tolerance to absorb it.
|
|
883
|
+
const contractSlippage = feeBps > 0n
|
|
884
|
+
? slippage + BigInt(newLeverage.sub(1)
|
|
885
|
+
.mul(Number(feeBps))
|
|
886
|
+
.ceil()
|
|
887
|
+
.toFixed(0))
|
|
888
|
+
: slippage;
|
|
863
889
|
calldata = manager.getLeverageCalldata({
|
|
864
890
|
borrowableCToken: borrow.address,
|
|
865
891
|
borrowAssets: FormatConverter_1.default.decimalToBigInt(borrowAmount, borrow.asset.decimals),
|
|
@@ -867,7 +893,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
867
893
|
expectedShares: this.virtualConvertToShares(BigInt(quote.min_out), LEVERAGE.SHARES_BUFFER_BPS),
|
|
868
894
|
swapAction: action,
|
|
869
895
|
auxData: "0x",
|
|
870
|
-
}, FormatConverter_1.default.bpsToBpsWad(
|
|
896
|
+
}, FormatConverter_1.default.bpsToBpsWad(contractSlippage));
|
|
871
897
|
break;
|
|
872
898
|
}
|
|
873
899
|
case 'native-vault':
|
|
@@ -905,8 +931,8 @@ class CToken extends Calldata_1.Calldata {
|
|
|
905
931
|
return { success: false, error: "New leverage must be less than current leverage" };
|
|
906
932
|
throw new Error("New leverage must be less than current leverage");
|
|
907
933
|
}
|
|
908
|
-
|
|
909
|
-
const config =
|
|
934
|
+
this.requireSigner();
|
|
935
|
+
const config = this.currentChainConfig;
|
|
910
936
|
const slippage = (0, helpers_1.toBps)(slippage_);
|
|
911
937
|
const manager = this.getPositionManager(type);
|
|
912
938
|
let calldata;
|
|
@@ -931,7 +957,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
931
957
|
// exact for current callers. Future notional-tiered policies
|
|
932
958
|
// should be aware that for full deleverage the inputAmount
|
|
933
959
|
// passed here is an underestimate.
|
|
934
|
-
const feeBps =
|
|
960
|
+
const feeBps = this.setup.feePolicy.getFeeBps({
|
|
935
961
|
operation: 'leverage-down',
|
|
936
962
|
inputToken: this.asset.address,
|
|
937
963
|
outputToken: borrowToken.asset.address,
|
|
@@ -939,7 +965,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
939
965
|
currentLeverage: currentLeverage,
|
|
940
966
|
targetLeverage: newLeverage,
|
|
941
967
|
});
|
|
942
|
-
const feeReceiver = feeBps > 0n ?
|
|
968
|
+
const feeReceiver = feeBps > 0n ? this.setup.feePolicy.feeReceiver : undefined;
|
|
943
969
|
if (isFullDeleverage) {
|
|
944
970
|
// Use exact projected debt from snapshot to size the swap.
|
|
945
971
|
// debtTokenBalance is in debt-token native decimals, projected
|
|
@@ -960,25 +986,40 @@ class CToken extends Calldata_1.Calldata {
|
|
|
960
986
|
swapCollateral = maxCollateral;
|
|
961
987
|
}
|
|
962
988
|
}
|
|
989
|
+
else if (feeBps > 0n) {
|
|
990
|
+
// Partial deleverage: inflate swap size to compensate
|
|
991
|
+
// for fee deduction on input. KyberSwap deducts feeBps
|
|
992
|
+
// from input before swapping, so without compensation
|
|
993
|
+
// the swap underdelivers and actual leverage is slightly
|
|
994
|
+
// higher than target.
|
|
995
|
+
swapCollateral = swapCollateral * 10000n / (10000n - feeBps);
|
|
996
|
+
}
|
|
963
997
|
const { action, quote } = await config.dexAgg.quoteAction(manager.address, this.asset.address, borrowToken.asset.address, swapCollateral, slippage, feeBps, feeReceiver);
|
|
998
|
+
// _swapSafe: expand action.slippage by feeBps so the
|
|
999
|
+
// deterministic fee cost doesn't eat the user's MEV budget.
|
|
1000
|
+
// Same rationale as leverageUp — see comment there.
|
|
1001
|
+
if (feeBps > 0n) {
|
|
1002
|
+
action.slippage = FormatConverter_1.default.bpsToBpsWad(slippage + feeBps);
|
|
1003
|
+
}
|
|
964
1004
|
const minRepay = isFullDeleverage ? 1n : quote.min_out;
|
|
965
|
-
//
|
|
966
|
-
//
|
|
967
|
-
//
|
|
968
|
-
//
|
|
969
|
-
//
|
|
970
|
-
// the contract slippage tolerance by exactly that forced amount,
|
|
971
|
-
// leaving the user's `slippage` budget available for variable
|
|
1005
|
+
// checkSlippage measures equity-fraction loss. Both the
|
|
1006
|
+
// intentional swap overshoot (full deleverage only) and the
|
|
1007
|
+
// DEX fee (always) are real equity losses amplified by
|
|
1008
|
+
// leverage. Expand contractSlippage to absorb them so the
|
|
1009
|
+
// user's `slippage` budget is preserved for variable
|
|
972
1010
|
// DEX impact + oracle drift.
|
|
973
1011
|
//
|
|
974
|
-
//
|
|
975
|
-
//
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
const
|
|
980
|
-
?
|
|
981
|
-
|
|
1012
|
+
// Full: (L-1) × (overhead + fee) — overshoot + fee
|
|
1013
|
+
// Partial: (ΔL) × fee — fee only, no overshoot
|
|
1014
|
+
const leverageDelta = isFullDeleverage
|
|
1015
|
+
? currentLeverage.sub(1)
|
|
1016
|
+
: currentLeverage.sub(newLeverage);
|
|
1017
|
+
const forcedBps = isFullDeleverage
|
|
1018
|
+
? LEVERAGE.DELEVERAGE_OVERHEAD_BPS + feeBps
|
|
1019
|
+
: feeBps;
|
|
1020
|
+
const contractSlippage = forcedBps > 0n
|
|
1021
|
+
? slippage + BigInt(leverageDelta
|
|
1022
|
+
.mul(Number(forcedBps))
|
|
982
1023
|
.ceil()
|
|
983
1024
|
.toFixed(0))
|
|
984
1025
|
: slippage;
|
|
@@ -1025,7 +1066,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1025
1066
|
switch (type) {
|
|
1026
1067
|
case 'simple': {
|
|
1027
1068
|
const borrowAssets = FormatConverter_1.default.decimalToBigInt(borrowAmount, borrow.asset.decimals);
|
|
1028
|
-
const feeBps =
|
|
1069
|
+
const feeBps = this.setup.feePolicy.getFeeBps({
|
|
1029
1070
|
operation: 'deposit-and-leverage',
|
|
1030
1071
|
inputToken: borrow.asset.address,
|
|
1031
1072
|
outputToken: this.asset.address,
|
|
@@ -1033,8 +1074,21 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1033
1074
|
currentLeverage: this.getLeverage() ?? (0, decimal_js_1.default)(1),
|
|
1034
1075
|
targetLeverage: multiplier,
|
|
1035
1076
|
});
|
|
1036
|
-
const feeReceiver = feeBps > 0n ?
|
|
1037
|
-
const { action, quote } = await
|
|
1077
|
+
const feeReceiver = feeBps > 0n ? this.setup.feePolicy.feeReceiver : undefined;
|
|
1078
|
+
const { action, quote } = await this.currentChainConfig.dexAgg.quoteAction(manager.address, borrow.asset.address, this.asset.address, borrowAssets, slippage, feeBps, feeReceiver);
|
|
1079
|
+
// _swapSafe: expand action.slippage by feeBps so the
|
|
1080
|
+
// deterministic fee cost doesn't eat the user's MEV budget.
|
|
1081
|
+
// Same rationale as leverageUp — see comment there.
|
|
1082
|
+
if (feeBps > 0n) {
|
|
1083
|
+
action.slippage = FormatConverter_1.default.bpsToBpsWad(slippage + feeBps);
|
|
1084
|
+
}
|
|
1085
|
+
// Fee amplification: same pattern as leverageUp.
|
|
1086
|
+
const contractSlippage = feeBps > 0n
|
|
1087
|
+
? slippage + BigInt(multiplier.sub(1)
|
|
1088
|
+
.mul(Number(feeBps))
|
|
1089
|
+
.ceil()
|
|
1090
|
+
.toFixed(0))
|
|
1091
|
+
: slippage;
|
|
1038
1092
|
calldata = manager.getDepositAndLeverageCalldata(FormatConverter_1.default.decimalToBigInt(depositAmount, this.asset.decimals), {
|
|
1039
1093
|
borrowableCToken: borrow.address,
|
|
1040
1094
|
borrowAssets: borrowAssets,
|
|
@@ -1042,7 +1096,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1042
1096
|
expectedShares: this.virtualConvertToShares(BigInt(quote.min_out), LEVERAGE.SHARES_BUFFER_BPS),
|
|
1043
1097
|
swapAction: action,
|
|
1044
1098
|
auxData: "0x",
|
|
1045
|
-
}, FormatConverter_1.default.bpsToBpsWad(
|
|
1099
|
+
}, FormatConverter_1.default.bpsToBpsWad(contractSlippage));
|
|
1046
1100
|
break;
|
|
1047
1101
|
}
|
|
1048
1102
|
case 'native-vault':
|
|
@@ -1076,7 +1130,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1076
1130
|
async simulateDeposit(amount, zap = 'none', receiver = null) {
|
|
1077
1131
|
try {
|
|
1078
1132
|
amount = await this.ensureUnderlyingAmount(amount, zap);
|
|
1079
|
-
const signer =
|
|
1133
|
+
const signer = this.requireSigner();
|
|
1080
1134
|
receiver ??= signer.address;
|
|
1081
1135
|
const isZapping = typeof zap === 'object' && zap.type !== 'none';
|
|
1082
1136
|
const depositAssets = FormatConverter_1.default.decimalToBigInt(amount, this.asset.decimals);
|
|
@@ -1084,7 +1138,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1084
1138
|
if (isZapping && zap.inputToken) {
|
|
1085
1139
|
const isNative = zap.inputToken.toLowerCase() === helpers_1.NATIVE_ADDRESS.toLowerCase();
|
|
1086
1140
|
const zapDecimals = isNative ? 18n : (() => {
|
|
1087
|
-
const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken);
|
|
1141
|
+
const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
|
|
1088
1142
|
return inputErc20.decimals ?? inputErc20.contract.decimals();
|
|
1089
1143
|
})();
|
|
1090
1144
|
zapAssets = FormatConverter_1.default.decimalToBigInt(amount, await zapDecimals);
|
|
@@ -1100,7 +1154,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1100
1154
|
async simulateDepositAsCollateral(amount, zap = 'none', receiver = null) {
|
|
1101
1155
|
try {
|
|
1102
1156
|
amount = await this.ensureUnderlyingAmount(amount, zap);
|
|
1103
|
-
const signer =
|
|
1157
|
+
const signer = this.requireSigner();
|
|
1104
1158
|
receiver ??= signer.address;
|
|
1105
1159
|
const isZapping = typeof zap === 'object' && zap.type !== 'none';
|
|
1106
1160
|
const depositAssets = FormatConverter_1.default.decimalToBigInt(amount, this.asset.decimals);
|
|
@@ -1108,7 +1162,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1108
1162
|
if (isZapping && zap.inputToken) {
|
|
1109
1163
|
const isNative = zap.inputToken.toLowerCase() === helpers_1.NATIVE_ADDRESS.toLowerCase();
|
|
1110
1164
|
const zapDecimals = isNative ? 18n : (() => {
|
|
1111
|
-
const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken);
|
|
1165
|
+
const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
|
|
1112
1166
|
return inputErc20.decimals ?? inputErc20.contract.decimals();
|
|
1113
1167
|
})();
|
|
1114
1168
|
zapAssets = FormatConverter_1.default.decimalToBigInt(amount, await zapDecimals);
|
|
@@ -1169,7 +1223,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1169
1223
|
}
|
|
1170
1224
|
async deposit(amount, zap = 'none', receiver = null) {
|
|
1171
1225
|
amount = await this.ensureUnderlyingAmount(amount, zap);
|
|
1172
|
-
const signer =
|
|
1226
|
+
const signer = this.requireSigner();
|
|
1173
1227
|
receiver ??= signer.address;
|
|
1174
1228
|
// When zapping, the swap amount uses input token decimals, but the
|
|
1175
1229
|
// default deposit calldata uses the deposit token decimals.
|
|
@@ -1181,7 +1235,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1181
1235
|
zapAssets = FormatConverter_1.default.decimalToBigInt(amount, 18n);
|
|
1182
1236
|
}
|
|
1183
1237
|
else {
|
|
1184
|
-
const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken);
|
|
1238
|
+
const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
|
|
1185
1239
|
const zapDecimals = inputErc20.decimals ?? await inputErc20.contract.decimals();
|
|
1186
1240
|
zapAssets = FormatConverter_1.default.decimalToBigInt(amount, zapDecimals);
|
|
1187
1241
|
}
|
|
@@ -1205,7 +1259,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1205
1259
|
}
|
|
1206
1260
|
async depositAsCollateral(amount, zap = 'none', receiver = null) {
|
|
1207
1261
|
amount = await this.ensureUnderlyingAmount(amount, zap);
|
|
1208
|
-
const signer =
|
|
1262
|
+
const signer = this.requireSigner();
|
|
1209
1263
|
receiver ??= signer.address;
|
|
1210
1264
|
// When zapping, the swap amount uses input token decimals, but collateral
|
|
1211
1265
|
// cap checks and the default deposit calldata use the deposit token decimals.
|
|
@@ -1217,7 +1271,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1217
1271
|
zapAssets = FormatConverter_1.default.decimalToBigInt(amount, 18n);
|
|
1218
1272
|
}
|
|
1219
1273
|
else {
|
|
1220
|
-
const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken);
|
|
1274
|
+
const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
|
|
1221
1275
|
const zapDecimals = inputErc20.decimals ?? await inputErc20.contract.decimals();
|
|
1222
1276
|
zapAssets = FormatConverter_1.default.decimalToBigInt(amount, zapDecimals);
|
|
1223
1277
|
}
|
|
@@ -1240,7 +1294,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1240
1294
|
return this.oracleRoute(calldata, calldata_overrides);
|
|
1241
1295
|
}
|
|
1242
1296
|
async redeem(amount) {
|
|
1243
|
-
const signer =
|
|
1297
|
+
const signer = this.requireSigner();
|
|
1244
1298
|
const receiver = signer.address;
|
|
1245
1299
|
const owner = signer.address;
|
|
1246
1300
|
const buffer = this.market.userDebt.greaterThan(0) ? 100n : 0n;
|
|
@@ -1255,19 +1309,17 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1255
1309
|
return this.oracleRoute(calldata);
|
|
1256
1310
|
}
|
|
1257
1311
|
async redeemShares(amount) {
|
|
1258
|
-
const signer =
|
|
1312
|
+
const signer = this.requireSigner();
|
|
1259
1313
|
const receiver = signer.address;
|
|
1260
1314
|
const owner = signer.address;
|
|
1261
1315
|
const calldata = this.getCallData("redeem", [amount, receiver, owner]);
|
|
1262
1316
|
return this.oracleRoute(calldata);
|
|
1263
1317
|
}
|
|
1264
1318
|
async collateralPosted(account = null) {
|
|
1265
|
-
|
|
1266
|
-
account = (0, helpers_1.validateProviderAsSigner)(this.provider).address;
|
|
1267
|
-
return this.contract.collateralPosted(account);
|
|
1319
|
+
return this.contract.collateralPosted(this.getAccountOrThrow(account));
|
|
1268
1320
|
}
|
|
1269
1321
|
async multicall(calls) {
|
|
1270
|
-
return this.
|
|
1322
|
+
return this.getWriteContract().multicall(calls);
|
|
1271
1323
|
}
|
|
1272
1324
|
async getSnapshot(account) {
|
|
1273
1325
|
const snapshot = await this.contract.getSnapshot(account);
|
|
@@ -1326,10 +1378,10 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1326
1378
|
}
|
|
1327
1379
|
}
|
|
1328
1380
|
async _checkZapperApproval(zapper) {
|
|
1329
|
-
if (!
|
|
1381
|
+
if (!this.setup.approval_protection) {
|
|
1330
1382
|
return;
|
|
1331
1383
|
}
|
|
1332
|
-
if (
|
|
1384
|
+
if (this.setup.approval_protection && zapper) {
|
|
1333
1385
|
const plugin_allowed = await this.isPluginApproved(zapper.type, 'zapper');
|
|
1334
1386
|
if (!plugin_allowed) {
|
|
1335
1387
|
throw new Error(`Please approve the ${zapper.type} Zapper to be able to move ${this.symbol} on your behalf.`);
|
|
@@ -1337,8 +1389,8 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1337
1389
|
}
|
|
1338
1390
|
}
|
|
1339
1391
|
async _checkErc20Approval(erc20_address, amount, spender) {
|
|
1340
|
-
const signer =
|
|
1341
|
-
const erc20 = new ERC20_1.ERC20(
|
|
1392
|
+
const signer = this.requireSigner();
|
|
1393
|
+
const erc20 = new ERC20_1.ERC20(this.provider, erc20_address, undefined, undefined, signer);
|
|
1342
1394
|
const allowance = await erc20.allowance(signer.address, spender);
|
|
1343
1395
|
if (allowance < amount) {
|
|
1344
1396
|
const symbol = await erc20.fetchSymbol();
|
|
@@ -1346,18 +1398,18 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1346
1398
|
}
|
|
1347
1399
|
}
|
|
1348
1400
|
async _checkAssetApproval(assets) {
|
|
1349
|
-
if (!
|
|
1401
|
+
if (!this.setup.approval_protection) {
|
|
1350
1402
|
return;
|
|
1351
1403
|
}
|
|
1352
1404
|
const asset = this.getAsset(true);
|
|
1353
|
-
const owner =
|
|
1405
|
+
const owner = this.getAccountOrThrow();
|
|
1354
1406
|
const allowance = await asset.allowance(owner, this.address);
|
|
1355
1407
|
if (allowance < assets) {
|
|
1356
1408
|
throw new Error(`Please approve the ${asset.symbol} token for ${this.symbol}`);
|
|
1357
1409
|
}
|
|
1358
1410
|
}
|
|
1359
1411
|
async _checkDepositApprovals(zapper, assets) {
|
|
1360
|
-
if (!
|
|
1412
|
+
if (!this.setup.approval_protection) {
|
|
1361
1413
|
return;
|
|
1362
1414
|
}
|
|
1363
1415
|
if (zapper) {
|
|
@@ -1366,7 +1418,7 @@ class CToken extends Calldata_1.Calldata {
|
|
|
1366
1418
|
await this._checkAssetApproval(assets);
|
|
1367
1419
|
}
|
|
1368
1420
|
async oracleRoute(calldata, override = {}) {
|
|
1369
|
-
const signer =
|
|
1421
|
+
const signer = this.requireSigner();
|
|
1370
1422
|
const price_updates = await this.getPriceUpdates();
|
|
1371
1423
|
if (price_updates.length > 0) {
|
|
1372
1424
|
const token_action = this.buildMultiCallAction(calldata);
|