@@ -23,6 +23,7 @@ import {FeeMath} from "../libraries/FeeMath.sol";
23
23
import {LiquiditySaltLibrary} from "../libraries/LiquiditySaltLibrary.sol " ;
24
24
import {IBaseLiquidityManagement} from "../interfaces/IBaseLiquidityManagement.sol " ;
25
25
import {PositionLibrary} from "../libraries/Position.sol " ;
26
+ import {BalanceDeltaExtensionLibrary} from "../libraries/BalanceDeltaExtensionLibrary.sol " ;
26
27
27
28
import "forge-std/console2.sol " ;
28
29
@@ -38,6 +39,7 @@ contract BaseLiquidityManagement is IBaseLiquidityManagement, SafeCallback {
38
39
using SafeCast for uint256 ;
39
40
using LiquiditySaltLibrary for IHooks;
40
41
using PositionLibrary for IBaseLiquidityManagement.Position;
42
+ using BalanceDeltaExtensionLibrary for BalanceDelta;
41
43
42
44
mapping (address owner = > mapping (LiquidityRangeId rangeId => Position)) public positions;
43
45
@@ -106,7 +108,7 @@ contract BaseLiquidityManagement is IBaseLiquidityManagement, SafeCallback {
106
108
LiquidityRange memory range ,
107
109
uint256 liquidityToAdd ,
108
110
bytes memory hookData
109
- ) internal returns (BalanceDelta, BalanceDelta) {
111
+ ) internal returns (BalanceDelta callerDelta , BalanceDelta thisDelta ) {
110
112
// Note that the liquidityDelta includes totalFeesAccrued. The totalFeesAccrued is returned separately for accounting purposes.
111
113
(BalanceDelta liquidityDelta , BalanceDelta totalFeesAccrued ) =
112
114
_modifyLiquidity (owner, range, liquidityToAdd.toInt256 (), hookData);
@@ -126,66 +128,37 @@ contract BaseLiquidityManagement is IBaseLiquidityManagement, SafeCallback {
126
128
position.liquidity
127
129
);
128
130
129
- console2.log (callerFeesAccrued.amount0 ());
130
- console2.log (callerFeesAccrued.amount1 ());
131
- console2.log ("totalFees " );
132
- console2.log (totalFeesAccrued.amount0 ());
133
- console2.log (totalFeesAccrued.amount1 ());
131
+ if (totalFeesAccrued == callerFeesAccrued) {
132
+ // when totalFeesAccrued == callerFeesAccrued, the caller is not sharing the range
133
+ // therefore, the caller is responsible for the entire liquidityDelta
134
+ callerDelta = liquidityDelta;
135
+ } else {
136
+ // the delta for increasing liquidity assuming that totalFeesAccrued was not applied
137
+ BalanceDelta principalDelta = liquidityDelta - totalFeesAccrued;
138
+
139
+ // outstanding deltas the caller is responsible for, after their fees are credited to the principal delta
140
+ callerDelta = principalDelta + callerFeesAccrued;
134
141
135
- // Calculate the accurate tokens owed to the caller.
136
- // If the totalFeesAccrued equals the callerFeesAccrued then the total owed to the caller is just the liquidityDelta.
137
- // If the totalFeesAccrued is greater than the callerFeesAccrued, we must account for the difference.
138
- // TODO: If totalFeesAccrued == callerFeesAccrued, I think we can just apply the entire delta onto the caller, even if this implicitly collects on behalf of another user in the same range.
139
- (int128 callerDelta0 , int128 callerDelta1 ) = totalFeesAccrued != callerFeesAccrued
140
- ? _calculateCallerDeltas (liquidityDelta, totalFeesAccrued, callerFeesAccrued)
141
- : (liquidityDelta.amount0 (), liquidityDelta.amount1 ());
142
+ // outstanding deltas this contract is responsible for, intuitively the contract is responsible for taking fees external to the caller's accrued fees
143
+ thisDelta = totalFeesAccrued - callerFeesAccrued;
144
+ }
142
145
143
146
// Update position storage, flushing the callerDelta value to tokensOwed first if necessary.
144
147
// If callerDelta > 0, then even after investing callerFeesAccrued, the caller still has some amount to collect that were not added into the position so they are accounted to tokensOwed and removed from the final callerDelta returned.
145
- uint128 tokensOwed0 = 0 ;
146
- uint128 tokensOwed1 = 0 ;
147
- (tokensOwed0, callerDelta0) = callerDelta0 > 0 ? (uint128 (callerDelta0), int128 (0 )) : (uint128 (0 ), callerDelta0);
148
- (tokensOwed1, callerDelta1) = callerDelta1 > 0 ? (uint128 (callerDelta1), int128 (0 )) : (uint128 (0 ), callerDelta1);
148
+ BalanceDelta tokensOwed;
149
+ if (callerDelta.amount0 () > 0 ) {
150
+ (tokensOwed, callerDelta, thisDelta) =
151
+ _moveCallerDeltaToTokensOwed (true , tokensOwed, callerDelta, thisDelta);
152
+ }
153
+
154
+ if (callerDelta.amount1 () > 0 ) {
155
+ (tokensOwed, callerDelta, thisDelta) =
156
+ _moveCallerDeltaToTokensOwed (false , tokensOwed, callerDelta, thisDelta);
157
+ }
149
158
150
- position.addTokensOwed (tokensOwed0, tokensOwed1 );
159
+ position.addTokensOwed (tokensOwed );
151
160
position.addLiquidity (liquidityToAdd);
152
161
position.updateFeeGrowthInside (feeGrowthInside0X128, feeGrowthInside1X128);
153
-
154
- // The delta owed or credited by this contract.
155
- // TODO @sauce check that if callerDelta == 0 (zerod out from above), then this line just credits the posm to takes on behalf of the caller
156
- int128 thisDelta0 = liquidityDelta.amount0 () - callerDelta0;
157
- int128 thisDelta1 = liquidityDelta.amount1 () - callerDelta1;
158
-
159
- return (toBalanceDelta (callerDelta0, callerDelta1), toBalanceDelta (thisDelta0, thisDelta1));
160
- }
161
-
162
- // Returns the delta paid/credited by/to the caller.
163
- function _calculateCallerDeltas (
164
- BalanceDelta liquidityDelta ,
165
- BalanceDelta totalFeesAccrued ,
166
- BalanceDelta callerFeesAccrued
167
- ) private pure returns (int128 callerDelta0 , int128 callerDelta1 ) {
168
- (int128 liquidityDelta0 , int128 liquidityDelta1 ) = (liquidityDelta.amount0 (), liquidityDelta.amount1 ());
169
- (int128 totalFeesAccrued0 , int128 totalFeesAccrued1 ) = (totalFeesAccrued.amount0 (), totalFeesAccrued.amount1 ());
170
- (int128 callerFeesAccrued0 , int128 callerFeesAccrued1 ) =
171
- (callerFeesAccrued.amount0 (), callerFeesAccrued.amount1 ());
172
-
173
- callerDelta0 = _calculateCallerDelta (liquidityDelta0, totalFeesAccrued0, callerFeesAccrued0);
174
- callerDelta1 = _calculateCallerDelta (liquidityDelta1, totalFeesAccrued1, callerFeesAccrued1);
175
- }
176
-
177
- function _calculateCallerDelta (int128 liquidityDelta , int128 totalFeesAccrued , int128 callerFeesAccrued )
178
- private
179
- pure
180
- returns (int128 callerDelta )
181
- {
182
- unchecked {
183
- // The principle delta owed/debited to the caller before any LP fees are deducted.
184
- int128 principleDelta = liquidityDelta - totalFeesAccrued;
185
- // The new caller delta is this principle delta plus the callerFeesAccrued which consists of
186
- // the custodied fees by posm and unclaimed fees from the modifyLiq call.
187
- callerDelta = principleDelta + callerFeesAccrued;
188
- }
189
162
}
190
163
191
164
function _increaseLiquidityAndZeroOut (
@@ -230,6 +203,26 @@ contract BaseLiquidityManagement is IBaseLiquidityManagement, SafeCallback {
230
203
if (delta1 < 0 ) currency1.settle (manager, address (this ), uint256 (int256 (- delta1)), true );
231
204
}
232
205
206
+ function _moveCallerDeltaToTokensOwed (
207
+ bool useAmount0 ,
208
+ BalanceDelta tokensOwed ,
209
+ BalanceDelta callerDelta ,
210
+ BalanceDelta thisDelta
211
+ ) private returns (BalanceDelta, BalanceDelta, BalanceDelta) {
212
+ // credit the excess tokens to the position's tokensOwed
213
+ tokensOwed =
214
+ useAmount0 ? tokensOwed.setAmount0 (callerDelta.amount0 ()) : tokensOwed.setAmount1 (callerDelta.amount1 ());
215
+
216
+ // this contract is responsible for custodying the excess tokens
217
+ thisDelta =
218
+ useAmount0 ? thisDelta.addAmount0 (callerDelta.amount0 ()) : thisDelta.addAmount1 (callerDelta.amount1 ());
219
+
220
+ // the caller is not expected to collect the excess tokens
221
+ callerDelta = useAmount0 ? callerDelta.setAmount0 (0 ) : callerDelta.setAmount1 (0 );
222
+
223
+ return (tokensOwed, callerDelta, thisDelta);
224
+ }
225
+
233
226
function _lockAndIncreaseLiquidity (
234
227
address owner ,
235
228
LiquidityRange memory range ,
0 commit comments