@gearbox-protocol/sdk 14.12.0-next.23 → 14.12.0-next.24

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 (98) hide show
  1. package/dist/cjs/plugins/adapters/contracts/AbstractAdapter.js +31 -9
  2. package/dist/cjs/plugins/adapters/contracts/AbstractCurveAdapter.js +8 -5
  3. package/dist/cjs/plugins/adapters/contracts/BalancerV3RouterAdapterContract.js +6 -4
  4. package/dist/cjs/plugins/adapters/contracts/BalancerV3WrapperAdapterContract.js +6 -4
  5. package/dist/cjs/plugins/adapters/contracts/CamelotV3AdapterContract.js +6 -9
  6. package/dist/cjs/plugins/adapters/contracts/ConvexV1BaseRewardPoolAdapterContract.js +7 -5
  7. package/dist/cjs/plugins/adapters/contracts/ConvexV1BoosterAdapterContract.js +6 -4
  8. package/dist/cjs/plugins/adapters/contracts/DaiUsdsAdapterContract.js +6 -4
  9. package/dist/cjs/plugins/adapters/contracts/ERC4626AdapterContract.js +13 -4
  10. package/dist/cjs/plugins/adapters/contracts/ERC4626ReferralAdapterContract.js +6 -4
  11. package/dist/cjs/plugins/adapters/contracts/FluidDexAdapterContract.js +8 -8
  12. package/dist/cjs/plugins/adapters/contracts/InfinifiGatewayAdapterContract.js +8 -5
  13. package/dist/cjs/plugins/adapters/contracts/KelpLRTDepositPoolAdapterContract.js +4 -3
  14. package/dist/cjs/plugins/adapters/contracts/LidoV1AdapterContract.js +4 -3
  15. package/dist/cjs/plugins/adapters/contracts/MellowClaimerAdapterContract.js +29 -0
  16. package/dist/cjs/plugins/adapters/contracts/MellowDVVAdapterContract.js +6 -4
  17. package/dist/cjs/plugins/adapters/contracts/MellowERC4626VaultAdapterContract.js +11 -4
  18. package/dist/cjs/plugins/adapters/contracts/MellowWrapperAdapterContract.js +4 -3
  19. package/dist/cjs/plugins/adapters/contracts/MidasGatewayAdapterContract.js +31 -4
  20. package/dist/cjs/plugins/adapters/contracts/MidasIssuanceVaultAdapterContract.js +4 -3
  21. package/dist/cjs/plugins/adapters/contracts/MidasRedemptionVaultAdapterContract.js +4 -3
  22. package/dist/cjs/plugins/adapters/contracts/PendleRouterAdapterContract.js +14 -16
  23. package/dist/cjs/plugins/adapters/contracts/SecuritizeOnRampAdapterContract.js +4 -3
  24. package/dist/cjs/plugins/adapters/contracts/SecuritizeRedemptionGatewayAdapterContract.js +14 -13
  25. package/dist/cjs/plugins/adapters/contracts/StakingRewardsAdapterContract.js +7 -5
  26. package/dist/cjs/plugins/adapters/contracts/TraderJoeRouterAdapterContract.js +4 -3
  27. package/dist/cjs/plugins/adapters/contracts/UniswapV2AdapterContract.js +4 -3
  28. package/dist/cjs/plugins/adapters/contracts/UniswapV3AdapterContract.js +6 -9
  29. package/dist/cjs/plugins/adapters/contracts/UniswapV4AdapterContract.js +8 -8
  30. package/dist/cjs/plugins/adapters/contracts/UpshiftVaultAdapterContract.js +6 -4
  31. package/dist/cjs/plugins/adapters/contracts/VelodromeV2AdapterContract.js +4 -3
  32. package/dist/cjs/plugins/adapters/contracts/WstETHV1AdapterContract.js +6 -4
  33. package/dist/esm/plugins/adapters/contracts/AbstractAdapter.js +31 -9
  34. package/dist/esm/plugins/adapters/contracts/AbstractCurveAdapter.js +8 -5
  35. package/dist/esm/plugins/adapters/contracts/BalancerV3RouterAdapterContract.js +6 -4
  36. package/dist/esm/plugins/adapters/contracts/BalancerV3WrapperAdapterContract.js +6 -4
  37. package/dist/esm/plugins/adapters/contracts/CamelotV3AdapterContract.js +6 -9
  38. package/dist/esm/plugins/adapters/contracts/ConvexV1BaseRewardPoolAdapterContract.js +7 -5
  39. package/dist/esm/plugins/adapters/contracts/ConvexV1BoosterAdapterContract.js +6 -4
  40. package/dist/esm/plugins/adapters/contracts/DaiUsdsAdapterContract.js +6 -4
  41. package/dist/esm/plugins/adapters/contracts/ERC4626AdapterContract.js +13 -4
  42. package/dist/esm/plugins/adapters/contracts/ERC4626ReferralAdapterContract.js +6 -4
  43. package/dist/esm/plugins/adapters/contracts/FluidDexAdapterContract.js +8 -8
  44. package/dist/esm/plugins/adapters/contracts/InfinifiGatewayAdapterContract.js +8 -5
  45. package/dist/esm/plugins/adapters/contracts/KelpLRTDepositPoolAdapterContract.js +4 -3
  46. package/dist/esm/plugins/adapters/contracts/LidoV1AdapterContract.js +4 -3
  47. package/dist/esm/plugins/adapters/contracts/MellowClaimerAdapterContract.js +32 -1
  48. package/dist/esm/plugins/adapters/contracts/MellowDVVAdapterContract.js +6 -4
  49. package/dist/esm/plugins/adapters/contracts/MellowERC4626VaultAdapterContract.js +11 -4
  50. package/dist/esm/plugins/adapters/contracts/MellowWrapperAdapterContract.js +4 -3
  51. package/dist/esm/plugins/adapters/contracts/MidasGatewayAdapterContract.js +33 -5
  52. package/dist/esm/plugins/adapters/contracts/MidasIssuanceVaultAdapterContract.js +4 -3
  53. package/dist/esm/plugins/adapters/contracts/MidasRedemptionVaultAdapterContract.js +4 -3
  54. package/dist/esm/plugins/adapters/contracts/PendleRouterAdapterContract.js +14 -16
  55. package/dist/esm/plugins/adapters/contracts/SecuritizeOnRampAdapterContract.js +4 -3
  56. package/dist/esm/plugins/adapters/contracts/SecuritizeRedemptionGatewayAdapterContract.js +14 -13
  57. package/dist/esm/plugins/adapters/contracts/StakingRewardsAdapterContract.js +7 -5
  58. package/dist/esm/plugins/adapters/contracts/TraderJoeRouterAdapterContract.js +4 -3
  59. package/dist/esm/plugins/adapters/contracts/UniswapV2AdapterContract.js +4 -3
  60. package/dist/esm/plugins/adapters/contracts/UniswapV3AdapterContract.js +6 -9
  61. package/dist/esm/plugins/adapters/contracts/UniswapV4AdapterContract.js +8 -8
  62. package/dist/esm/plugins/adapters/contracts/UpshiftVaultAdapterContract.js +6 -4
  63. package/dist/esm/plugins/adapters/contracts/VelodromeV2AdapterContract.js +4 -3
  64. package/dist/esm/plugins/adapters/contracts/WstETHV1AdapterContract.js +6 -4
  65. package/dist/types/plugins/adapters/contracts/AbstractAdapter.d.ts +27 -7
  66. package/dist/types/plugins/adapters/contracts/AbstractCurveAdapter.d.ts +2 -3
  67. package/dist/types/plugins/adapters/contracts/BalancerV3RouterAdapterContract.d.ts +2 -3
  68. package/dist/types/plugins/adapters/contracts/BalancerV3WrapperAdapterContract.d.ts +2 -3
  69. package/dist/types/plugins/adapters/contracts/CamelotV3AdapterContract.d.ts +2 -3
  70. package/dist/types/plugins/adapters/contracts/ConvexV1BaseRewardPoolAdapterContract.d.ts +2 -3
  71. package/dist/types/plugins/adapters/contracts/ConvexV1BoosterAdapterContract.d.ts +2 -3
  72. package/dist/types/plugins/adapters/contracts/DaiUsdsAdapterContract.d.ts +2 -3
  73. package/dist/types/plugins/adapters/contracts/ERC4626AdapterContract.d.ts +2 -3
  74. package/dist/types/plugins/adapters/contracts/ERC4626ReferralAdapterContract.d.ts +2 -3
  75. package/dist/types/plugins/adapters/contracts/FluidDexAdapterContract.d.ts +2 -3
  76. package/dist/types/plugins/adapters/contracts/InfinifiGatewayAdapterContract.d.ts +2 -3
  77. package/dist/types/plugins/adapters/contracts/KelpLRTDepositPoolAdapterContract.d.ts +2 -3
  78. package/dist/types/plugins/adapters/contracts/LidoV1AdapterContract.d.ts +2 -3
  79. package/dist/types/plugins/adapters/contracts/MellowClaimerAdapterContract.d.ts +3 -2
  80. package/dist/types/plugins/adapters/contracts/MellowDVVAdapterContract.d.ts +2 -3
  81. package/dist/types/plugins/adapters/contracts/MellowERC4626VaultAdapterContract.d.ts +2 -3
  82. package/dist/types/plugins/adapters/contracts/MellowWrapperAdapterContract.d.ts +2 -3
  83. package/dist/types/plugins/adapters/contracts/MidasGatewayAdapterContract.d.ts +2 -3
  84. package/dist/types/plugins/adapters/contracts/MidasIssuanceVaultAdapterContract.d.ts +2 -3
  85. package/dist/types/plugins/adapters/contracts/MidasRedemptionVaultAdapterContract.d.ts +2 -3
  86. package/dist/types/plugins/adapters/contracts/PendleRouterAdapterContract.d.ts +2 -3
  87. package/dist/types/plugins/adapters/contracts/SecuritizeOnRampAdapterContract.d.ts +2 -3
  88. package/dist/types/plugins/adapters/contracts/SecuritizeRedemptionGatewayAdapterContract.d.ts +2 -3
  89. package/dist/types/plugins/adapters/contracts/StakingRewardsAdapterContract.d.ts +2 -3
  90. package/dist/types/plugins/adapters/contracts/TraderJoeRouterAdapterContract.d.ts +2 -3
  91. package/dist/types/plugins/adapters/contracts/UniswapV2AdapterContract.d.ts +2 -3
  92. package/dist/types/plugins/adapters/contracts/UniswapV3AdapterContract.d.ts +2 -3
  93. package/dist/types/plugins/adapters/contracts/UniswapV4AdapterContract.d.ts +2 -3
  94. package/dist/types/plugins/adapters/contracts/UpshiftVaultAdapterContract.d.ts +2 -3
  95. package/dist/types/plugins/adapters/contracts/VelodromeV2AdapterContract.d.ts +2 -3
  96. package/dist/types/plugins/adapters/contracts/WstETHV1AdapterContract.d.ts +2 -3
  97. package/dist/types/plugins/adapters/types.d.ts +0 -10
  98. package/package.json +1 -1
