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.
Files changed (111) hide show
  1. package/README.md +595 -59
  2. package/dist/chains/arbitrum.d.ts.map +1 -1
  3. package/dist/chains/arbitrum.js +4 -2
  4. package/dist/chains/arbitrum.js.map +1 -1
  5. package/dist/chains/index.d.ts +4 -0
  6. package/dist/chains/index.d.ts.map +1 -1
  7. package/dist/chains/index.js +15 -0
  8. package/dist/chains/index.js.map +1 -1
  9. package/dist/chains/monad.d.ts.map +1 -1
  10. package/dist/chains/monad.js +4 -2
  11. package/dist/chains/monad.js.map +1 -1
  12. package/dist/chains/rpc.d.ts +57 -0
  13. package/dist/chains/rpc.d.ts.map +1 -0
  14. package/dist/chains/rpc.js +47 -0
  15. package/dist/chains/rpc.js.map +1 -0
  16. package/dist/classes/Api.d.ts +4 -3
  17. package/dist/classes/Api.d.ts.map +1 -1
  18. package/dist/classes/Api.js +7 -7
  19. package/dist/classes/Api.js.map +1 -1
  20. package/dist/classes/BorrowableCToken.d.ts +3 -2
  21. package/dist/classes/BorrowableCToken.d.ts.map +1 -1
  22. package/dist/classes/BorrowableCToken.js +6 -5
  23. package/dist/classes/BorrowableCToken.js.map +1 -1
  24. package/dist/classes/CToken.d.ts +11 -3
  25. package/dist/classes/CToken.d.ts.map +1 -1
  26. package/dist/classes/CToken.js +168 -116
  27. package/dist/classes/CToken.js.map +1 -1
  28. package/dist/classes/Calldata.d.ts +2 -2
  29. package/dist/classes/Calldata.d.ts.map +1 -1
  30. package/dist/classes/Calldata.js +2 -2
  31. package/dist/classes/Calldata.js.map +1 -1
  32. package/dist/classes/DexAggregators/IDexAgg.d.ts +2 -2
  33. package/dist/classes/DexAggregators/IDexAgg.d.ts.map +1 -1
  34. package/dist/classes/DexAggregators/Kuru.d.ts +2 -2
  35. package/dist/classes/DexAggregators/Kuru.d.ts.map +1 -1
  36. package/dist/classes/DexAggregators/Kuru.js +3 -4
  37. package/dist/classes/DexAggregators/Kuru.js.map +1 -1
  38. package/dist/classes/DexAggregators/KyberSwap.d.ts +2 -2
  39. package/dist/classes/DexAggregators/KyberSwap.d.ts.map +1 -1
  40. package/dist/classes/DexAggregators/KyberSwap.js +88 -9
  41. package/dist/classes/DexAggregators/KyberSwap.js.map +1 -1
  42. package/dist/classes/DexAggregators/MultiDexAgg.d.ts +2 -2
  43. package/dist/classes/DexAggregators/MultiDexAgg.d.ts.map +1 -1
  44. package/dist/classes/DexAggregators/MultiDexAgg.js +3 -3
  45. package/dist/classes/DexAggregators/MultiDexAgg.js.map +1 -1
  46. package/dist/classes/ERC20.d.ts +5 -3
  47. package/dist/classes/ERC20.d.ts.map +1 -1
  48. package/dist/classes/ERC20.js +20 -14
  49. package/dist/classes/ERC20.js.map +1 -1
  50. package/dist/classes/ERC4626.d.ts.map +1 -1
  51. package/dist/classes/ERC4626.js +3 -1
  52. package/dist/classes/ERC4626.js.map +1 -1
  53. package/dist/classes/Market.d.ts +13 -4
  54. package/dist/classes/Market.d.ts.map +1 -1
  55. package/dist/classes/Market.js +86 -28
  56. package/dist/classes/Market.js.map +1 -1
  57. package/dist/classes/NativeToken.d.ts +6 -3
  58. package/dist/classes/NativeToken.d.ts.map +1 -1
  59. package/dist/classes/NativeToken.js +11 -16
  60. package/dist/classes/NativeToken.js.map +1 -1
  61. package/dist/classes/OptimizerReader.d.ts +3 -3
  62. package/dist/classes/OptimizerReader.d.ts.map +1 -1
  63. package/dist/classes/OptimizerReader.js +1 -1
  64. package/dist/classes/OptimizerReader.js.map +1 -1
  65. package/dist/classes/OracleManager.d.ts +3 -3
  66. package/dist/classes/OracleManager.d.ts.map +1 -1
  67. package/dist/classes/OracleManager.js +1 -1
  68. package/dist/classes/OracleManager.js.map +1 -1
  69. package/dist/classes/PositionManager.d.ts +2 -2
  70. package/dist/classes/PositionManager.d.ts.map +1 -1
  71. package/dist/classes/PositionManager.js +4 -4
  72. package/dist/classes/PositionManager.js.map +1 -1
  73. package/dist/classes/ProtocolReader.d.ts +18 -4
  74. package/dist/classes/ProtocolReader.d.ts.map +1 -1
  75. package/dist/classes/ProtocolReader.js +177 -55
  76. package/dist/classes/ProtocolReader.js.map +1 -1
  77. package/dist/classes/Redstone.d.ts.map +1 -1
  78. package/dist/classes/Redstone.js +1 -2
  79. package/dist/classes/Redstone.js.map +1 -1
  80. package/dist/classes/Zapper.d.ts +4 -2
  81. package/dist/classes/Zapper.d.ts.map +1 -1
  82. package/dist/classes/Zapper.js +16 -14
  83. package/dist/classes/Zapper.js.map +1 -1
  84. package/dist/classes/index.d.ts +1 -1
  85. package/dist/classes/index.d.ts.map +1 -1
  86. package/dist/classes/index.js +6 -1
  87. package/dist/classes/index.js.map +1 -1
  88. package/dist/contracts/monad-mainnet.json +1 -1
  89. package/dist/feePolicy.d.ts +27 -1
  90. package/dist/feePolicy.d.ts.map +1 -1
  91. package/dist/feePolicy.js +10 -2
  92. package/dist/feePolicy.js.map +1 -1
  93. package/dist/helpers.d.ts +3 -1
  94. package/dist/helpers.d.ts.map +1 -1
  95. package/dist/helpers.js +34 -4
  96. package/dist/helpers.js.map +1 -1
  97. package/dist/integrations/snapshot.d.ts.map +1 -1
  98. package/dist/integrations/snapshot.js +4 -18
  99. package/dist/integrations/snapshot.js.map +1 -1
  100. package/dist/retry-provider.d.ts +81 -6
  101. package/dist/retry-provider.d.ts.map +1 -1
  102. package/dist/retry-provider.js +491 -37
  103. package/dist/retry-provider.js.map +1 -1
  104. package/dist/setup.d.ts +14 -3
  105. package/dist/setup.d.ts.map +1 -1
  106. package/dist/setup.js +56 -20
  107. package/dist/setup.js.map +1 -1
  108. package/dist/types.d.ts +2 -1
  109. package/dist/types.d.ts.map +1 -1
  110. package/dist/types.js.map +1 -1
  111. package/package.json +3 -1
