@@ -428,7 +428,7 @@ abstract contract AbstractARM is OwnableOperable, ERC20Upgradeable, ReentrancyGu
428428 amountOut = convertedAmountIn * config.buyPrice / PRICE_SCALE;
429429 }
430430
431- _validateAndConsumeSwapLiquidity (config, isBuySide, outToken, amountOut);
431+ _validateAndConsumeSwapLiquidity (config, isBuySide, outToken, amountIn, amountOut);
432432
433433 // Transfer the input tokens from the caller to this ARM contract
434434 inToken.transferFrom (msg .sender , address (this ), amountIn);
@@ -468,7 +468,7 @@ abstract contract AbstractARM is OwnableOperable, ERC20Upgradeable, ReentrancyGu
468468 amountIn = convertedAmountOut * PRICE_SCALE / config.buyPrice + 3 ;
469469 }
470470
471- _validateAndConsumeSwapLiquidity (config, isBuySide, outToken, amountOut);
471+ _validateAndConsumeSwapLiquidity (config, isBuySide, outToken, amountIn, amountOut);
472472
473473 // Transfer the input tokens from the caller to this ARM contract
474474 inToken.transferFrom (msg .sender , address (this ), amountIn);
@@ -518,16 +518,18 @@ abstract contract AbstractARM is OwnableOperable, ERC20Upgradeable, ReentrancyGu
518518 /// @dev Validate swap reserves and consume the per-base liquidity limit.
519519 /// @param isBuySide True when the ARM buys base asset and pays out liquidity asset.
520520 /// @param outToken Swap output token address.
521+ /// @param amountIn Swap input token amount.
521522 /// @param amountOut Swap output token amount.
522523 function _validateAndConsumeSwapLiquidity (
523524 BaseAssetConfig storage config ,
524525 bool isBuySide ,
525526 IERC20 outToken ,
527+ uint256 amountIn ,
526528 uint256 amountOut
527529 ) private {
528530 uint256 remaining;
529531 if (isBuySide) {
530- _accrueSwapFee (config.buyPrice, config.crossPrice , amountOut);
532+ _accrueSwapFee (config, amountIn , amountOut);
531533 remaining = config.buyLiquidityRemaining;
532534 if (amountOut > remaining) revert InsufficientLiquidity ();
533535 unchecked {
@@ -581,13 +583,14 @@ abstract contract AbstractARM is OwnableOperable, ERC20Upgradeable, ReentrancyGu
581583 return baseDecimals > liquidityAssetDecimals ? amount * 1e12 : amount / 1e12 ;
582584 }
583585
584- /// @dev Accrue fees on discounted buy-side swaps using the recognized NAV gain .
585- /// @param buyPrice Price the ARM paid for the base asset .
586- /// @param crossPrice Price used to value the base asset in totalAssets() .
586+ /// @dev Accrue fees on buy-side swaps using the gain realized from the settled input and output amounts .
587+ /// @param config Base asset configuration used to value the input received by the ARM .
588+ /// @param amountIn Base asset amount received by the ARM .
587589 /// @param amountOut Liquidity asset amount paid out by the ARM.
588- function _accrueSwapFee (uint256 buyPrice , uint256 crossPrice , uint256 amountOut ) internal {
589- uint256 feeMultiplier = (crossPrice - buyPrice) * uint256 (fee) * PRICE_SCALE / (buyPrice * FEE_SCALE);
590- feesAccrued = SafeCast.toUint128 (feesAccrued + amountOut * feeMultiplier / PRICE_SCALE);
590+ function _accrueSwapFee (BaseAssetConfig storage config , uint256 amountIn , uint256 amountOut ) internal {
591+ uint256 realizedAssets = _convertToAssets (config, amountIn) * config.crossPrice / PRICE_SCALE;
592+ uint256 gain = realizedAssets > amountOut ? realizedAssets - amountOut : 0 ;
593+ feesAccrued = SafeCast.toUint128 (feesAccrued + gain * uint256 (fee) / FEE_SCALE);
591594 }
592595
593596 ////////////////////////////////////////////////////
0 commit comments