@@ -117,27 +117,29 @@ class PendleRouterAdapterContract extends import_AbstractAdapter.AbstractAdapter
117
117
  }))
118
118
  };
119
119
  }
120
- decodeDiffLeftovers(decoded, balances) {
120
+ applyBalanceChanges(balances, decoded) {
121
121
  switch (decoded.functionName) {
122
122
  case "swapDiffTokenForPt":
123
123
  case "addLiquiditySingleTokenDiff": {
124
124
  const [, , , diffInput] = decoded.args;
125
- return [
126
- {
127
- tokenIn: diffInput.tokenIn,
128
- leftoverAmount: diffInput.leftoverTokenIn
129
- }
130
- ];
125
+ this.setLeftover(
126
+ balances,
127
+ diffInput.tokenIn,
128
+ diffInput.leftoverTokenIn
129
+ );
130
+ break;
131
131
  }
132
132
  case "swapDiffPtForToken": {
133
133
  const [market, leftoverPt] = decoded.args;
134
134
  const pt = this.#mustFindPendleToken(market, 0 /* PT */);
135
- return [{ tokenIn: pt, leftoverAmount: leftoverPt }];
135
+ this.setLeftover(balances, pt, leftoverPt);
136
+ break;
136
137
  }
137
138
  case "removeLiquiditySingleTokenDiff": {
138
139
  const [market, leftoverLp] = decoded.args;
139
140
  const lp = this.#mustFindPendleToken(market, 1 /* LP */);
140
- return [{ tokenIn: lp, leftoverAmount: leftoverLp }];
141
+ this.setLeftover(balances, lp, leftoverLp);
142
+ break;
141
143
  }
142
144
  case "redeemDiffPyToToken": {
143
145
  const candidates = this.allowedPairs.filter(
@@ -152,15 +154,11 @@ class PendleRouterAdapterContract extends import_AbstractAdapter.AbstractAdapter
152
154
  );
153
155
  }
154
156
  const [, leftoverPt] = decoded.args;
155
- return [
156
- {
157
- tokenIn: candidates[0].pendleToken,
158
- leftoverAmount: leftoverPt
159
- }
160
- ];
157
+ this.setLeftover(balances, candidates[0].pendleToken, leftoverPt);
158
+ break;
161
159
  }
162
160
  default:
163
- return super.decodeDiffLeftovers(decoded, balances);
161
+ super.applyBalanceChanges(balances, decoded);
164
162
  }
165
163
  }
