curvance 4.0.4 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/README.md +649 -59
  2. package/dist/chains/arb-sepolia.json +44 -0
  3. package/dist/chains/arbitrum.d.ts.map +1 -1
  4. package/dist/chains/arbitrum.js +4 -2
  5. package/dist/chains/arbitrum.js.map +1 -1
  6. package/dist/chains/index.d.ts +4 -0
  7. package/dist/chains/index.d.ts.map +1 -1
  8. package/dist/chains/index.js +15 -0
  9. package/dist/chains/index.js.map +1 -1
  10. package/dist/chains/monad-mainnet.json +26 -1
  11. package/dist/chains/monad.d.ts.map +1 -1
  12. package/dist/chains/monad.js +4 -2
  13. package/dist/chains/monad.js.map +1 -1
  14. package/dist/chains/rpc.d.ts +57 -0
  15. package/dist/chains/rpc.d.ts.map +1 -0
  16. package/dist/chains/rpc.js +67 -0
  17. package/dist/chains/rpc.js.map +1 -0
  18. package/dist/classes/Api.d.ts +4 -3
  19. package/dist/classes/Api.d.ts.map +1 -1
  20. package/dist/classes/Api.js +7 -7
  21. package/dist/classes/Api.js.map +1 -1
  22. package/dist/classes/BorrowableCToken.d.ts +3 -2
  23. package/dist/classes/BorrowableCToken.d.ts.map +1 -1
  24. package/dist/classes/BorrowableCToken.js +6 -5
  25. package/dist/classes/BorrowableCToken.js.map +1 -1
  26. package/dist/classes/CToken.d.ts +11 -3
  27. package/dist/classes/CToken.d.ts.map +1 -1
  28. package/dist/classes/CToken.js +102 -108
  29. package/dist/classes/CToken.js.map +1 -1
  30. package/dist/classes/Calldata.d.ts +2 -2
  31. package/dist/classes/Calldata.d.ts.map +1 -1
  32. package/dist/classes/Calldata.js +2 -2
  33. package/dist/classes/Calldata.js.map +1 -1
  34. package/dist/classes/DexAggregators/IDexAgg.d.ts +2 -2
  35. package/dist/classes/DexAggregators/IDexAgg.d.ts.map +1 -1
  36. package/dist/classes/DexAggregators/Kuru.d.ts +2 -2
  37. package/dist/classes/DexAggregators/Kuru.d.ts.map +1 -1
  38. package/dist/classes/DexAggregators/Kuru.js +3 -4
  39. package/dist/classes/DexAggregators/Kuru.js.map +1 -1
  40. package/dist/classes/DexAggregators/KuruMainnet.d.ts +1 -0
  41. package/dist/classes/DexAggregators/KuruMainnet.d.ts.map +1 -0
  42. package/dist/classes/DexAggregators/KuruMainnet.js +228 -0
  43. package/dist/classes/DexAggregators/KuruMainnet.js.map +1 -0
  44. package/dist/classes/DexAggregators/KyberSwap.d.ts +2 -2
  45. package/dist/classes/DexAggregators/KyberSwap.d.ts.map +1 -1
  46. package/dist/classes/DexAggregators/KyberSwap.js +22 -13
  47. package/dist/classes/DexAggregators/KyberSwap.js.map +1 -1
  48. package/dist/classes/DexAggregators/MultiDexAgg.d.ts +2 -2
  49. package/dist/classes/DexAggregators/MultiDexAgg.d.ts.map +1 -1
  50. package/dist/classes/DexAggregators/MultiDexAgg.js +3 -3
  51. package/dist/classes/DexAggregators/MultiDexAgg.js.map +1 -1
  52. package/dist/classes/ERC20.d.ts +5 -3
  53. package/dist/classes/ERC20.d.ts.map +1 -1
  54. package/dist/classes/ERC20.js +20 -14
  55. package/dist/classes/ERC20.js.map +1 -1
  56. package/dist/classes/ERC4626.d.ts.map +1 -1
  57. package/dist/classes/ERC4626.js +3 -1
  58. package/dist/classes/ERC4626.js.map +1 -1
  59. package/dist/classes/Kuru.d.ts +59 -0
  60. package/dist/classes/Kuru.d.ts.map +1 -0
  61. package/dist/classes/Kuru.js +167 -0
  62. package/dist/classes/Kuru.js.map +1 -0
  63. package/dist/classes/KuruMainnet.d.ts +59 -0
  64. package/dist/classes/KuruMainnet.d.ts.map +1 -0
  65. package/dist/classes/KuruMainnet.js +167 -0
  66. package/dist/classes/KuruMainnet.js.map +1 -0
  67. package/dist/classes/Market.d.ts +13 -4
  68. package/dist/classes/Market.d.ts.map +1 -1
  69. package/dist/classes/Market.js +87 -32
  70. package/dist/classes/Market.js.map +1 -1
  71. package/dist/classes/NativeToken.d.ts +6 -3
  72. package/dist/classes/NativeToken.d.ts.map +1 -1
  73. package/dist/classes/NativeToken.js +11 -16
  74. package/dist/classes/NativeToken.js.map +1 -1
  75. package/dist/classes/OptimizerReader.d.ts +3 -3
  76. package/dist/classes/OptimizerReader.d.ts.map +1 -1
  77. package/dist/classes/OptimizerReader.js +1 -1
  78. package/dist/classes/OptimizerReader.js.map +1 -1
  79. package/dist/classes/OracleManager.d.ts +3 -3
  80. package/dist/classes/OracleManager.d.ts.map +1 -1
  81. package/dist/classes/OracleManager.js +1 -1
  82. package/dist/classes/OracleManager.js.map +1 -1
  83. package/dist/classes/PositionManager.d.ts +2 -2
  84. package/dist/classes/PositionManager.d.ts.map +1 -1
  85. package/dist/classes/PositionManager.js +4 -4
  86. package/dist/classes/PositionManager.js.map +1 -1
  87. package/dist/classes/ProtocolReader.d.ts +23 -8
  88. package/dist/classes/ProtocolReader.d.ts.map +1 -1
  89. package/dist/classes/ProtocolReader.js +197 -64
  90. package/dist/classes/ProtocolReader.js.map +1 -1
  91. package/dist/classes/Redstone.d.ts.map +1 -1
  92. package/dist/classes/Redstone.js +1 -2
  93. package/dist/classes/Redstone.js.map +1 -1
  94. package/dist/classes/Zapper.d.ts +4 -2
  95. package/dist/classes/Zapper.d.ts.map +1 -1
  96. package/dist/classes/Zapper.js +14 -13
  97. package/dist/classes/Zapper.js.map +1 -1
  98. package/dist/classes/index.d.ts +1 -1
  99. package/dist/classes/index.d.ts.map +1 -1
  100. package/dist/classes/index.js +6 -1
  101. package/dist/classes/index.js.map +1 -1
  102. package/dist/contracts/monad-mainnet.json +1 -1
  103. package/dist/helpers.d.ts +3 -1
  104. package/dist/helpers.d.ts.map +1 -1
  105. package/dist/helpers.js +34 -4
  106. package/dist/helpers.js.map +1 -1
  107. package/dist/integrations/snapshot.d.ts.map +1 -1
  108. package/dist/integrations/snapshot.js +4 -18
  109. package/dist/integrations/snapshot.js.map +1 -1
  110. package/dist/retry-provider.d.ts +83 -6
  111. package/dist/retry-provider.d.ts.map +1 -1
  112. package/dist/retry-provider.js +538 -68
  113. package/dist/retry-provider.js.map +1 -1
  114. package/dist/setup.d.ts +14 -3
  115. package/dist/setup.d.ts.map +1 -1
  116. package/dist/setup.js +67 -20
  117. package/dist/setup.js.map +1 -1
  118. package/dist/snapshot.d.ts +53 -0
  119. package/dist/snapshot.d.ts.map +1 -0
  120. package/dist/snapshot.js +103 -0
  121. package/dist/snapshot.js.map +1 -0
  122. package/dist/types.d.ts +2 -1
  123. package/dist/types.d.ts.map +1 -1
  124. package/dist/types.js.map +1 -1
  125. package/package.json +5 -2
