@@ -7,6 +7,7 @@ import {Deployers} from "lib/v4-periphery/lib/v4-core/test/utils/Deployers.sol";
77import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol " ;
88import {LPVault} from "src/LPVault.sol " ;
99import {LPVaultHarness} from "test/harness/LPVaultHarness.sol " ;
10+ import {IPoolManager} from "v4-core/interfaces/IPoolManager.sol " ;
1011import {ImmutableState} from "v4-periphery/src/base/ImmutableState.sol " ;
1112import {PoolKey} from "v4-core/types/PoolKey.sol " ;
1213import {Currency} from "v4-core/types/Currency.sol " ;
@@ -1370,26 +1371,26 @@ contract CollectFees is LPVaultTest {
13701371 // Deposit and get shares
13711372 (uint256 _shares ,,) = _deposit (_depositor, _amount0, _amount1);
13721373
1373- // Generate fees via swaps (but don't collect yet)
1374- BalanceDelta _delta0 = _performSwap (true , _boundSwapAbs (_swapAbs0));
1375- BalanceDelta _delta1 = _performSwap (false , _boundSwapAbs (_swapAbs1));
1376-
1377- uint256 _expectedFee0 = uint256 (- int256 (_delta0.amount0 ())) * DEFAULT_FEE / FEE_DENOMINATOR;
1378- uint256 _expectedFee1 = uint256 (- int256 (_delta1.amount1 ())) * DEFAULT_FEE / FEE_DENOMINATOR;
1374+ // Generate fees via swaps (but don't collect yet).
1375+ _performSwap (true , _boundSwapAbs (_swapAbs0));
1376+ _performSwap (false , _boundSwapAbs (_swapAbs1));
13791377
1380- // Transfer shares BEFORE collecting fees
1378+ // Transfer shares BEFORE collecting fees. This syncs fees and attributes accrued fees
1379+ // to the sender before balances move.
13811380 vm.prank (_depositor);
13821381 vault.transfer (_recipient, _shares);
13831382
1383+ (,, uint256 _expectedClaim0 , uint256 _expectedClaim1 ) = vault.userFees (_depositor);
1384+
13841385 // Now collect fees - they should be attributed to depositor (original holder)
13851386 vault.collectFees ();
13861387
13871388 // Depositor should be able to claim fees that accrued while they held shares
13881389 vm.prank (_depositor);
13891390 (uint256 _claimed0 , uint256 _claimed1 ) = vault.claim (_depositor);
13901391
1391- assertApproxEqRel (_claimed0, _expectedFee0, FEE_TOLERANCE );
1392- assertApproxEqRel (_claimed1, _expectedFee1, FEE_TOLERANCE );
1392+ assertEq (_claimed0, _expectedClaim0 );
1393+ assertEq (_claimed1, _expectedClaim1 );
13931394
13941395 // Recipient should have no fees (they got shares after fees accrued)
13951396 vm.prank (_recipient);
@@ -1411,20 +1412,23 @@ contract CollectFees is LPVaultTest {
14111412 // Note: This is a bit tricky since we need fees in the pool before our position exists
14121413 // In practice, this tests that checkpoints are initialized correctly on first deposit
14131414 _deposit (_depositor, _amount0, _amount1);
1415+ uint256 _balance = vault.balanceOf (_depositor);
1416+ uint256 _globalIndex0Before = vault.globalFeeIndex0Scaled ();
14141417
14151418 // Now generate fees (vault has liquidity)
1416- BalanceDelta _delta = _performSwap (true , _boundSwapAbs (_swapAbs0));
1417- uint256 _expectedFee0 = uint256 (- int256 (_delta.amount0 ())) * DEFAULT_FEE / FEE_DENOMINATOR;
1419+ _performSwap (true , _boundSwapAbs (_swapAbs0));
14181420
14191421 // Collect fees
14201422 vault.collectFees ();
1423+ uint256 _globalIndex0After = vault.globalFeeIndex0Scaled ();
1424+ uint256 _expectedClaim0 = _expectedAccrued (_balance, _globalIndex0After - _globalIndex0Before);
14211425
14221426 // Claim fees - should only get fees from after we deposited
14231427 vm.prank (_depositor);
14241428 (uint256 _claimed0 ,) = vault.claim (_depositor);
14251429
1426- // Should have fees from the swap
1427- assertApproxEqRel (_claimed0, _expectedFee0, FEE_TOLERANCE );
1430+ // Should only include fees accrued after the depositor held shares.
1431+ assertEq (_claimed0, _expectedClaim0 );
14281432 }
14291433
14301434 /// @notice Tests that fee indexes update on transfer even without collecting fees.
0 commit comments