166
164
  #mustFindPendleToken(market, type) {
@@ -64,15 +64,16 @@ class SecuritizeOnRampAdapterContract extends import_AbstractAdapter.AbstractAda
64
64
  liquidityToken: this.#liquidityToken ? this.labelAddress(this.#liquidityToken) : void 0
65
65
  };
66
66
  }
67
- decodeDiffLeftovers(decoded, balances) {
67
+ applyBalanceChanges(balances, decoded) {
68
68
  switch (decoded.functionName) {
69
69
  // swaps the liquidity token into dsToken
70
70
  case "swapDiff": {
71
71
  const [leftoverAmount] = decoded.args;
72
- return [{ tokenIn: this.liquidityToken, leftoverAmount }];
72
+ this.setLeftover(balances, this.liquidityToken, leftoverAmount);
73
+ break;
73
74
  }
74
75
  default:
75
- return super.decodeDiffLeftovers(decoded, balances);
76
+ super.applyBalanceChanges(balances, decoded);
76
77
  }
77
78
  }
78
79
  }
@@ -72,28 +72,29 @@ class SecuritizeRedemptionGatewayAdapterContract extends import_AbstractAdapter.
72
72
  redemptionPhantomToken: this.#redemptionPhantomToken ? this.labelAddress(this.#redemptionPhantomToken) : void 0
73
73
  };
74
74
  }