@@ -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
  ]);
@@ -48,9 +46,10 @@ const EXCLUDED_ZAP_SYMBOLS = new Set([
48
46
  *
49
47
  * Because _swapSafe measures value loss against the FULL input (pre-fee),
50
48
  * the deterministic KyberSwap fee would consume feeBps of the user's MEV
51
- * tolerance if not compensated. Each call site expands action.slippage by
52
- * feeBps after quoting so the fee is absorbed and the user's chosen
53
- * tolerance is preserved for actual MEV/routing variance.
49
+ * tolerance if not compensated. `KyberSwap.quoteAction` (the DEX adapter)
50
+ * expands action.slippage by feeBps internally so the fee is absorbed and
51
+ * the user's chosen tolerance is preserved for actual MEV/routing variance.
52
+ * Callers pass raw user slippage — the adapter owns the expansion.
54
53
  *
55
54
  * Asymmetry between leverage up and deleverage
56
55
  * --------------------------------------------
@@ -81,10 +80,11 @@ const LEVERAGE = {
81
80
  * wei-level share rounding plus possible Redstone price drift between
82
81
  * snapshot RPC and tx broadcast block. Both are small constants.
83
82
  *
84
- * Fee handling: each call site expands both action.slippage (by feeBps,
85
- * so _swapSafe doesn't treat the fee as MEV) and contractSlippage (by
86
- * (L-1) × feeBps, so checkSlippage doesn't fire from equity-fraction
87
- * amplification). This buffer covers rounding/drift only. */
83
+ * Fee handling: KyberSwap.quoteAction expands action.slippage by feeBps
84
+ * internally so _swapSafe doesn't treat the fee as MEV. Each call site
85
+ * still computes contractSlippage (expanded by (L-1) × feeBps) so
86
+ * checkSlippage doesn't fire from equity-fraction amplification. This
87
+ * buffer covers rounding/drift only. */
88
88
  LEVERAGE_UP_BUFFER_BPS: 10n,
89
89
  /** BPS overhead on full deleverage swap sizing — absolute terms.
90
90
  * Oversizes the collateral→debt swap so DEX impact + drift doesn't
@@ -114,6 +114,8 @@ class CToken extends Calldata_1.Calldata {
114
114
  nativeApy = (0, decimal_js_1.default)(0);
115
115
  incentiveSupplyApy = (0, decimal_js_1.default)(0);
116
116
  incentiveBorrowApy = (0, decimal_js_1.default)(0);
117
+ get signer() { return this.market.signer; }
118
+ get account() { return this.market.account; }
117
119
  constructor(provider, address, cache, market) {
118
120
  super();
119
121
  this.provider = provider;
@@ -121,11 +123,11 @@ class CToken extends Calldata_1.Calldata {
121
123
  this.contract = (0, helpers_1.contractSetup)(provider, address, BaseCToken_json_1.default);
122
124
  this.cache = cache;
123
125
  this.market = market;
124
- const chain_config = (0, helpers_1.getChainConfig)();
126
+ const chainSettings = this.currentChainConfig;
125
127
  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;
128
+ this.isNativeVault = chainSettings.native_vaults.some(vault => vault.contract.toLowerCase() == assetAddr);
129
+ this.isVault = chainSettings.vaults.some(vault => vault.contract.toLowerCase() == assetAddr);
130
+ this.isWrappedNative = chainSettings.wrapped_native.toLowerCase() == assetAddr;
129
131
  if (EXCLUDED_ZAP_SYMBOLS.has(this.asset.symbol)) {
130
132
  return;
131
133
  }
@@ -143,6 +145,16 @@ class CToken extends Calldata_1.Calldata {
143
145
  this.leverageTypes.push('simple');
144
146
  this.zapTypes.push('simple');
145
147
  }
148
+ get setup() { return this.market.setup; }
149
+ get currentChain() { return this.setup.chain; }
150
+ get currentChainConfig() { return (0, helpers_1.getChainConfig)(this.currentChain); }
151
+ requireSigner() { return (0, helpers_1.requireSigner)(this.signer); }
152
+ getAccountOrThrow(account = null) {
153
+ return (0, helpers_1.requireAccount)(account ?? this.account, this.signer);
154
+ }
155
+ getWriteContract() {
156
+ return (0, helpers_1.contractSetup)(this.requireSigner(), this.address, BaseCToken_json_1.default);
157
+ }
146
158
  get adapters() { return this.cache.adapters; }
147
159
  get borrowPaused() { return this.cache.borrowPaused; }
148
160
  get collateralizationPaused() { return this.cache.collateralizationPaused; }
@@ -260,8 +272,7 @@ class CToken extends Calldata_1.Calldata {
260
272
  return inUSD ? this.convertTokensToUsd(this.cache.userCollateral, false) : FormatConverter_1.default.bigIntToDecimal(this.cache.userCollateral, this.decimals);
261
273
  }
262
274
  async fetchUserCollateral(formatted = false) {
263
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
264
- const collateral = await this.contract.collateralPosted(signer.address);
275
+ const collateral = await this.contract.collateralPosted(this.getAccountOrThrow());
265
276
  this.cache.userCollateral = collateral;
266
277
  return formatted ? (0, helpers_1.toDecimal)(collateral, this.decimals) : collateral;
267
278
  }
@@ -285,13 +296,15 @@ class CToken extends Calldata_1.Calldata {
285
296
  if (!this.isVault && !this.isNativeVault) {
286
297
  throw new Error("CToken does not use a vault asset as its underlying asset");
287
298
  }
288
- return new ERC4626_1.ERC4626(this.provider, this.getAsset(false));
299
+ return new ERC4626_1.ERC4626(this.provider, this.getAsset(false), undefined, this.setup.contracts.OracleManager, this.signer);
289
300
  }
290
301
  async getVaultAsset(asErc20) {
291
302
  return asErc20 ? await this.getUnderlyingVault().fetchAsset(true) : await this.getUnderlyingVault().fetchAsset(false);
292
303
  }
293
304
  getAsset(asErc20) {
294
- return asErc20 ? new ERC20_1.ERC20(this.provider, this.cache.asset.address, this.cache.asset) : this.cache.asset.address;
305
+ return asErc20
306
+ ? new ERC20_1.ERC20(this.provider, this.cache.asset.address, this.cache.asset, this.setup.contracts.OracleManager, this.signer)
307
+ : this.cache.asset.address;
295
308
  }
296
309
  getPrice(asset = false, lower = false, formatted = true) {
297
310
  let price = asset ? this.cache.assetPrice : this.cache.sharePrice;
@@ -335,7 +348,7 @@ class CToken extends Calldata_1.Calldata {
335
348
  return inUSD ? this.fetchConvertTokensToUsd(totalCollateral) : totalCollateral;
336
349
  }
337
350
  getPositionManager(type) {
338
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
351
+ const signer = this.requireSigner();
339
352
  let manager_contract = this.getPluginAddress(type, 'positionManager');
340
353
  if (manager_contract == null) {
341
354
  throw new Error("Plugin does not have an associated contract");
@@ -343,12 +356,12 @@ class CToken extends Calldata_1.Calldata {
343
356
  return new PositionManager_1.PositionManager(manager_contract, signer, type);
344
357
  }
345
358
  getZapper(type) {
346
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
359
+ const signer = this.requireSigner();
347
360
  const zap_contract = this.getPluginAddress(type, 'zapper');
348
361
  if (zap_contract == null) {
349
362
  return null;
350
363
  }
351
- return new Zapper_1.Zapper(zap_contract, signer, type);
364
+ return new Zapper_1.Zapper(zap_contract, signer, type, this.setup);
352
365
  }
353
366
  async isZapAssetApproved(instructions, amount) {
354
367
  if (instructions == 'none' || typeof instructions != 'object') {
@@ -357,8 +370,8 @@ class CToken extends Calldata_1.Calldata {
357
370
  if (instructions.inputToken.toLowerCase() === helpers_1.NATIVE_ADDRESS.toLowerCase()) {
358
371
  return true;
359
372
  }
360
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
361
- const asset = new ERC20_1.ERC20(signer, instructions.inputToken);
373
+ const signer = this.requireSigner();
374
+ const asset = new ERC20_1.ERC20(this.provider, instructions.inputToken, undefined, undefined, signer);
362
375
  const plugin = this.getPluginAddress(instructions.type, 'zapper');
363
376
  const allowance = await asset.allowance(signer.address, plugin);
364
377
  return allowance >= amount;
@@ -370,8 +383,8 @@ class CToken extends Calldata_1.Calldata {
370
383
  if (instructions.inputToken.toLowerCase() === helpers_1.NATIVE_ADDRESS.toLowerCase()) {
371
384
  return;
372
385
  }
373
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
374
- const asset = new ERC20_1.ERC20(signer, instructions.inputToken);
386
+ const signer = this.requireSigner();
387
+ const asset = new ERC20_1.ERC20(this.provider, instructions.inputToken, undefined, undefined, signer);
375
388
  const plugin = this.getPluginAddress(instructions.type, 'zapper');
376
389
  return asset.approve(plugin, amount);
377
390
  }
@@ -379,7 +392,7 @@ class CToken extends Calldata_1.Calldata {
379
392
  if (plugin == 'none') {
380
393
  return true;
381
394
  }
382
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
395
+ const signer = this.requireSigner();
383
396
  const plugin_address = this.getPluginAddress(plugin, type);
384
397
  if (plugin_address == null) {
385
398
  throw new Error("Plugin does not have an associated contract");
@@ -391,7 +404,7 @@ class CToken extends Calldata_1.Calldata {
391
404
  if (plugin_address == null) {
392
405
  throw new Error("Plugin does not have an associated contract");
393
406
  }
394
- return this.contract.setDelegateApproval(plugin_address, true);
407
+ return this.getWriteContract().setDelegateApproval(plugin_address, true);
395
408
  }
396
409
  getPluginAddress(plugin, type) {
397
410
  switch (type) {
@@ -402,10 +415,10 @@ class CToken extends Calldata_1.Calldata {
402
415
  throw new Error("Plugin does not have a contract to map too");
403
416
  }
404
417
  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)) {
418
+ if (!plugin_name || !this.setup.contracts.zappers || !(plugin_name in this.setup.contracts.zappers)) {
406
419
  throw new Error(`Plugin ${plugin_name} not found in zappers`);
407
420
  }
408
- return setup_1.setup_config.contracts.zappers[plugin_name];
421
+ return this.setup.contracts.zappers[plugin_name];
409
422
  }
410
423
  case 'positionManager': {
411
424
  switch (plugin) {
@@ -419,8 +432,8 @@ class CToken extends Calldata_1.Calldata {
419
432
  }
420
433
  }
421
434
  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);
435
+ const signer = this.requireSigner();
436
+ const erc20 = new ERC20_1.ERC20(this.provider, underlying ? this.asset.address : this.address, undefined, undefined, this.signer);
424
437
  const allowance = await erc20.allowance(signer.address, check_contract);
425
438
  return allowance;
426
439
  }
@@ -430,12 +443,12 @@ class CToken extends Calldata_1.Calldata {
430
443
  * @returns tx
431
444
  */
432
445
  async approveUnderlying(amount = null, target = null) {
433
- const erc20 = new ERC20_1.ERC20(this.provider, this.asset.address);
446
+ const erc20 = new ERC20_1.ERC20(this.provider, this.asset.address, undefined, undefined, this.signer);
434
447
  const tx = await erc20.approve(target ? target : this.address, amount);
435
448
  return tx;
436
449
  }
437
450
  async approve(amount = null, spender) {
438
- const erc20 = new ERC20_1.ERC20(this.provider, this.address);
451
+ const erc20 = new ERC20_1.ERC20(this.provider, this.address, undefined, undefined, this.signer);
439
452
  const tx = await erc20.approve(spender, amount);
440
453
  return tx;
441
454
  }
@@ -506,10 +519,10 @@ class CToken extends Calldata_1.Calldata {
506
519
  }
507
520
  async transfer(receiver, amount) {
508
521
  const shares = this.convertTokenInputToShares(amount);
509
- return this.contract.transfer(receiver, shares);
522
+ return this.getWriteContract().transfer(receiver, shares);
510
523
  }
511
524
  async redeemCollateral(amount, receiver = null, owner = null) {
512
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
525
+ const signer = this.requireSigner();
513
526
  receiver ??= signer.address;
514
527
  owner ??= signer.address;
515
528
  const shares = this.convertTokenInputToShares(amount);
@@ -517,7 +530,7 @@ class CToken extends Calldata_1.Calldata {
517
530
  return this.oracleRoute(calldata);
518
531
  }
519
532
  async postCollateral(amount) {
520
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
533
+ const signer = this.requireSigner();
521
534
  const shares = this.convertTokenInputToShares(amount);
522
535
  const balance = await this.balanceOf(signer.address);
523
536
  const collateral = await this.fetchUserCollateral();
@@ -530,14 +543,14 @@ class CToken extends Calldata_1.Calldata {
530
543
  return tx;
531
544
  }
532
545
  async getZapBalance(zap) {
533
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
546
+ const signer = this.requireSigner();
534
547
  let asset;
535
548
  if (typeof zap === 'object') {
536
549
  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);
550
+ asset = new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account);
538
551
  }
539
552
  else {
540
- asset = new ERC20_1.ERC20(this.provider, zap.inputToken);
553
+ asset = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
541
554
  }
542
555
  }
543
556
  else {
@@ -549,10 +562,10 @@ class CToken extends Calldata_1.Calldata {
549
562
  asset = await this.getVaultAsset(true);
550
563
  break;
551
564
  case 'native-vault':
552
- asset = new NativeToken_1.NativeToken(setup_1.setup_config.chain, this.provider);
565
+ asset = new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account);
553
566
  break;
554
567
  case 'native-simple':
555
- asset = new NativeToken_1.NativeToken(setup_1.setup_config.chain, this.provider);
568
+ asset = new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account);
556
569
  break;
557
570
  default: throw new Error("Unsupported zap type for balance fetch");
558
571
  }
@@ -570,7 +583,7 @@ class CToken extends Calldata_1.Calldata {
570
583
  decimals = 18n;
571
584
  }
572
585
  else {
573
- const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken);
586
+ const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
574
587
  decimals = inputErc20.decimals ?? await inputErc20.contract.decimals();
575
588
  }
576
589
  }