@@ -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 (= the user's raw slippage in WAD).
45
+ * Swap.slippage parameter we pass.
48
46
  *
49
- * That swap-level check bounds any sandwich extraction to the user's
50
- * tolerance regardless of how the buffers below are tuned. The buffers
51
- * here only adjust the contract-level sanity check so it doesn't fire
52
- * false-positives from intentional or unavoidable forced losses.
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 contract slippage tolerance.
79
- * Under single-oracle, the only forced loss comes from wei-level share
80
- * rounding plus possible Redstone price drift between the snapshot RPC
81
- * and the tx broadcast block (typically same-block or 1-3 blocks
82
- * later). Both are small constants in absolute terms; the equity-
83
- * fraction amplification at high leverage happens automatically inside
84
- * checkSlippage's denominator and does not require leverage-scaling
85
- * the buffer itself. Conservative starting value reduce after
86
- * empirically observing successful leverage-up across the leverage
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 chain_config = (0, helpers_1.getChainConfig)();
124
+ const chainSettings = this.currentChainConfig;
125
125
  const assetAddr = this.asset.address.toLowerCase();
126
- this.isNativeVault = chain_config.native_vaults.some(vault => vault.contract.toLowerCase() == assetAddr);
127
- this.isVault = chain_config.vaults.some(vault => vault.contract.toLowerCase() == assetAddr);
128
- this.isWrappedNative = chain_config.wrapped_native.toLowerCase() == assetAddr;
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 signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
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 ? new ERC20_1.ERC20(this.provider, this.cache.asset.address, this.cache.asset) : this.cache.asset.address;
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
361
- const asset = new ERC20_1.ERC20(signer, instructions.inputToken);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
374
- const asset = new ERC20_1.ERC20(signer, instructions.inputToken);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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.contract.setDelegateApproval(plugin_address, true);
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 || !setup_1.setup_config.contracts.zappers || !(plugin_name in setup_1.setup_config.contracts.zappers)) {
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 setup_1.setup_config.contracts.zappers[plugin_name];
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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.contract.transfer(receiver, shares);
520
+ return this.getWriteContract().transfer(receiver, shares);
510
521
  }