75
- decodeDiffLeftovers(decoded, balances) {
75
+ applyBalanceChanges(balances, decoded) {
76
76
  switch (decoded.functionName) {
77
- // exact-input redemption: burns dsTokenAmount of the DS token in
78
- // exchange for the redemption phantom token (which is credited by the
79
- // storeExpectedBalances bracket delta, not here)
80
77
  case "redeem": {
81
78
  const [dsTokenAmount] = decoded.args;
82
- const balance = balances.get(this.dsToken) ?? 0n;
83
- return [
84
- {
85
- tokenIn: this.dsToken,
86
- leftoverAmount: balance > dsTokenAmount ? balance - dsTokenAmount : 0n
87
- }
88
- ];
79
+ this.spendExact(balances, this.dsToken, dsTokenAmount);
80
+ break;
89
81
  }
90
82
  // diff-style redemption: spends the DS token down to the leftover
91
83
  case "redeemDiff": {
92
84
  const [leftoverAmount] = decoded.args;
93
- return [{ tokenIn: this.dsToken, leftoverAmount }];
85
+ this.setLeftover(balances, this.dsToken, leftoverAmount);
86
+ break;
94
87
  }
88
+ // TODO:
89
+ // `claim(address[] redeemers)` (the claim call emitted by the
90
+ // withdrawal compressor) cannot be previewed offline: the redemption
91
+ // phantom token burn (the compressor's `withdrawalTokenSpent`, i.e.
92
+ // each redeemer's `getRedemptionAmount()`) lives in per-redeemer clone
93
+ // contracts and is not recoverable from calldata. For claimable
94
+ // redeemers it equals the stablecoin credit, but that value is not in
95
+ // calldata either.
95
96
  default:
96
- return super.decodeDiffLeftovers(decoded, balances);
97
+ super.applyBalanceChanges(balances, decoded);
97
98
  }
98
99
  }
99
100
  }
@@ -100,21 +100,23 @@ class StakingRewardsAdapterContract extends import_AbstractAdapter.AbstractAdapt
100
100
  referral: this.#referral
101
101
  };
102
102
  }
103
- decodeDiffLeftovers(decoded, balances) {
103
+ applyBalanceChanges(balances, decoded) {
104
104
  switch (decoded.functionName) {
105
105
  case "stakeDiff": {
106
106
  const [leftoverAmount] = decoded.args;
107
- return [{ tokenIn: this.stakingToken, leftoverAmount }];
107
+ this.setLeftover(balances, this.stakingToken, leftoverAmount);
108
+ break;
108
109
  }
109
110
  case "withdrawDiff": {
110
111
  const [leftoverAmount] = decoded.args;
111
- return [{ tokenIn: this.stakedPhantomToken, leftoverAmount }];
112
+ this.setLeftover(balances, this.stakedPhantomToken, leftoverAmount);
113
+ break;
112
114
  }
113
115
  // no accrued rewards on a freshly opened account
114
116
  case "getReward":
115
- return [];
117
+ break;
116
118
  default:
117
- return super.decodeDiffLeftovers(decoded, balances);
119
+ super.applyBalanceChanges(balances, decoded);
118
120
  }
119
121
  }
120
122
  }
@@ -82,14 +82,15 @@ class TraderJoeRouterAdapterContract extends import_AbstractAdapter.AbstractAdap
82
82
  }))
83
83
  };
84
84
  }
85
- decodeDiffLeftovers(decoded, balances) {
85
+ applyBalanceChanges(balances, decoded) {
86
86
  switch (decoded.functionName) {
87
87
  case "swapDiffTokensForTokens": {
88
88
  const [leftoverAmount, , path] = decoded.args;
89
- return [{ tokenIn: path.tokenPath[0], leftoverAmount }];
89
+ this.setLeftover(balances, path.tokenPath[0], leftoverAmount);
90
+ break;
90
91
  }
91
92
  default:
92
- return super.decodeDiffLeftovers(decoded, balances);
93
+ super.applyBalanceChanges(balances, decoded);
93
94
  }
94
95
  }
95
96
  }
@@ -93,14 +93,15 @@ class UniswapV2AdapterContract extends import_AbstractAdapter.AbstractAdapterCon
93
93
  classifyLegacyOperation(_parsed, transfers) {
94
94
  return { operation: "UniswapSwap", ...(0, import_transferHelpers.swapFromTransfers)(transfers) };
95
95
  }
96
- decodeDiffLeftovers(decoded, balances) {
96
+ applyBalanceChanges(balances, decoded) {
97
97
  switch (decoded.functionName) {
98
98
  case "swapDiffTokensForTokens": {
99
99
  const [leftoverAmount, , path] = decoded.args;
100
- return [{ tokenIn: path[0], leftoverAmount }];
100
+ this.setLeftover(balances, path[0], leftoverAmount);
101
+ break;
101
102
  }
102
103
  default:
103
- return super.decodeDiffLeftovers(decoded, balances);
104
+ super.applyBalanceChanges(balances, decoded);
104
105
  }
105
106
  }
106
107
  }