@@ -634,8 +647,7 @@ class CToken extends Calldata_1.Calldata {
634
647
  return bufferBps > 0n ? shares * (10000n - bufferBps) / 10000n : shares;
635
648
  }
636
649
  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);
650
+ const data = await this.market.reader.maxRedemptionOf(this.getAccountOrThrow(), this, bufferTime);
639
651
  if (data.errorCodeHit) {
640
652
  throw new Error(`Error fetching max redemption. Possible stale price or other issues...`);
641
653
  }
@@ -661,14 +673,14 @@ class CToken extends Calldata_1.Calldata {
661
673
  let tokens_exclude = [this.asset.address.toLocaleLowerCase()];
662
674
  if (this.zapTypes.includes('native-vault')) {
663
675
  tokens.push({
664
- interface: new NativeToken_1.NativeToken(setup_1.setup_config.chain, this.provider),
676
+ interface: new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account),
665
677
  type: 'native-vault'
666
678
  });
667
679
  tokens_exclude.push(helpers_1.EMPTY_ADDRESS, helpers_1.NATIVE_ADDRESS);
668
680
  }
669
681
  if (this.zapTypes.includes('native-simple')) {
670
682
  tokens.push({
671
- interface: new NativeToken_1.NativeToken(setup_1.setup_config.chain, this.provider),
683
+ interface: new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account),
672
684
  type: 'native-simple'
673
685
  });