511
522
  async redeemCollateral(amount, receiver = null, owner = null) {
512
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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(setup_1.setup_config.chain, this.provider);
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(setup_1.setup_config.chain, this.provider);
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(setup_1.setup_config.chain, this.provider);
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 signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
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(setup_1.setup_config.chain, this.provider),
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(setup_1.setup_config.chain, this.provider),
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 chains_1.chain_config[setup_1.setup_config.chain].dexAgg.getAvailableTokens(this.provider, search);
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(setup_1.setup_config.chain, this.provider),
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(signer.address, this, shares);
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 signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
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
- const newCollateralInUsd = notional.add(rawDebtInUsd);
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 = setup_1.setup_config.feePolicy.getFeeBps({
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 ? setup_1.setup_config.feePolicy.getFeeBps({
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
- (0, helpers_1.validateProviderAsSigner)(this.provider);
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 = setup_1.setup_config.feePolicy.getFeeBps({
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 ? setup_1.setup_config.feePolicy.feeReceiver : undefined;
862
- const { action, quote } = await chains_1.chain_config[setup_1.setup_config.chain].dexAgg.quoteAction(manager.address, borrow.asset.address, this.asset.address, borrowAssets, slippage, feeBps, feeReceiver);
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(slippage));
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
- (0, helpers_1.validateProviderAsSigner)(this.provider);
909
- const config = (0, helpers_1.getChainConfig)();
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 = setup_1.setup_config.feePolicy.getFeeBps({
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 ? setup_1.setup_config.feePolicy.feeReceiver : undefined;
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
- // Full deleverage oversizes the swap by (DELEVERAGE_OVERHEAD_BPS +
966
- // feeBps) in absolute terms to prevent dust debt. The contract's
967
- // checkSlippage modifier compares equity-before vs equity-after
968
- // as a fraction of starting equity, so the absolute overshoot
969
- // becomes (L-1) × overhead in equity-fraction terms. We expand
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
- // This does NOT loosen MEV protection that lives at the
975
- // _swapSafe layer (which still receives raw user slippage).
976
- // The contract checkSlippage is sanity-only per its docstring.
977
- // Note: the contract returns excess debt token to the user's
978
- // wallet, so the economic loss from the overshoot is zero.
979
- const contractSlippage = isFullDeleverage
980
- ? slippage + BigInt(currentLeverage.sub(1)
981
- .mul(Number(LEVERAGE.DELEVERAGE_OVERHEAD_BPS + feeBps))
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 = setup_1.setup_config.feePolicy.getFeeBps({
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 ? setup_1.setup_config.feePolicy.feeReceiver : undefined;
1037
- const { action, quote } = await chains_1.chain_config[setup_1.setup_config.chain].dexAgg.quoteAction(manager.address, borrow.asset.address, this.asset.address, borrowAssets, slippage, feeBps, feeReceiver);
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(slippage));
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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
- if (!account)
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.contract.multicall(calls);
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 (!setup_1.setup_config.approval_protection) {
1381
+ if (!this.setup.approval_protection) {
1330
1382
  return;
1331
1383
  }
1332
- if (setup_1.setup_config.approval_protection && zapper) {
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
1341
- const erc20 = new ERC20_1.ERC20(signer, erc20_address);
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 (!setup_1.setup_config.approval_protection) {
1401
+ if (!this.setup.approval_protection) {
1350
1402
  return;
1351
1403
  }
1352
1404
  const asset = this.getAsset(true);
1353
- const owner = (0, helpers_1.validateProviderAsSigner)(this.provider).address;
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 (!setup_1.setup_config.approval_protection) {
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 = (0, helpers_1.validateProviderAsSigner)(this.provider);
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);