@@ -71,24 +71,21 @@ class UniswapV3AdapterContract extends import_AbstractAdapter.AbstractAdapterCon
71
71
  }))
72
72
  };
73
73
  }
74
- decodeDiffLeftovers(decoded, balances) {
74
+ applyBalanceChanges(balances, decoded) {
75
75
  switch (decoded.functionName) {
76
76
  case "exactDiffInputSingle": {
77
77
  const [params] = decoded.args;
78
- return [
79
- {
80
- tokenIn: params.tokenIn,
81
- leftoverAmount: params.leftoverAmount
82
- }
83
- ];
78
+ this.setLeftover(balances, params.tokenIn, params.leftoverAmount);
79
+ break;
84
80
  }
85
81
  case "exactDiffInput": {
86
82
  const [params] = decoded.args;
87
83
  const tokenIn = `0x${params.path.replace("0x", "").slice(0, 40)}`;
88
- return [{ tokenIn, leftoverAmount: params.leftoverAmount }];
84
+ this.setLeftover(balances, tokenIn, params.leftoverAmount);
85
+ break;
89
86
  }
90
87
  default:
91
- return super.decodeDiffLeftovers(decoded, balances);
88
+ super.applyBalanceChanges(balances, decoded);
92
89
  }
93
90
  }
94
91
  stringifyFunctionParams(params) {
@@ -81,19 +81,19 @@ class UniswapV4AdapterContract extends import_AbstractAdapter.AbstractAdapterCon
81
81
  classifyLegacyOperation(_parsed, transfers) {
82
82
  return { operation: "UniswapSwap", ...(0, import_transferHelpers.swapFromTransfers)(transfers) };
83
83
  }
84
- decodeDiffLeftovers(decoded, balances) {
84
+ applyBalanceChanges(balances, decoded) {
85
85
  switch (decoded.functionName) {
86
86
  case "swapExactInputSingleDiff": {
87
87
  const [poolKey, zeroForOne, leftoverAmount] = decoded.args;
88
- return [
89
- {
90
- tokenIn: zeroForOne ? poolKey.token0 : poolKey.token1,
91
- leftoverAmount
92
- }
93
- ];
88
+ this.setLeftover(
89
+ balances,
90
+ zeroForOne ? poolKey.token0 : poolKey.token1,
91
+ leftoverAmount
92
+ );
93
+ break;
94
94
  }
95
95
  default:
96
- return super.decodeDiffLeftovers(decoded, balances);
96
+ super.applyBalanceChanges(balances, decoded);
97
97
  }
98
98
  }
99
99
  }
@@ -70,18 +70,20 @@ class UpshiftVaultAdapterContract extends import_AbstractAdapter.AbstractAdapter
70
70
  stakedPhantomToken: this.#stakedPhantomToken ? this.labelAddress(this.#stakedPhantomToken) : void 0
71
71
  };
72
72
  }
73
- decodeDiffLeftovers(decoded, balances) {
73
+ applyBalanceChanges(balances, decoded) {
74
74
  switch (decoded.functionName) {
75
75
  case "depositDiff": {
76
76
  const [leftoverAmount] = decoded.args;
77
- return [{ tokenIn: this.asset, leftoverAmount }];
77
+ this.setLeftover(balances, this.asset, leftoverAmount);
78
+ break;
78
79
  }
79
80
  case "redeemDiff": {
80
81
  const [leftoverAmount] = decoded.args;
81
- return [{ tokenIn: this.vault, leftoverAmount }];
82
+ this.setLeftover(balances, this.vault, leftoverAmount);
83
+ break;
82
84
  }
83
85
  default:
84
- return super.decodeDiffLeftovers(decoded, balances);
86
+ super.applyBalanceChanges(balances, decoded);
85
87
  }
86
88
  }
87
89
  }
@@ -74,14 +74,15 @@ class VelodromeV2RouterAdapterContract extends import_AbstractAdapter.AbstractAd
74
74
  }))
75
75
  };
76
76
  }
77
- decodeDiffLeftovers(decoded, balances) {
77
+ applyBalanceChanges(balances, decoded) {
78
78
  switch (decoded.functionName) {
79
79
  case "swapDiffTokensForTokens": {
80
80
  const [leftoverAmount, , routes] = decoded.args;
81
- return [{ tokenIn: routes[0].from, leftoverAmount }];
81
+ this.setLeftover(balances, routes[0].from, leftoverAmount);
82
+ break;
82
83
  }
83
84
  default:
84
- return super.decodeDiffLeftovers(decoded, balances);
85
+ super.applyBalanceChanges(balances, decoded);
85
86
  }
86
87
  }
87
88
  }
@@ -65,19 +65,21 @@ class WstETHV1AdapterContract extends import_AbstractAdapter.AbstractAdapterCont
65
65
  }
66
66
  return super.classifyLegacyOperation(parsed, transfers);
67
67
  }