674
686
  if (!this.zapTypes.includes('native-vault')) {
@@ -684,13 +696,13 @@ class CToken extends Calldata_1.Calldata {
684
696
  tokens_exclude.push(vault_asset.address.toLocaleLowerCase());
685
697
  }
686
698
  if (this.zapTypes.includes('simple')) {
687
- let dexAggSearch = await chains_1.chain_config[setup_1.setup_config.chain].dexAgg.getAvailableTokens(this.provider, search);
699
+ let dexAggSearch = await this.currentChainConfig.dexAgg.getAvailableTokens(this.provider, search, this.account);
688
700
  tokens = tokens.concat(dexAggSearch.filter(token => !tokens_exclude.includes(token.interface.address.toLocaleLowerCase())));
689
701
  // Add native MON as a zap option for any token with a simple zapper
690
702
  // (not just wrapped native). The simple zapper handles wrapping + swapping.
691
703
  if (!tokens_exclude.includes(helpers_1.NATIVE_ADDRESS.toLowerCase()) && !this.isWrappedNative) {
692
704
  tokens.push({
693
- interface: new NativeToken_1.NativeToken(setup_1.setup_config.chain, this.provider),
705
+ interface: new NativeToken_1.NativeToken(this.currentChain, this.provider, this.setup.contracts.OracleManager, this.signer, this.account),
694
706
  type: 'simple'
695
707
  });
696
708
  tokens_exclude.push(helpers_1.NATIVE_ADDRESS.toLowerCase());
@@ -705,9 +717,8 @@ class CToken extends Calldata_1.Calldata {
705
717
  return tokens;
706
718
  }
707
719
  async hypotheticalRedemptionOf(amount) {
708
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
709
720
  const shares = this.convertTokenInputToShares(amount);
710
- return this.market.reader.hypotheticalRedemptionOf(signer.address, this, shares);
721
+ return this.market.reader.hypotheticalRedemptionOf(this.getAccountOrThrow(), this, shares);
711
722
  }
712
723
  /**
713
724
  * Single-RPC snapshot of fresh position state for leverage operations.
@@ -720,8 +731,7 @@ class CToken extends Calldata_1.Calldata {
720
731
  * for full deleverage swap sizing).
721
732
  */
722
733
  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);
734
+ const snapshot = await this.market.reader.getLeverageSnapshot(this.getAccountOrThrow(), this.address, borrow.address, 120n);
725
735
  if (snapshot.oracleError) {
726
736
  throw new Error(`Oracle error fetching leverage snapshot for ${this.symbol}/${borrow.symbol}`);
727
737
  }
@@ -766,7 +776,7 @@ class CToken extends Calldata_1.Calldata {
766
776
  const borrowAmount = rawDebtInUsd.sub(currentDebt).div(borrowPrice);
767
777
  // Fee preview: queried from the configured fee policy.
768
778
  const borrowAssets = FormatConverter_1.default.decimalToBigInt(borrowAmount, borrow.asset.decimals);
769
- const feeBps = setup_1.setup_config.feePolicy.getFeeBps({
779
+ const feeBps = this.setup.feePolicy.getFeeBps({
770
780
  operation: 'leverage-up',
771
781
  inputToken: borrow.asset.address,
772
782
  outputToken: this.asset.address,
@@ -813,7 +823,7 @@ class CToken extends Calldata_1.Calldata {
813
823
  // (exact for partial; for full deleverage the actual swap is sized
814
824
  // by leverageDown using the snapshot, but the preview is close enough
815
825
  // for display purposes).
816
- const feeBps = borrow ? setup_1.setup_config.feePolicy.getFeeBps({
826
+ const feeBps = borrow ? this.setup.feePolicy.getFeeBps({
817
827
  operation: 'leverage-down',
818
828
  inputToken: this.asset.address,
819
829
  outputToken: borrow.asset.address,
@@ -840,7 +850,7 @@ class CToken extends Calldata_1.Calldata {
840
850
  }
841
851
  async leverageUp(borrow, newLeverage, type, slippage_ = (0, decimal_js_1.default)(0.05), simulate = false) {
842
852
  try {
843
- (0, helpers_1.validateProviderAsSigner)(this.provider);
853
+ this.requireSigner();
844
854
  const slippage = this._leverageUpSlippage(FormatConverter_1.default.percentageToBps(slippage_), newLeverage);
845
855
  const manager = this.getPositionManager(type);
846
856
  let calldata;
@@ -849,7 +859,7 @@ class CToken extends Calldata_1.Calldata {
849
859
  switch (type) {
850
860
  case 'simple': {
851
861
  const borrowAssets = FormatConverter_1.default.decimalToBigInt(borrowAmount, borrow.asset.decimals);
852
- const feeBps = setup_1.setup_config.feePolicy.getFeeBps({
862
+ const feeBps = this.setup.feePolicy.getFeeBps({
853
863
  operation: 'leverage-up',
854
864
  inputToken: borrow.asset.address,
855
865
  outputToken: this.asset.address,
@@ -857,18 +867,12 @@ class CToken extends Calldata_1.Calldata {
857
867
  currentLeverage: this.getLeverage() ?? (0, decimal_js_1.default)(1),
858
868
  targetLeverage: newLeverage,
859
869
  });
860
- const feeReceiver = feeBps > 0n ? setup_1.setup_config.feePolicy.feeReceiver : undefined;
861
- 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);
862
- // _swapSafe measures value loss as (valueIn - valueOut) / valueIn
863
- // where valueIn is the FULL input (pre-fee). KyberSwap deducts
864
- // the fee before swapping, so _swapSafe sees feeBps as "slippage"
865
- // even though it's a known, deterministic cost. Expand
866
- // action.slippage by feeBps so the fee doesn't consume the user's
867
- // MEV protection budget. The KyberSwap quote already used the
868
- // user's raw slippage for minReturnAmount (DEX-level protection).
869
- if (feeBps > 0n) {
870
- action.slippage = FormatConverter_1.default.bpsToBpsWad(slippage + feeBps);
871
- }
870
+ const feeReceiver = feeBps > 0n ? this.setup.feePolicy.feeReceiver : undefined;
871
+ const { action, quote } = await this.currentChainConfig.dexAgg.quoteAction(manager.address, borrow.asset.address, this.asset.address, borrowAssets, slippage, feeBps, feeReceiver);
872
+ // Fee-aware slippage expansion now lives inside KyberSwap.quoteAction
873
+ // so any caller inherits correct behavior. See KyberSwap.ts for the
874
+ // rationale. The fee still reduces swap output, which checkSlippage
875
+ // sees as equity loss amplified by (L-1) — handled below.
872
876
  // The fee also reduces swap output, which checkSlippage sees
873
877
  // as equity loss amplified by (L-1) — same pattern as
874
878
  // deleverage. Expand the contract-level tolerance to absorb it.
@@ -923,8 +927,8 @@ class CToken extends Calldata_1.Calldata {
923
927
  return { success: false, error: "New leverage must be less than current leverage" };
924
928
  throw new Error("New leverage must be less than current leverage");
925
929
  }
926
- (0, helpers_1.validateProviderAsSigner)(this.provider);
927
- const config = (0, helpers_1.getChainConfig)();
930
+ this.requireSigner();
931
+ const config = this.currentChainConfig;
928
932
  const slippage = (0, helpers_1.toBps)(slippage_);
929
933
  const manager = this.getPositionManager(type);
930
934
  let calldata;
@@ -949,7 +953,7 @@ class CToken extends Calldata_1.Calldata {
949
953
  // exact for current callers. Future notional-tiered policies
950
954
  // should be aware that for full deleverage the inputAmount
951
955
  // passed here is an underestimate.
952
- const feeBps = setup_1.setup_config.feePolicy.getFeeBps({
956
+ const feeBps = this.setup.feePolicy.getFeeBps({
953
957
  operation: 'leverage-down',
954
958
  inputToken: this.asset.address,
955
959
  outputToken: borrowToken.asset.address,
@@ -957,7 +961,7 @@ class CToken extends Calldata_1.Calldata {
957
961
  currentLeverage: currentLeverage,
958
962
  targetLeverage: newLeverage,
959
963
  });
960
- const feeReceiver = feeBps > 0n ? setup_1.setup_config.feePolicy.feeReceiver : undefined;
964
+ const feeReceiver = feeBps > 0n ? this.setup.feePolicy.feeReceiver : undefined;
961
965
  if (isFullDeleverage) {
962
966
  // Use exact projected debt from snapshot to size the swap.
963
967
  // debtTokenBalance is in debt-token native decimals, projected
@@ -987,12 +991,8 @@ class CToken extends Calldata_1.Calldata {
987
991
  swapCollateral = swapCollateral * 10000n / (10000n - feeBps);
988
992
  }
989
993
  const { action, quote } = await config.dexAgg.quoteAction(manager.address, this.asset.address, borrowToken.asset.address, swapCollateral, slippage, feeBps, feeReceiver);
990
- // _swapSafe: expand action.slippage by feeBps so the
991
- // deterministic fee cost doesn't eat the user's MEV budget.
992
- // Same rationale as leverageUp — see comment there.
993
- if (feeBps > 0n) {
994
- action.slippage = FormatConverter_1.default.bpsToBpsWad(slippage + feeBps);
995
- }
994
+ // Fee-aware slippage expansion for `_swapSafe` is handled by
995
+ // KyberSwap.quoteAction. See KyberSwap.ts for rationale.
996
996
  const minRepay = isFullDeleverage ? 1n : quote.min_out;
997
997
  // checkSlippage measures equity-fraction loss. Both the
998
998
  // intentional swap overshoot (full deleverage only) and the
@@ -1058,7 +1058,7 @@ class CToken extends Calldata_1.Calldata {
1058
1058
  switch (type) {
1059
1059
  case 'simple': {
1060
1060
  const borrowAssets = FormatConverter_1.default.decimalToBigInt(borrowAmount, borrow.asset.decimals);
1061
- const feeBps = setup_1.setup_config.feePolicy.getFeeBps({
1061
+ const feeBps = this.setup.feePolicy.getFeeBps({
1062
1062
  operation: 'deposit-and-leverage',
1063
1063
  inputToken: borrow.asset.address,
1064
1064
  outputToken: this.asset.address,
@@ -1066,14 +1066,10 @@ class CToken extends Calldata_1.Calldata {
1066
1066
  currentLeverage: this.getLeverage() ?? (0, decimal_js_1.default)(1),
1067
1067
  targetLeverage: multiplier,
1068
1068
  });
1069
- const feeReceiver = feeBps > 0n ? setup_1.setup_config.feePolicy.feeReceiver : undefined;
1070
- 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);
1071
- // _swapSafe: expand action.slippage by feeBps so the
1072
- // deterministic fee cost doesn't eat the user's MEV budget.
1073
- // Same rationale as leverageUp — see comment there.
1074
- if (feeBps > 0n) {
1075
- action.slippage = FormatConverter_1.default.bpsToBpsWad(slippage + feeBps);
1076
- }
1069
+ const feeReceiver = feeBps > 0n ? this.setup.feePolicy.feeReceiver : undefined;
1070
+ const { action, quote } = await this.currentChainConfig.dexAgg.quoteAction(manager.address, borrow.asset.address, this.asset.address, borrowAssets, slippage, feeBps, feeReceiver);
1071
+ // Fee-aware slippage expansion for `_swapSafe` is handled by
1072
+ // KyberSwap.quoteAction. See KyberSwap.ts for rationale.
1077
1073
  // Fee amplification: same pattern as leverageUp.
1078
1074
  const contractSlippage = feeBps > 0n
1079
1075
  ? slippage + BigInt(multiplier.sub(1)
@@ -1122,7 +1118,7 @@ class CToken extends Calldata_1.Calldata {
1122
1118
  async simulateDeposit(amount, zap = 'none', receiver = null) {
1123
1119
  try {
1124
1120
  amount = await this.ensureUnderlyingAmount(amount, zap);
1125
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
1121
+ const signer = this.requireSigner();
1126
1122
  receiver ??= signer.address;
1127
1123
  const isZapping = typeof zap === 'object' && zap.type !== 'none';
1128
1124
  const depositAssets = FormatConverter_1.default.decimalToBigInt(amount, this.asset.decimals);
@@ -1130,7 +1126,7 @@ class CToken extends Calldata_1.Calldata {
1130
1126
  if (isZapping && zap.inputToken) {
1131
1127
  const isNative = zap.inputToken.toLowerCase() === helpers_1.NATIVE_ADDRESS.toLowerCase();
1132
1128
  const zapDecimals = isNative ? 18n : (() => {
1133
- const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken);
1129
+ const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
1134
1130
  return inputErc20.decimals ?? inputErc20.contract.decimals();
1135
1131
  })();
1136
1132
  zapAssets = FormatConverter_1.default.decimalToBigInt(amount, await zapDecimals);
@@ -1146,7 +1142,7 @@ class CToken extends Calldata_1.Calldata {
1146
1142
  async simulateDepositAsCollateral(amount, zap = 'none', receiver = null) {
1147
1143
  try {
1148
1144
  amount = await this.ensureUnderlyingAmount(amount, zap);
1149
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
1145
+ const signer = this.requireSigner();
1150
1146
  receiver ??= signer.address;
1151
1147
  const isZapping = typeof zap === 'object' && zap.type !== 'none';
1152
1148
  const depositAssets = FormatConverter_1.default.decimalToBigInt(amount, this.asset.decimals);
@@ -1154,7 +1150,7 @@ class CToken extends Calldata_1.Calldata {
1154
1150
  if (isZapping && zap.inputToken) {
1155
1151
  const isNative = zap.inputToken.toLowerCase() === helpers_1.NATIVE_ADDRESS.toLowerCase();
1156
1152
  const zapDecimals = isNative ? 18n : (() => {
1157
- const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken);
1153
+ const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
1158
1154
  return inputErc20.decimals ?? inputErc20.contract.decimals();
1159
1155
  })();
1160
1156
  zapAssets = FormatConverter_1.default.decimalToBigInt(amount, await zapDecimals);
@@ -1215,7 +1211,7 @@ class CToken extends Calldata_1.Calldata {
1215
1211
  }
1216
1212
  async deposit(amount, zap = 'none', receiver = null) {
1217
1213
  amount = await this.ensureUnderlyingAmount(amount, zap);
1218
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
1214
+ const signer = this.requireSigner();
1219
1215
  receiver ??= signer.address;
1220
1216
  // When zapping, the swap amount uses input token decimals, but the
1221
1217
  // default deposit calldata uses the deposit token decimals.
@@ -1227,7 +1223,7 @@ class CToken extends Calldata_1.Calldata {
1227
1223
  zapAssets = FormatConverter_1.default.decimalToBigInt(amount, 18n);
1228
1224
  }
1229
1225
  else {
1230
- const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken);
1226
+ const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
1231
1227
  const zapDecimals = inputErc20.decimals ?? await inputErc20.contract.decimals();
1232
1228
  zapAssets = FormatConverter_1.default.decimalToBigInt(amount, zapDecimals);
1233
1229
  }
@@ -1251,7 +1247,7 @@ class CToken extends Calldata_1.Calldata {
1251
1247
  }
1252
1248
  async depositAsCollateral(amount, zap = 'none', receiver = null) {
1253
1249
  amount = await this.ensureUnderlyingAmount(amount, zap);
1254
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
1250
+ const signer = this.requireSigner();
1255
1251
  receiver ??= signer.address;
1256
1252
  // When zapping, the swap amount uses input token decimals, but collateral
1257
1253
  // cap checks and the default deposit calldata use the deposit token decimals.
@@ -1263,7 +1259,7 @@ class CToken extends Calldata_1.Calldata {
1263
1259
  zapAssets = FormatConverter_1.default.decimalToBigInt(amount, 18n);
1264
1260
  }
1265
1261
  else {
1266
- const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken);
1262
+ const inputErc20 = new ERC20_1.ERC20(this.provider, zap.inputToken, undefined, undefined, this.signer);
1267
1263
  const zapDecimals = inputErc20.decimals ?? await inputErc20.contract.decimals();
1268
1264
  zapAssets = FormatConverter_1.default.decimalToBigInt(amount, zapDecimals);
1269
1265
  }
@@ -1286,7 +1282,7 @@ class CToken extends Calldata_1.Calldata {
1286
1282
  return this.oracleRoute(calldata, calldata_overrides);
1287
1283
  }
1288
1284
  async redeem(amount) {
1289
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
1285
+ const signer = this.requireSigner();
1290
1286
  const receiver = signer.address;
1291
1287
  const owner = signer.address;
1292
1288
  const buffer = this.market.userDebt.greaterThan(0) ? 100n : 0n;
@@ -1301,19 +1297,17 @@ class CToken extends Calldata_1.Calldata {
1301
1297
  return this.oracleRoute(calldata);
1302
1298
  }
1303
1299
  async redeemShares(amount) {
1304
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
1300
+ const signer = this.requireSigner();
1305
1301
  const receiver = signer.address;
1306
1302
  const owner = signer.address;
1307
1303
  const calldata = this.getCallData("redeem", [amount, receiver, owner]);
1308
1304
  return this.oracleRoute(calldata);
1309
1305
  }
1310
1306
  async collateralPosted(account = null) {
1311
- if (!account)
1312
- account = (0, helpers_1.validateProviderAsSigner)(this.provider).address;
1313
- return this.contract.collateralPosted(account);
1307
+ return this.contract.collateralPosted(this.getAccountOrThrow(account));
1314
1308
  }
1315
1309
  async multicall(calls) {
1316
- return this.contract.multicall(calls);
1310
+ return this.getWriteContract().multicall(calls);
1317
1311
  }
1318
1312
  async getSnapshot(account) {
1319
1313
  const snapshot = await this.contract.getSnapshot(account);
@@ -1372,10 +1366,10 @@ class CToken extends Calldata_1.Calldata {
1372
1366
  }
1373
1367
  }
1374
1368
  async _checkZapperApproval(zapper) {
1375
- if (!setup_1.setup_config.approval_protection) {
1369
+ if (!this.setup.approval_protection) {
1376
1370
  return;
1377
1371
  }
1378
- if (setup_1.setup_config.approval_protection && zapper) {
1372
+ if (this.setup.approval_protection && zapper) {
1379
1373
  const plugin_allowed = await this.isPluginApproved(zapper.type, 'zapper');
1380
1374
  if (!plugin_allowed) {
1381
1375
  throw new Error(`Please approve the ${zapper.type} Zapper to be able to move ${this.symbol} on your behalf.`);
@@ -1383,8 +1377,8 @@ class CToken extends Calldata_1.Calldata {
1383
1377
  }
1384
1378
  }
1385
1379
  async _checkErc20Approval(erc20_address, amount, spender) {
1386
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
1387
- const erc20 = new ERC20_1.ERC20(signer, erc20_address);
1380
+ const signer = this.requireSigner();
1381
+ const erc20 = new ERC20_1.ERC20(this.provider, erc20_address, undefined, undefined, signer);
1388
1382
  const allowance = await erc20.allowance(signer.address, spender);
1389
1383
  if (allowance < amount) {
1390
1384
  const symbol = await erc20.fetchSymbol();
@@ -1392,18 +1386,18 @@ class CToken extends Calldata_1.Calldata {
1392
1386
  }
1393
1387
  }
1394
1388
  async _checkAssetApproval(assets) {
1395
- if (!setup_1.setup_config.approval_protection) {
1389
+ if (!this.setup.approval_protection) {
1396
1390
  return;
1397
1391
  }
1398
1392
  const asset = this.getAsset(true);
1399
- const owner = (0, helpers_1.validateProviderAsSigner)(this.provider).address;
1393
+ const owner = this.getAccountOrThrow();
1400
1394
  const allowance = await asset.allowance(owner, this.address);
1401
1395
  if (allowance < assets) {
1402
1396
  throw new Error(`Please approve the ${asset.symbol} token for ${this.symbol}`);
1403
1397
  }
1404
1398
  }
1405
1399
  async _checkDepositApprovals(zapper, assets) {
1406
- if (!setup_1.setup_config.approval_protection) {
1400
+ if (!this.setup.approval_protection) {
1407
1401
  return;
1408
1402
  }
1409
1403
  if (zapper) {
@@ -1412,7 +1406,7 @@ class CToken extends Calldata_1.Calldata {
1412
1406
  await this._checkAssetApproval(assets);
1413
1407
  }
1414
1408
  async oracleRoute(calldata, override = {}) {
1415
- const signer = (0, helpers_1.validateProviderAsSigner)(this.provider);
1409
+ const signer = this.requireSigner();
1416
1410
  const price_updates = await this.getPriceUpdates();
1417
1411
  if (price_updates.length > 0) {
1418
1412
  const token_action = this.buildMultiCallAction(calldata);