68
- decodeDiffLeftovers(decoded, balances) {
68
+ applyBalanceChanges(balances, decoded) {
69
69
  switch (decoded.functionName) {
70
70
  case "wrapDiff": {
71
71
  const [leftoverAmount] = decoded.args;
72
- return [{ tokenIn: this.stETH, leftoverAmount }];
72
+ this.setLeftover(balances, this.stETH, leftoverAmount);
73
+ break;
73
74
  }
74
75
  // wstETH is the adapter's target contract
75
76
  case "unwrapDiff": {
76
77
  const [leftoverAmount] = decoded.args;
77
- return [{ tokenIn: this.targetContract, leftoverAmount }];
78
+ this.setLeftover(balances, this.targetContract, leftoverAmount);
79
+ break;
78
80
  }
79
81
  default:
80
- return super.decodeDiffLeftovers(decoded, balances);
82
+ super.applyBalanceChanges(balances, decoded);
81
83
  }
82
84
  }
83
85
  }
@@ -104,8 +104,10 @@ class AbstractAdapterContract extends BaseContract {
104
104
  }
105
105
  }
106
106
  /**
107
- * Applies the balance changes implied by a router-generated diff-style
108
- * adapter call to a map of credit-account token balances.
107
+ * Applies the balance changes implied by an adapter call to a map of
108
+ * credit-account token balances. Handles both router-generated diff-style
109
+ * calls and exact-input calls (e.g. those emitted by the withdrawal
110
+ * compressor).
109
111
  *
110
112
  * @param balances - Token balances before the call. Mutated in place.
111
113
  * @param calldata - Raw ABI-encoded adapter calldata.
@@ -122,23 +124,43 @@ class AbstractAdapterContract extends BaseContract {
122
124
  { cause: e }
123
125
  );
124
126
  }
125
- const leftovers = this.decodeDiffLeftovers(decoded, balances);
126
- for (const { tokenIn, leftoverAmount } of leftovers) {
127
- balances.upsert(tokenIn, leftoverAmount);
128
- }
127
+ this.applyBalanceChanges(balances, decoded);
129
128
  }
130
129
  /**
131
- * Resolves which tokens the diff-style call spends down to which leftovers.
130
+ * Applies the balance changes of a decoded adapter call to the running
131
+ * balances, mutating them in place. Overrides should express changes via
132
+ * {@link setLeftover} (diff-style calls) and {@link spendExact}
133
+ * (exact-input calls), and should resolve all tokens/amounts before the
134
+ * first write so a throw never leaves balances partially mutated.
132
135
  *
136
+ * @param _balances - Token balances before the call. Mutated in place.
133
137
  * @param decoded - The viem-decoded adapter call
134
- * @param _balances - Token balances before the call
135
138
  * @throws When the adapter (or the specific function) has no balance-changes support
136
139
  */
137
- decodeDiffLeftovers(decoded, _balances) {
140
+ applyBalanceChanges(_balances, decoded) {
138
141
  throw new Error(
139
142
  `previewBalanceChanges is not supported for ${decoded.functionName} on ${this.contractType} adapter at ${this.address}`
140
143
  );
141
144
  }
145
+ /**
146
+ * Diff-call semantics of a diff-style adapter call: the call spends the
147
+ * consumed token down to the exact `leftoverAmount` encoded in its
148
+ * calldata, so the post-call balance of `tokenIn` is `leftoverAmount`
149
+ * regardless of the actual amount spent.
150
+ */
151
+ setLeftover(balances, tokenIn, leftoverAmount) {
152
+ balances.upsert(tokenIn, leftoverAmount);
153
+ }
154
+ /**
155
+ * Exact-input call semantics: spends exactly `amount` of `tokenIn` from
156
+ * the running balance, clamping at zero. Used for non-diff adapter calls
157
+ * (e.g. those generated by the withdrawal compressor) whose spent amount
158
+ * is present in calldata.
159
+ */
160
+ spendExact(balances, tokenIn, amount) {
161
+ const balance = balances.getOrZero(tokenIn);
162
+ balances.upsert(tokenIn, balance > amount ? balance - amount : 0n);
163
+ }
142
164
  /**
143
165
  * Classifies an adapter call into a {@link LegacyAdapterOperation} using the
144
166
  * parsed call and credit-account transfer deltas.
@@ -5,23 +5,26 @@ class AbstractCurveAdapterContract extends AbstractAdapterContract {
5
5
  classifyLegacyOperation(parsed, transfers) {
6
6
  return classifyCurveOperation(parsed.functionName, transfers) ?? super.classifyLegacyOperation(parsed, transfers);
7
7
  }
8
- decodeDiffLeftovers(decoded, balances) {
8
+ applyBalanceChanges(balances, decoded) {
9
9
  const { functionName, args } = decoded;
10
10
  switch (functionName) {
11
11
  case "exchange_diff": {
12
12
  const [i, , leftoverAmount] = args;
13
- return [{ tokenIn: this.curveCoin(i), leftoverAmount }];
13
+ this.setLeftover(balances, this.curveCoin(i), leftoverAmount);
14
+ break;
14
15
  }
15
16
  case "add_diff_liquidity_one_coin": {
16
17
  const [leftoverAmount, i] = args;
17
- return [{ tokenIn: this.curveCoin(i), leftoverAmount }];
18
+ this.setLeftover(balances, this.curveCoin(i), leftoverAmount);
19
+ break;
18
20
  }
19
21
  case "remove_diff_liquidity_one_coin": {
20
22
  const [leftoverAmount] = args;
21
- return [{ tokenIn: this.lpToken, leftoverAmount }];
23
+ this.setLeftover(balances, this.lpToken, leftoverAmount);
24
+ break;
22
25
  }
23
26
  default:
24
- return super.decodeDiffLeftovers(decoded, balances);
27
+ super.applyBalanceChanges(balances, decoded);
25
28
  }
26
29
  }
27
30
  /**
@@ -71,23 +71,25 @@ class BalancerV3RouterAdapterContract extends AbstractAdapterContract {
71
71
  }))
72
72
  };
73
73
  }
74
- decodeDiffLeftovers(decoded, balances) {
74
+ applyBalanceChanges(balances, decoded) {
75
75
  switch (decoded.functionName) {
76
76
  case "swapSingleTokenDiffIn": {
77
77
  const [, tokenIn, , leftoverAmount] = decoded.args;
78
- return [{ tokenIn, leftoverAmount }];
78
+ this.setLeftover(balances, tokenIn, leftoverAmount);
79
+ break;
79
80
  }
80
81
  // BPT (pool token) is spent down to the leftover
81
82
  case "removeLiquiditySingleTokenDiff": {
82
83
  const [pool, leftoverAmount] = decoded.args;
83
- return [{ tokenIn: pool, leftoverAmount }];
84
+ this.setLeftover(balances, pool, leftoverAmount);
85
+ break;
84
86
  }
85
87
  case "addLiquidityUnbalancedDiff":
86
88
  throw new Error(
87
89
  `previewBalanceChanges cannot resolve pool tokens for addLiquidityUnbalancedDiff on ${this.contractType} adapter at ${this.address}`
88
90
  );
89
91
  default:
90
- return super.decodeDiffLeftovers(decoded, balances);
92
+ super.applyBalanceChanges(balances, decoded);
91
93
  }
92
94
  }
93
95
  }
@@ -34,19 +34,21 @@ class BalancerV3WrapperAdapterContract extends AbstractAdapterContract {
34
34
  balancerPoolToken: this.#balancerPoolToken ? this.labelAddress(this.#balancerPoolToken) : void 0
35
35
  };
36
36
  }
37
- decodeDiffLeftovers(decoded, balances) {
37
+ applyBalanceChanges(balances, decoded) {
38
38
  switch (decoded.functionName) {
39
39
  // mint spends the pool token, burn spends the wrapper (target contract)
40
40
  case "mintDiff": {
41
41
  const [leftoverAmount] = decoded.args;
42
- return [{ tokenIn: this.balancerPoolToken, leftoverAmount }];
42
+ this.setLeftover(balances, this.balancerPoolToken, leftoverAmount);
43
+ break;
43
44
  }
44
45
  case "burnDiff": {
45
46
  const [leftoverAmount] = decoded.args;
46
- return [{ tokenIn: this.targetContract, leftoverAmount }];
47
+ this.setLeftover(balances, this.targetContract, leftoverAmount);
48
+ break;
47
49
  }
48
50
  default:
49
- return super.decodeDiffLeftovers(decoded, balances);
51
+ super.applyBalanceChanges(balances, decoded);
50
52
  }
51
53
  }
52
54
  }
@@ -47,24 +47,21 @@ class CamelotV3AdapterContract extends AbstractAdapterContract {
47
47
  }))
48
48
  };
49
49
  }
50
- decodeDiffLeftovers(decoded, balances) {
50
+ applyBalanceChanges(balances, decoded) {
51
51
  switch (decoded.functionName) {
52
52
  case "exactDiffInputSingle": {
53
53
  const [params] = decoded.args;
54
- return [
55
- {
56
- tokenIn: params.tokenIn,
57
- leftoverAmount: params.leftoverAmount
58
- }
59
- ];
54
+ this.setLeftover(balances, params.tokenIn, params.leftoverAmount);
55
+ break;
60
56
  }
61
57
  case "exactDiffInput": {
62
58
  const [params] = decoded.args;
63
59
  const tokenIn = `0x${params.path.replace("0x", "").slice(0, 40)}`;
64
- return [{ tokenIn, leftoverAmount: params.leftoverAmount }];
60
+ this.setLeftover(balances, tokenIn, params.leftoverAmount);
61
+ break;
65
62
  }
66
63
  default:
67
- return super.decodeDiffLeftovers(decoded, balances);
64
+ super.applyBalanceChanges(balances, decoded);
68
65
  }
69
66
  }
70
67
  }
@@ -116,22 +116,24 @@ class ConvexV1BaseRewardPoolAdapterContract extends AbstractAdapterContract {
116
116
  withdrawAmount: swap.toAmount
117
117
  };
118
118
  }
119
- decodeDiffLeftovers(decoded, balances) {
119
+ applyBalanceChanges(balances, decoded) {
120
120
  switch (decoded.functionName) {
121
121
  case "stakeDiff": {
122
122
  const [leftoverAmount] = decoded.args;
123
- return [{ tokenIn: this.stakingToken, leftoverAmount }];
123
+ this.setLeftover(balances, this.stakingToken, leftoverAmount);
124
+ break;
124
125
  }
125
126
  case "withdrawDiff":
126
127
  case "withdrawDiffAndUnwrap": {
127
128
  const [leftoverAmount] = decoded.args;
128
- return [{ tokenIn: this.stakedPhantomToken, leftoverAmount }];
129
+ this.setLeftover(balances, this.stakedPhantomToken, leftoverAmount);
130
+ break;
129
131
  }
130
132
  // no accrued rewards on a freshly opened account
131
133
  case "getReward":
132
- return [];
134
+ break;
133
135
  default:
134
- return super.decodeDiffLeftovers(decoded, balances);
136
+ super.applyBalanceChanges(balances, decoded);
135
137
  }
136
138
  }
137
139
  }
@@ -83,21 +83,23 @@ class ConvexV1BoosterAdapterContract extends AbstractAdapterContract {
83
83
  }
84
84
  return super.classifyLegacyOperation(parsed, transfers);
85
85
  }
86
- decodeDiffLeftovers(decoded, balances) {
86
+ applyBalanceChanges(balances, decoded) {
87
87
  switch (decoded.functionName) {
88
88
  // deposit spends the curve LP token, withdraw spends the convex token
89
89
  case "depositDiff": {
90
90
  const [pid, leftoverAmount] = decoded.args;
91
91
  const pool = this.#mustFindPool(Number(pid));
92
- return [{ tokenIn: pool.curveToken, leftoverAmount }];
92
+ this.setLeftover(balances, pool.curveToken, leftoverAmount);
93
+ break;
93
94
  }
94
95
  case "withdrawDiff": {
95
96
  const [pid, leftoverAmount] = decoded.args;
96
97
  const pool = this.#mustFindPool(Number(pid));
97
- return [{ tokenIn: pool.convexToken, leftoverAmount }];
98
+ this.setLeftover(balances, pool.convexToken, leftoverAmount);
99
+ break;
98
100
  }
99
101
  default:
100
- return super.decodeDiffLeftovers(decoded, balances);
102
+ super.applyBalanceChanges(balances, decoded);
101
103
  }
102
104
  }
103
105
  #mustFindPool(pid) {
@@ -55,18 +55,20 @@ class DaiUsdsAdapterContract extends AbstractAdapterContract {
55
55
  }
56
56
  return super.classifyLegacyOperation(parsed, transfers);
57
57
  }
58
- decodeDiffLeftovers(decoded, balances) {
58
+ applyBalanceChanges(balances, decoded) {
59
59
  switch (decoded.functionName) {
60
60
  case "daiToUsdsDiff": {
61
61
  const [leftoverAmount] = decoded.args;
62
- return [{ tokenIn: this.dai, leftoverAmount }];
62
+ this.setLeftover(balances, this.dai, leftoverAmount);
63
+ break;
63
64
  }
64
65
  case "usdsToDaiDiff": {
65
66
  const [leftoverAmount] = decoded.args;
66
- return [{ tokenIn: this.usds, leftoverAmount }];
67
+ this.setLeftover(balances, this.usds, leftoverAmount);
68
+ break;
67
69
  }
68
70
  default:
69
- return super.decodeDiffLeftovers(decoded, balances);
71
+ super.applyBalanceChanges(balances, decoded);
70
72
  }
71
73
  }
72
74
  }
@@ -81,18 +81,27 @@ class ERC4626AdapterContract extends AbstractAdapterContract {
81
81
  }
82
82
  return super.classifyLegacyOperation(parsed, transfers);
83
83
  }
84
- decodeDiffLeftovers(decoded, balances) {
84
+ applyBalanceChanges(balances, decoded) {
85
85
  switch (decoded.functionName) {
86
86
  case "depositDiff": {
87
87
  const [leftoverAmount] = decoded.args;
88
- return [{ tokenIn: this.asset, leftoverAmount }];
88
+ this.setLeftover(balances, this.asset, leftoverAmount);
89
+ break;
89
90
  }
90
91
  case "redeemDiff": {
91
92
  const [leftoverAmount] = decoded.args;
92
- return [{ tokenIn: this.share, leftoverAmount }];
93
+ this.setLeftover(balances, this.share, leftoverAmount);
94
+ break;
93
95
  }
96
+ case "redeem": {
97
+ const [shares] = decoded.args;
98
+ this.spendExact(balances, this.share, shares);
99
+ break;
100
+ }
101
+ // `withdraw`/`deposit`/`mint` stay unsupported: they are not emitted
102
+ // by the router (which uses diff variants) or the withdrawal compressor
94
103
  default:
95
- return super.decodeDiffLeftovers(decoded, balances);
104
+ super.applyBalanceChanges(balances, decoded);
96
105
  }
97
106
  }
98
107
  }