From 0f94d9d59aa98e1e77743e31b15e01889db59bf1 Mon Sep 17 00:00:00 2001 From: mejango Date: Sat, 18 Jan 2025 19:23:32 -0300 Subject: [PATCH 1/4] fee always from --- src/JBERC20.sol | 8 +++ src/JBMultiTerminal.sol | 20 +++---- src/libraries/JBFees.sol | 15 ++--- test/TestAccessToFunds.sol | 56 ++++++++----------- test/TestCashOut.sol | 4 +- test/TestCashOutHooks.sol | 7 +-- test/TestFees.sol | 17 ++---- test/TestMultipleAccessLimits.sol | 10 ++-- test/TestSplits.sol | 2 +- .../JBMultiTerminal/TestAddToBalanceOf.sol | 7 +-- .../JBMultiTerminal/TestCashOutTokensOf.sol | 4 +- .../JBMultiTerminal/TestExecutePayout.sol | 12 ++-- .../JBMultiTerminal/TestSendPayoutsOf.sol | 4 +- .../JBMultiTerminal/TestUseAllowanceOf.sol | 8 +-- 14 files changed, 81 insertions(+), 93 deletions(-) diff --git a/src/JBERC20.sol b/src/JBERC20.sol index b697cb39c..6248c1175 100644 --- a/src/JBERC20.sol +++ b/src/JBERC20.sol @@ -43,6 +43,14 @@ contract JBERC20 is ERC20Votes, ERC20Permit, Ownable, IJBToken { return super.balanceOf(account); } +<<<<<<< Updated upstream +======= + /// @notice This token can only be added to a project when its created by the `JBTokens` contract. + function canBeAddedTo(uint256) external pure override returns (bool) { + return false; + } + +>>>>>>> Stashed changes /// @notice The number of decimals used for this token's fixed point accounting. /// @return The number of decimals. function decimals() public view override(ERC20, IJBToken) returns (uint8) { diff --git a/src/JBMultiTerminal.sol b/src/JBMultiTerminal.sol index 090c54c35..0d2391ffd 100644 --- a/src/JBMultiTerminal.sol +++ b/src/JBMultiTerminal.sol @@ -552,7 +552,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { // This payout is eligible for a fee since the funds are leaving this contract and the split hook isn't a // feeless address. if (!_isFeeless(address(split.hook))) { - netPayoutAmount -= JBFees.feeAmountIn({amount: amount, feePercent: FEE}); + netPayoutAmount -= JBFees.feeAmountFrom({amountBeforeFee: amount, feePercent: FEE}); } // Create the context to send to the split hook. @@ -585,7 +585,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { // This payout is eligible for a fee if the funds are leaving this contract and the receiving terminal isn't // a feelss address. if (terminal != this && !_isFeeless(address(terminal))) { - netPayoutAmount -= JBFees.feeAmountIn({amount: amount, feePercent: FEE}); + netPayoutAmount -= JBFees.feeAmountFrom({amountBeforeFee: amount, feePercent: FEE}); } // Send the `projectId` in the metadata as a referral. @@ -622,7 +622,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { // This payout is eligible for a fee since the funds are leaving this contract and the recipient isn't a // feeless address. if (!_isFeeless(recipient)) { - netPayoutAmount -= JBFees.feeAmountIn({amount: amount, feePercent: FEE}); + netPayoutAmount -= JBFees.feeAmountFrom({amountBeforeFee: amount, feePercent: FEE}); } // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the @@ -830,7 +830,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { _processFee({ projectId: projectId, token: token, - amount: JBFees.feeAmountIn({amount: heldFee.amount, feePercent: FEE}), + amount: JBFees.feeAmountFrom({amountBeforeFee: heldFee.amount, feePercent: FEE}), beneficiary: heldFee.beneficiary, feeTerminal: feeTerminal, wasHeld: true @@ -1129,7 +1129,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { if (!_isFeeless(beneficiary) && cashOutTaxRate != 0) { amountEligibleForFees += reclaimAmount; // Subtract the fee for the reclaimed amount. - reclaimAmount -= JBFees.feeAmountIn({amount: reclaimAmount, feePercent: FEE}); + reclaimAmount -= JBFees.feeAmountFrom({amountBeforeFee: reclaimAmount, feePercent: FEE}); } // Subtract the fee from the reclaim amount. @@ -1401,7 +1401,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { // Get the fee for the specified amount. uint256 specificationAmountFee = _isFeeless(address(specification.hook)) ? 0 - : JBFees.feeAmountIn({amount: specification.amount, feePercent: FEE}); + : JBFees.feeAmountFrom({amountBeforeFee: specification.amount, feePercent: FEE}); // Add the specification's amount to the amount eligible for fees. if (specificationAmountFee != 0) { @@ -1638,7 +1638,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { break; } else { // Notice here we take `feeAmountIn` on the stored `.amount`. - uint256 feeAmount = JBFees.feeAmountIn({amount: heldFee.amount, feePercent: FEE}); + uint256 feeAmount = JBFees.feeAmountFrom({amountBeforeFee: heldFee.amount, feePercent: FEE}); // Keep a reference to the amount from which the fee was taken. uint256 amountPaidOut = heldFee.amount - feeAmount; @@ -1653,7 +1653,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { newStartIndex = startIndex + i + 1; } else { // And here we overwrite with `feeAmountFrom` the `leftoverAmount` - feeAmount = JBFees.feeAmountFrom({amount: leftoverAmount, feePercent: FEE}); + feeAmount = JBFees.feeAmountIn({amountAfterFee: leftoverAmount, feePercent: FEE}); // Get fee from `leftoverAmount`. unchecked { @@ -1741,7 +1741,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { if (leftoverPayoutAmount != 0) { // Keep a reference to the fee for the leftover payout amount. uint256 fee = - _isFeeless(projectOwner) ? 0 : JBFees.feeAmountIn({amount: leftoverPayoutAmount, feePercent: FEE}); + _isFeeless(projectOwner) ? 0 : JBFees.feeAmountFrom({amountBeforeFee: leftoverPayoutAmount, feePercent: FEE}); // Transfer the amount to the project owner. try this.executeTransferTo({addr: projectOwner, token: token, amount: leftoverPayoutAmount - fee}) { @@ -1915,7 +1915,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { returns (uint256 feeAmount) { // Get a reference to the fee amount. - feeAmount = JBFees.feeAmountIn({amount: amount, feePercent: FEE}); + feeAmount = JBFees.feeAmountFrom({amountBeforeFee: amount, feePercent: FEE}); if (shouldHoldFees) { // Store the held fee. diff --git a/src/libraries/JBFees.sol b/src/libraries/JBFees.sol index 616b0f2f7..d64146a91 100644 --- a/src/libraries/JBFees.sol +++ b/src/libraries/JBFees.sol @@ -8,28 +8,25 @@ import {JBConstants} from "./../libraries/JBConstants.sol"; /// @notice Fee calculations. library JBFees { /// @notice Returns the amount of tokens to pay as a fee out of the specified `amount`. - /// @dev The resulting fee will be `feePercent` of the REMAINING `amount` after subtracting the fee, not the full - /// `amount`. - /// @param amount The amount that the fee is based on, as a fixed point number. + /// @param amountAfterFee The amount that the fee is based on, as a fixed point number. /// @param feePercent The fee percent, out of `JBConstants.MAX_FEE`. /// @return The amount of tokens to pay as a fee, as a fixed point number with the same number of decimals as the /// provided `amount`. - function feeAmountIn(uint256 amount, uint256 feePercent) internal pure returns (uint256) { + function feeAmountIn(uint256 amountAfterFee, uint256 feePercent) internal pure returns (uint256) { // The amount of tokens from the `amount` to pay as a fee. If reverse, the fee taken from a payout of // `amount`. - return amount - mulDiv(amount, JBConstants.MAX_FEE, feePercent + JBConstants.MAX_FEE); + return mulDiv(amountAfterFee, JBConstants.MAX_FEE, JBConstants.MAX_FEE - feePercent) - amountAfterFee; } /// @notice Returns the fee that would have been paid based on an `amount` which has already had the fee subtracted /// from it. - /// @dev The resulting fee will be `feePercent` of the full `amount`. - /// @param amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as + /// @param amountBeforeFee The amount that the fee is based on, as a fixed point number with the same amount of decimals as /// this terminal. /// @param feePercent The fee percent, out of `JBConstants.MAX_FEE`. /// @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal. - function feeAmountFrom(uint256 amount, uint256 feePercent) internal pure returns (uint256) { + function feeAmountFrom(uint256 amountBeforeFee, uint256 feePercent) internal pure returns (uint256) { // The amount of tokens from the `amount` to pay as a fee. If reverse, the fee taken from a payout of // `amount`. - return mulDiv(amount, feePercent, JBConstants.MAX_FEE); + return mulDiv(amountBeforeFee, feePercent, JBConstants.MAX_FEE); } } diff --git a/test/TestAccessToFunds.sol b/test/TestAccessToFunds.sol index 0628a60b2..7f49e0fb3 100644 --- a/test/TestAccessToFunds.sol +++ b/test/TestAccessToFunds.sol @@ -185,8 +185,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { }); // Make sure the beneficiary received the funds and that they are no longer in the terminal. - uint256 _beneficiaryNativeBalance = - mulDiv(_nativeCurrencySurplusAllowance, JBConstants.MAX_FEE, JBConstants.MAX_FEE + _terminal.FEE()); + uint256 _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -217,8 +216,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { }); // Make sure the project owner received the funds which were paid out. - uint256 _projectOwnerNativeBalance = - (_nativeCurrencyPayoutLimit * JBConstants.MAX_FEE) / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _projectOwnerNativeBalance = _nativeCurrencyPayoutLimit - _nativeCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; // Make sure the project owner received the full amount. assertEq(_projectOwner.balance, _projectOwnerNativeBalance); @@ -275,7 +273,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { // Calculate the fee from the cash out. uint256 _feeAmount = - _nativeReclaimAmount - _nativeReclaimAmount * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + _nativeReclaimAmount * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_beneficiary.balance, _beneficiaryNativeBalance + _nativeReclaimAmount - _feeAmount); // Make sure the fee was paid correctly. @@ -439,7 +437,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { if (_nativeCurrencySurplusAllowance + _nativeCurrencyPayoutLimit <= _nativePayAmount) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. _beneficiaryNativeBalance = - mulDiv(_nativeCurrencySurplusAllowance, JBConstants.MAX_FEE, JBConstants.MAX_FEE + _terminal.FEE()); + _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -496,7 +494,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { if (_nativeCurrencyPayoutLimit <= _nativePayAmount && _nativeCurrencyPayoutLimit != 0) { // Make sure the project owner received the payout. _projectOwnerNativeBalance = - (_nativeCurrencyPayoutLimit * JBConstants.MAX_FEE) / (_terminal.FEE() + JBConstants.MAX_FEE); + _nativeCurrencyPayoutLimit - _nativeCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_projectOwner.balance, _projectOwnerNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -558,8 +556,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { JBConstants.MAX_CASH_OUT_TAX_RATE ); // Calculate the fee from the cash out. - uint256 _feeAmount = _nativeReclaimAmount - - _nativeReclaimAmount * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _feeAmount = _nativeReclaimAmount * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_beneficiary.balance, _beneficiaryNativeBalance + _nativeReclaimAmount - _feeAmount); // Make sure the fee was paid correctly. @@ -726,8 +723,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { // Check the collected balance if one is expected. if (_nativeCurrencySurplusAllowance + _nativeCurrencyPayoutLimit <= _nativePayAmount) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. - _beneficiaryNativeBalance = - mulDiv(_nativeCurrencySurplusAllowance, JBConstants.MAX_FEE, JBConstants.MAX_FEE + _terminal.FEE()); + _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); // Make sure the fee stays in the terminal. assertEq( @@ -778,7 +774,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { if (_nativeCurrencyPayoutLimit <= _nativePayAmount && _nativeCurrencyPayoutLimit != 0) { // Make sure the project owner received the funds that were paid out. _projectOwnerNativeBalance = - (_nativeCurrencyPayoutLimit * JBConstants.MAX_FEE) / (_terminal.FEE() + JBConstants.MAX_FEE); + _nativeCurrencyPayoutLimit - _nativeCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_projectOwner.balance, _projectOwnerNativeBalance); // Make sure the fee stays in the terminal. assertEq( @@ -830,8 +826,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { ); // Calculate the fee from the cash out. - uint256 _feeAmount = _nativeReclaimAmount - - _nativeReclaimAmount * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _feeAmount = _nativeReclaimAmount * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_beneficiary.balance, _beneficiaryNativeBalance + _nativeReclaimAmount - _feeAmount); // Make sure the fee stays in the terminal. assertEq( @@ -984,8 +979,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { // Check the collected balance if one is expected. if (_nativeCurrencySurplusAllowance + _nativeCurrencyPayoutLimit <= _nativePayAmount) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. - _beneficiaryNativeBalance = - mulDiv(_nativeCurrencySurplusAllowance, JBConstants.MAX_FEE, JBConstants.MAX_FEE + _terminal.FEE()); + _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -1035,8 +1029,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { // Check the received payout if one is expected. if (_nativeCurrencyPayoutLimit <= _nativePayAmount && _nativeCurrencyPayoutLimit != 0) { // Make sure the project owner received the funds that were paid out. - _projectOwnerNativeBalance = - (_nativeCurrencyPayoutLimit * JBConstants.MAX_FEE) / (_terminal.FEE() + JBConstants.MAX_FEE); + _projectOwnerNativeBalance = _nativeCurrencyPayoutLimit - _nativeCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_projectOwner.balance, _projectOwnerNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -1092,8 +1085,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { JBConstants.MAX_CASH_OUT_TAX_RATE ); // Calculate the fee from the cash out. - uint256 _feeAmount = _nativeReclaimAmount - - _nativeReclaimAmount * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _feeAmount = _nativeReclaimAmount * _terminal.FEE() / JBConstants.MAX_FEE; // Make sure the beneficiary received tokens from the fee just paid. assertEq( @@ -1336,7 +1328,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { ) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. _beneficiaryNativeBalance = - mulDiv(_nativeCurrencySurplusAllowance, JBConstants.MAX_FEE, JBConstants.MAX_FEE + _terminal.FEE()); + _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -1406,8 +1398,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { + _toNative(_usdCurrencySurplusAllowance + _usdCurrencyPayoutLimit) <= _nativePayAmount ) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. - _beneficiaryNativeBalance += mulDiv( - _toNative(_usdCurrencySurplusAllowance), JBConstants.MAX_FEE, JBConstants.MAX_FEE + _terminal.FEE() + _beneficiaryNativeBalance += _toNative(_usdCurrencySurplusAllowance) - mulDiv( + _toNative(_usdCurrencySurplusAllowance), _terminal.FEE(), JBConstants.MAX_FEE ); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( @@ -1475,7 +1467,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { if (_nativeCurrencyPayoutLimit <= _nativePayAmount && _nativeCurrencyPayoutLimit != 0) { // Make sure the project owner received the funds that were paid out. _projectOwnerNativeBalance = - (_nativeCurrencyPayoutLimit * JBConstants.MAX_FEE) / (_terminal.FEE() + JBConstants.MAX_FEE); + _nativeCurrencyPayoutLimit - _nativeCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_projectOwner.balance, _projectOwnerNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -1555,7 +1547,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { ) { // Make sure the project owner received the funds that were paid out. _projectOwnerNativeBalance += - (_toNative(_usdCurrencyPayoutLimit) * JBConstants.MAX_FEE) / (_terminal.FEE() + JBConstants.MAX_FEE); + _toNative(_usdCurrencyPayoutLimit) - _toNative(_usdCurrencyPayoutLimit) * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_projectOwner.balance, _projectOwnerNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -1728,8 +1720,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { _usdcPayAmount - _usdcReclaimAmount ); - uint256 _usdcFeeAmount = _usdcReclaimAmount - - _usdcReclaimAmount * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _usdcFeeAmount = _usdcReclaimAmount * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_usdcToken.balanceOf(_beneficiary), _usdcReclaimAmount - _usdcFeeAmount); // Make sure the fee was paid correctly. @@ -2016,7 +2007,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { if (_nativeCurrencySurplusAllowance + _nativeCurrencyPayoutLimit <= _nativePayAmount) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. _beneficiaryNativeBalance = - mulDiv(_nativeCurrencySurplusAllowance, JBConstants.MAX_FEE, JBConstants.MAX_FEE + _terminal.FEE()); + _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -2079,7 +2070,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { if (_usdCurrencySurplusAllowance + _usdCurrencyPayoutLimit <= _usdcPayAmount) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. _beneficiaryUsdcBalance += - mulDiv(_usdCurrencySurplusAllowance, JBConstants.MAX_FEE, JBConstants.MAX_FEE + _terminal.FEE()); + _usdCurrencySurplusAllowance - mulDiv(_usdCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_usdcToken.balanceOf(_beneficiary), _beneficiaryUsdcBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal2), _projectId, address(_usdcToken)), @@ -2152,7 +2143,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { if (_nativeCurrencyPayoutLimit <= _nativePayAmount && _nativeCurrencyPayoutLimit != 0) { // Make sure the project owner received the funds that were paid out. _projectOwnerNativeBalance = - (_nativeCurrencyPayoutLimit * JBConstants.MAX_FEE) / (_terminal.FEE() + JBConstants.MAX_FEE); + _nativeCurrencyPayoutLimit - _nativeCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_projectOwner.balance, _projectOwnerNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -2211,7 +2202,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { if (_usdCurrencyPayoutLimit <= _usdcPayAmount && _usdCurrencyPayoutLimit != 0) { // Make sure the project owner received the funds that were paid out. _projectOwnerUsdcBalance = - (_usdCurrencyPayoutLimit * JBConstants.MAX_FEE) / (_terminal.FEE() + JBConstants.MAX_FEE); + _usdCurrencyPayoutLimit - _usdCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_usdcToken.balanceOf(_projectOwner), _projectOwnerUsdcBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal2), _projectId, address(_usdcToken)), @@ -2381,8 +2372,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { _usdcSurplus - _usdcReclaimAmount ); - uint256 _usdcFeeAmount = _usdcReclaimAmount - - _usdcReclaimAmount * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _usdcFeeAmount = _usdcReclaimAmount * _terminal.FEE() / JBConstants.MAX_FEE; _beneficiaryUsdcBalance += _usdcReclaimAmount - _usdcFeeAmount; assertEq(_usdcToken.balanceOf(_beneficiary), _beneficiaryUsdcBalance); diff --git a/test/TestCashOut.sol b/test/TestCashOut.sol index 3a9bbff9e..b7f77cc8e 100644 --- a/test/TestCashOut.sol +++ b/test/TestCashOut.sol @@ -160,7 +160,7 @@ contract TestCashOut_Local is TestBaseWorkflow { assertEq(_grossCashedOut, _grossPerReclaimable); // Compute the fee taken. - uint256 _fee = _grossCashedOut - mulDiv(_grossCashedOut, 1_000_000_000, 25_000_000 + 1_000_000_000); // 2.5% fee + uint256 _fee = mulDiv(_grossCashedOut, 25_000_000, 1_000_000_000); // 2.5% fee // Compute the net amount received, still in project. uint256 _netReceived = _grossCashedOut - _fee; @@ -181,7 +181,7 @@ contract TestCashOut_Local is TestBaseWorkflow { // Make sure the native token balance in terminal should be up to date (with 1 wei precision). assertApproxEqAbs( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), - _nativeTerminalBalance - _nativeReclaimAmt - (_nativeReclaimAmt * 25 / 1000), + _nativeTerminalBalance - _grossCashedOut, 1 ); } diff --git a/test/TestCashOutHooks.sol b/test/TestCashOutHooks.sol index 3d5b0274a..71ee40b75 100644 --- a/test/TestCashOutHooks.sol +++ b/test/TestCashOutHooks.sol @@ -249,7 +249,7 @@ contract TestCashOutHooks_Local is TestBaseWorkflow { uint256 _customTotalSupply = 5 * 10 ** 18; uint256 _forwardedAmount = - _halfPaid - (_halfPaid - mulDiv(_halfPaid, JBConstants.MAX_FEE, _terminal.FEE() + JBConstants.MAX_FEE)); + _halfPaid - (_halfPaid * _terminal.FEE() / JBConstants.MAX_FEE); uint256 _beneficiaryAmount = mulDiv( mulDiv(_nativePayAmount, _customCashOutCount, _customTotalSupply), @@ -258,9 +258,8 @@ contract TestCashOutHooks_Local is TestBaseWorkflow { JBConstants.MAX_CASH_OUT_TAX_RATE ); - _beneficiaryAmount -= ( - _beneficiaryAmount - mulDiv(_beneficiaryAmount, JBConstants.MAX_FEE, _terminal.FEE() + JBConstants.MAX_FEE) - ); + _beneficiaryAmount -= + mulDiv(_beneficiaryAmount, _terminal.FEE(), JBConstants.MAX_FEE); // Cash out context. JBAfterCashOutRecordedContext memory _cashOutContext = JBAfterCashOutRecordedContext({ diff --git a/test/TestFees.sol b/test/TestFees.sol index ed4e0d937..e8423be77 100644 --- a/test/TestFees.sol +++ b/test/TestFees.sol @@ -195,7 +195,7 @@ contract TestFees_Local is TestBaseWorkflow { // Calculate the fee from the allowance use. uint256 _feeAmount = - _nativeDistLimit - _nativeDistLimit * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + _nativeDistLimit * _terminal.FEE() / JBConstants.MAX_FEE; uint256 _afterFee = _nativeDistLimit - _feeAmount; @@ -238,8 +238,7 @@ contract TestFees_Local is TestBaseWorkflow { }); // Calculate the fee from the allowance use. - uint256 _feeAmount = - _nativeDistLimit - _nativeDistLimit * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _feeAmount = _nativeDistLimit * _terminal.FEE() / JBConstants.MAX_FEE; uint256 _afterFee = _nativeDistLimit - _feeAmount; @@ -288,8 +287,7 @@ contract TestFees_Local is TestBaseWorkflow { }); // Calculate the fee from the allowance use. - uint256 _feeAmount = - _nativeDistLimit - _nativeDistLimit * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _feeAmount = _nativeDistLimit * _terminal.FEE() / JBConstants.MAX_FEE; uint256 _afterFee = _nativeDistLimit - _feeAmount; @@ -349,8 +347,7 @@ contract TestFees_Local is TestBaseWorkflow { }); // Calculate the fee from the allowance use. - uint256 _feeAmount = - _halfDistLimit - _halfDistLimit * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _feeAmount = _halfDistLimit * _terminal.FEE() / JBConstants.MAX_FEE; uint256 _afterFee = (_halfDistLimit - _feeAmount) * 2; @@ -410,8 +407,7 @@ contract TestFees_Local is TestBaseWorkflow { }); // Calculate the fee from the allowance use. - uint256 _feeAmount = - _halfDistLimit - _halfDistLimit * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _feeAmount = _halfDistLimit * _terminal.FEE() / JBConstants.MAX_FEE; uint256 _afterFee = (_halfDistLimit - _feeAmount) * 2; @@ -463,8 +459,7 @@ contract TestFees_Local is TestBaseWorkflow { }); // Calculate the fee from the allowance use. - uint256 _feeAmount = - _nativeDistLimit - _nativeDistLimit * JBConstants.MAX_FEE / (_terminal.FEE() + JBConstants.MAX_FEE); + uint256 _feeAmount = _nativeDistLimit * _terminal.FEE() / JBConstants.MAX_FEE; uint256 _afterFee = _nativeDistLimit - _feeAmount; diff --git a/test/TestMultipleAccessLimits.sol b/test/TestMultipleAccessLimits.sol index bb102e9ab..fbeb4526d 100644 --- a/test/TestMultipleAccessLimits.sol +++ b/test/TestMultipleAccessLimits.sol @@ -169,7 +169,7 @@ contract TestMultipleAccessLimits_Local is TestBaseWorkflow { assertEq( address(__terminal).balance, initTerminalBalance - - mulDiv(_payoutLimits[0].amount, JBConstants.MAX_FEE, JBConstants.MAX_FEE + __terminal.FEE()) + - _payoutLimits[0].amount + mulDiv(_payoutLimits[0].amount, __terminal.FEE(), JBConstants.MAX_FEE) ); // Price for the amount (in USD) that can be paid out based on the terminal's current balance. @@ -620,13 +620,13 @@ contract TestMultipleAccessLimits_Local is TestBaseWorkflow { assertEq( _projectOwner.balance, ownerBalanceBeforeFirst - + mulDiv(_amountPaidOut, JBConstants.MAX_FEE, JBConstants.MAX_FEE + __terminal.FEE()) + + _amountPaidOut - mulDiv(_amountPaidOut, __terminal.FEE(), JBConstants.MAX_FEE) ); // Funds leaving the ecosystem -> fee taken. assertEq( address(__terminal).balance, - initTerminalBalance - mulDiv(_amountPaidOut, JBConstants.MAX_FEE, JBConstants.MAX_FEE + __terminal.FEE()) + initTerminalBalance - _amountPaidOut + mulDiv(_amountPaidOut, __terminal.FEE(), JBConstants.MAX_FEE) ); uint256 _balanceBeforeNativeDist = address(__terminal).balance; @@ -643,12 +643,12 @@ contract TestMultipleAccessLimits_Local is TestBaseWorkflow { // Funds leaving the ecosystem -> fee taken. assertEq( _projectOwner.balance, - _ownerBalanceBeforeNativeDist + mulDiv(1 ether, JBConstants.MAX_FEE, JBConstants.MAX_FEE + __terminal.FEE()) + _ownerBalanceBeforeNativeDist + 1 ether - mulDiv(1 ether, __terminal.FEE(), JBConstants.MAX_FEE) ); assertEq( address(__terminal).balance, - _balanceBeforeNativeDist - mulDiv(1 ether, JBConstants.MAX_FEE, JBConstants.MAX_FEE + __terminal.FEE()) + _balanceBeforeNativeDist - 1 ether + mulDiv(1 ether, __terminal.FEE(), JBConstants.MAX_FEE) ); } } diff --git a/test/TestSplits.sol b/test/TestSplits.sol index 5798b4f1e..0ac5d7de4 100644 --- a/test/TestSplits.sol +++ b/test/TestSplits.sol @@ -172,7 +172,7 @@ contract TestSplits_Local is TestBaseWorkflow { // Calculate the amount returned after fees are processed. uint256 _beneficiaryNativeBalance = - mulDiv(_nativePayoutLimit, JBConstants.MAX_FEE, JBConstants.MAX_FEE + _terminal.FEE()); + _nativePayoutLimit - mulDiv(_nativePayoutLimit, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_splitsGuy.balance, _beneficiaryNativeBalance); diff --git a/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol b/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol index f3fcd3ac4..a4066e326 100644 --- a/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol +++ b/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol @@ -86,7 +86,7 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup { assertEq(setFees[0].amount, feeAmount); payAmount = 2e18; - feeAmountIn = JBFees.feeAmountIn(feeAmount, 25); + feeAmountIn = JBFees.feeAmountFrom(feeAmount, 25); amountFromFee = feeAmount - feeAmountIn; leftOverAmount = payAmount - amountFromFee; @@ -152,8 +152,7 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup { { // it will set heldFeesOf return feeAmountFrom and set leftoverAmount to zero uint256 lowerPayAmount = 1e8; - uint256 feeA = JBFees.feeAmountFrom(feeAmount, 25); - uint256 returnedFee = mulDiv(lowerPayAmount, 25, JBConstants.MAX_FEE); + uint256 returnedFee = JBFees.feeAmountIn(lowerPayAmount, 25); // mock call to store recordAddedBalanceFor mockExpect( @@ -174,7 +173,7 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup { metadata: "" }); - uint256 newFeeAmount = feeAmount - (lowerPayAmount + JBFees.feeAmountFrom(lowerPayAmount, 25)); + uint256 newFeeAmount = feeAmount - (lowerPayAmount + returnedFee); // Heldfee should be a new amount JBFee[] memory feesAfter = _terminal.heldFeesOf(_projectId, _native, 100); diff --git a/test/units/static/JBMultiTerminal/TestCashOutTokensOf.sol b/test/units/static/JBMultiTerminal/TestCashOutTokensOf.sol index fac445d02..539dc9f5e 100644 --- a/test/units/static/JBMultiTerminal/TestCashOutTokensOf.sol +++ b/test/units/static/JBMultiTerminal/TestCashOutTokensOf.sol @@ -210,7 +210,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup { mockExpect(address(feelessAddresses), abi.encodeCall(IJBFeelessAddresses.isFeeless, (_bene)), abi.encode(false)); // get fee amount - uint256 tax = JBFees.feeAmountIn(reclaimAmount, 25); // 25 = default fee) + uint256 tax = JBFees.feeAmountFrom(reclaimAmount, 25); // 25 = default fee) uint256 transferredAmount = reclaimAmount - tax; // transfer reclaimed to beneficiary @@ -424,7 +424,7 @@ contract TestCashOutTokensOf_Local is JBMultiTerminalSetup { abi.encode(false) ); - uint256 hookTax = JBFees.feeAmountIn(_defaultAmount, 25); + uint256 hookTax = JBFees.feeAmountFrom(_defaultAmount, 25); uint256 passedAfterTax = _defaultAmount - hookTax; JBTokenAmount memory reclaimedAmount = JBTokenAmount(address(_mockToken2), 0, 0, reclaimAmount); diff --git a/test/units/static/JBMultiTerminal/TestExecutePayout.sol b/test/units/static/JBMultiTerminal/TestExecutePayout.sol index c2cf27488..5e43bee92 100644 --- a/test/units/static/JBMultiTerminal/TestExecutePayout.sol +++ b/test/units/static/JBMultiTerminal/TestExecutePayout.sol @@ -106,7 +106,7 @@ contract TestExecutePayout_Local is JBMultiTerminalSetup { hook: IJBSplitHook(_hook) }); - uint256 taxedAmount = JBFees.feeAmountIn(_defaultAmount, _fee); + uint256 taxedAmount = JBFees.feeAmountFrom(_defaultAmount, _fee); // Create the context to send to the split hook. JBSplitHookContext memory context = JBSplitHookContext({ @@ -167,7 +167,7 @@ contract TestExecutePayout_Local is JBMultiTerminalSetup { hook: IJBSplitHook(address(0)) }); - uint256 taxedAmount = JBFees.feeAmountIn(_defaultAmount, _fee); + uint256 taxedAmount = JBFees.feeAmountFrom(_defaultAmount, _fee); // mock call to usdc transfer mockExpect( @@ -286,7 +286,7 @@ contract TestExecutePayout_Local is JBMultiTerminalSetup { hook: IJBSplitHook(address(0)) }); - uint256 taxedAmount = JBFees.feeAmountIn(_defaultAmount, _fee); + uint256 taxedAmount = JBFees.feeAmountFrom(_defaultAmount, _fee); uint256 amountAfterTax = _defaultAmount - taxedAmount; // mock call for SafeERC20s allowance check @@ -405,7 +405,7 @@ contract TestExecutePayout_Local is JBMultiTerminalSetup { hook: IJBSplitHook(address(0)) }); - uint256 taxedAmount = JBFees.feeAmountIn(_defaultAmount, _fee); + uint256 taxedAmount = JBFees.feeAmountFrom(_defaultAmount, _fee); uint256 amountAfterTax = _defaultAmount - taxedAmount; // mock call for SafeERC20s allowance check @@ -487,7 +487,7 @@ contract TestExecutePayout_Local is JBMultiTerminalSetup { hook: IJBSplitHook(address(0)) }); - uint256 taxedAmount = JBFees.feeAmountIn(_defaultAmount, _fee); + uint256 taxedAmount = JBFees.feeAmountFrom(_defaultAmount, _fee); uint256 amountAfterTax = _defaultAmount - taxedAmount; // mock call to usdc transfer @@ -522,7 +522,7 @@ contract TestExecutePayout_Local is JBMultiTerminalSetup { hook: IJBSplitHook(address(0)) }); - uint256 taxedAmount = JBFees.feeAmountIn(_defaultAmount, _fee); + uint256 taxedAmount = JBFees.feeAmountFrom(_defaultAmount, _fee); uint256 amountAfterTax = _defaultAmount - taxedAmount; // mock call to usdc transfer diff --git a/test/units/static/JBMultiTerminal/TestSendPayoutsOf.sol b/test/units/static/JBMultiTerminal/TestSendPayoutsOf.sol index 3705ba5fd..8a1236ac6 100644 --- a/test/units/static/JBMultiTerminal/TestSendPayoutsOf.sol +++ b/test/units/static/JBMultiTerminal/TestSendPayoutsOf.sol @@ -232,8 +232,8 @@ contract TestSendPayoutsOf_Local is JBMultiTerminalSetup { _projectId, address(this), address(0), - 97, // Amount that would have been transferred after fee. - 3, // fee amount + 98, // Amount that would have been transferred after fee. + 2, // fee amount bytes(hex"5274afe70000000000000000000000000000000000000000000000000000000000000000"), address(this) ); diff --git a/test/units/static/JBMultiTerminal/TestUseAllowanceOf.sol b/test/units/static/JBMultiTerminal/TestUseAllowanceOf.sol index 23bc72a6d..2089318f8 100644 --- a/test/units/static/JBMultiTerminal/TestUseAllowanceOf.sol +++ b/test/units/static/JBMultiTerminal/TestUseAllowanceOf.sol @@ -235,7 +235,7 @@ contract TestUseAllowanceOf_Local is JBMultiTerminalSetup { address(feelessAddresses), abi.encodeCall(IJBFeelessAddresses.isFeeless, (beneficiary)), abi.encode(false) ); - mockExpect(mockToken, abi.encodeCall(IERC20.transfer, (beneficiary, 97)), abi.encode(true)); + mockExpect(mockToken, abi.encodeCall(IERC20.transfer, (beneficiary, 98)), abi.encode(true)); // call to find the primary terminal for fee processing mockExpect( @@ -245,7 +245,7 @@ contract TestUseAllowanceOf_Local is JBMultiTerminalSetup { ); JBTokenAmount memory tokenContext = - JBTokenAmount({token: mockToken, decimals: 18, currency: currencyId, value: 3}); + JBTokenAmount({token: mockToken, decimals: 18, currency: currencyId, value: 2}); // mock call to jbterminalstore mockExpect( @@ -262,7 +262,7 @@ contract TestUseAllowanceOf_Local is JBMultiTerminalSetup { mockExpect( address(controller), abi.encodeCall(IJBController.mintTokensOf, (_projectId, 1, address(this), "", true)), - abi.encode(1) + abi.encode(2) ); vm.expectEmit(); @@ -274,7 +274,7 @@ contract TestUseAllowanceOf_Local is JBMultiTerminalSetup { feeBeneficiary: address(this), amount: 100, amountPaidOut: 100, - netAmountPaidOut: 97, + netAmountPaidOut: 98, memo: "", caller: address(this) }); From b87746451832a9687b7f046ac216020ef136372f Mon Sep 17 00:00:00 2001 From: mejango Date: Sat, 18 Jan 2025 19:24:20 -0300 Subject: [PATCH 2/4] resolve --- src/JBERC20.sol | 8 ------ src/JBMultiTerminal.sol | 5 ++-- src/libraries/JBFees.sol | 3 ++- test/TestAccessToFunds.sol | 43 +++++++++++++++++-------------- test/TestCashOutHooks.sol | 6 ++--- test/TestFees.sol | 3 +-- test/TestMultipleAccessLimits.sol | 7 +++-- 7 files changed, 34 insertions(+), 41 deletions(-) diff --git a/src/JBERC20.sol b/src/JBERC20.sol index 6248c1175..b697cb39c 100644 --- a/src/JBERC20.sol +++ b/src/JBERC20.sol @@ -43,14 +43,6 @@ contract JBERC20 is ERC20Votes, ERC20Permit, Ownable, IJBToken { return super.balanceOf(account); } -<<<<<<< Updated upstream -======= - /// @notice This token can only be added to a project when its created by the `JBTokens` contract. - function canBeAddedTo(uint256) external pure override returns (bool) { - return false; - } - ->>>>>>> Stashed changes /// @notice The number of decimals used for this token's fixed point accounting. /// @return The number of decimals. function decimals() public view override(ERC20, IJBToken) returns (uint8) { diff --git a/src/JBMultiTerminal.sol b/src/JBMultiTerminal.sol index 0d2391ffd..8f28c4e43 100644 --- a/src/JBMultiTerminal.sol +++ b/src/JBMultiTerminal.sol @@ -1740,8 +1740,9 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { // Send any leftover funds to the project owner and update the fee tracking accordingly. if (leftoverPayoutAmount != 0) { // Keep a reference to the fee for the leftover payout amount. - uint256 fee = - _isFeeless(projectOwner) ? 0 : JBFees.feeAmountFrom({amountBeforeFee: leftoverPayoutAmount, feePercent: FEE}); + uint256 fee = _isFeeless(projectOwner) + ? 0 + : JBFees.feeAmountFrom({amountBeforeFee: leftoverPayoutAmount, feePercent: FEE}); // Transfer the amount to the project owner. try this.executeTransferTo({addr: projectOwner, token: token, amount: leftoverPayoutAmount - fee}) { diff --git a/src/libraries/JBFees.sol b/src/libraries/JBFees.sol index d64146a91..e6fa14045 100644 --- a/src/libraries/JBFees.sol +++ b/src/libraries/JBFees.sol @@ -20,7 +20,8 @@ library JBFees { /// @notice Returns the fee that would have been paid based on an `amount` which has already had the fee subtracted /// from it. - /// @param amountBeforeFee The amount that the fee is based on, as a fixed point number with the same amount of decimals as + /// @param amountBeforeFee The amount that the fee is based on, as a fixed point number with the same amount of + /// decimals as /// this terminal. /// @param feePercent The fee percent, out of `JBConstants.MAX_FEE`. /// @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal. diff --git a/test/TestAccessToFunds.sol b/test/TestAccessToFunds.sol index 7f49e0fb3..c26d8ba4c 100644 --- a/test/TestAccessToFunds.sol +++ b/test/TestAccessToFunds.sol @@ -185,7 +185,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { }); // Make sure the beneficiary received the funds and that they are no longer in the terminal. - uint256 _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); + uint256 _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance + - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -216,7 +217,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { }); // Make sure the project owner received the funds which were paid out. - uint256 _projectOwnerNativeBalance = _nativeCurrencyPayoutLimit - _nativeCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; + uint256 _projectOwnerNativeBalance = + _nativeCurrencyPayoutLimit - _nativeCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; // Make sure the project owner received the full amount. assertEq(_projectOwner.balance, _projectOwnerNativeBalance); @@ -272,8 +274,7 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { ); // Calculate the fee from the cash out. - uint256 _feeAmount = - _nativeReclaimAmount * _terminal.FEE() / JBConstants.MAX_FEE; + uint256 _feeAmount = _nativeReclaimAmount * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_beneficiary.balance, _beneficiaryNativeBalance + _nativeReclaimAmount - _feeAmount); // Make sure the fee was paid correctly. @@ -436,8 +437,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { // Check the collected balance if one is expected. if (_nativeCurrencySurplusAllowance + _nativeCurrencyPayoutLimit <= _nativePayAmount) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. - _beneficiaryNativeBalance = - _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); + _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance + - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -723,7 +724,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { // Check the collected balance if one is expected. if (_nativeCurrencySurplusAllowance + _nativeCurrencyPayoutLimit <= _nativePayAmount) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. - _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); + _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance + - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); // Make sure the fee stays in the terminal. assertEq( @@ -979,7 +981,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { // Check the collected balance if one is expected. if (_nativeCurrencySurplusAllowance + _nativeCurrencyPayoutLimit <= _nativePayAmount) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. - _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); + _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance + - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -1029,7 +1032,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { // Check the received payout if one is expected. if (_nativeCurrencyPayoutLimit <= _nativePayAmount && _nativeCurrencyPayoutLimit != 0) { // Make sure the project owner received the funds that were paid out. - _projectOwnerNativeBalance = _nativeCurrencyPayoutLimit - _nativeCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; + _projectOwnerNativeBalance = + _nativeCurrencyPayoutLimit - _nativeCurrencyPayoutLimit * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_projectOwner.balance, _projectOwnerNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -1327,8 +1331,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { <= _nativePayAmount ) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. - _beneficiaryNativeBalance = - _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); + _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance + - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -1398,9 +1402,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { + _toNative(_usdCurrencySurplusAllowance + _usdCurrencyPayoutLimit) <= _nativePayAmount ) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. - _beneficiaryNativeBalance += _toNative(_usdCurrencySurplusAllowance) - mulDiv( - _toNative(_usdCurrencySurplusAllowance), _terminal.FEE(), JBConstants.MAX_FEE - ); + _beneficiaryNativeBalance += _toNative(_usdCurrencySurplusAllowance) + - mulDiv(_toNative(_usdCurrencySurplusAllowance), _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -1546,8 +1549,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { && _usdCurrencyPayoutLimit > 0 ) { // Make sure the project owner received the funds that were paid out. - _projectOwnerNativeBalance += - _toNative(_usdCurrencyPayoutLimit) - _toNative(_usdCurrencyPayoutLimit) * _terminal.FEE() / JBConstants.MAX_FEE; + _projectOwnerNativeBalance += _toNative(_usdCurrencyPayoutLimit) + - _toNative(_usdCurrencyPayoutLimit) * _terminal.FEE() / JBConstants.MAX_FEE; assertEq(_projectOwner.balance, _projectOwnerNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -2006,8 +2009,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { // Check the collected balance if one is expected. if (_nativeCurrencySurplusAllowance + _nativeCurrencyPayoutLimit <= _nativePayAmount) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. - _beneficiaryNativeBalance = - _nativeCurrencySurplusAllowance - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); + _beneficiaryNativeBalance = _nativeCurrencySurplusAllowance + - mulDiv(_nativeCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_beneficiary.balance, _beneficiaryNativeBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN), @@ -2069,8 +2072,8 @@ contract TestAccessToFunds_Local is TestBaseWorkflow { // Check the collected balance if one is expected. if (_usdCurrencySurplusAllowance + _usdCurrencyPayoutLimit <= _usdcPayAmount) { // Make sure the beneficiary received the funds and that they are no longer in the terminal. - _beneficiaryUsdcBalance += - _usdCurrencySurplusAllowance - mulDiv(_usdCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); + _beneficiaryUsdcBalance += _usdCurrencySurplusAllowance + - mulDiv(_usdCurrencySurplusAllowance, _terminal.FEE(), JBConstants.MAX_FEE); assertEq(_usdcToken.balanceOf(_beneficiary), _beneficiaryUsdcBalance); assertEq( jbTerminalStore().balanceOf(address(_terminal2), _projectId, address(_usdcToken)), diff --git a/test/TestCashOutHooks.sol b/test/TestCashOutHooks.sol index 71ee40b75..5540246d7 100644 --- a/test/TestCashOutHooks.sol +++ b/test/TestCashOutHooks.sol @@ -248,8 +248,7 @@ contract TestCashOutHooks_Local is TestBaseWorkflow { uint256 _customCashOutCount = 1 * 10 ** 18; uint256 _customTotalSupply = 5 * 10 ** 18; - uint256 _forwardedAmount = - _halfPaid - (_halfPaid * _terminal.FEE() / JBConstants.MAX_FEE); + uint256 _forwardedAmount = _halfPaid - (_halfPaid * _terminal.FEE() / JBConstants.MAX_FEE); uint256 _beneficiaryAmount = mulDiv( mulDiv(_nativePayAmount, _customCashOutCount, _customTotalSupply), @@ -258,8 +257,7 @@ contract TestCashOutHooks_Local is TestBaseWorkflow { JBConstants.MAX_CASH_OUT_TAX_RATE ); - _beneficiaryAmount -= - mulDiv(_beneficiaryAmount, _terminal.FEE(), JBConstants.MAX_FEE); + _beneficiaryAmount -= mulDiv(_beneficiaryAmount, _terminal.FEE(), JBConstants.MAX_FEE); // Cash out context. JBAfterCashOutRecordedContext memory _cashOutContext = JBAfterCashOutRecordedContext({ diff --git a/test/TestFees.sol b/test/TestFees.sol index e8423be77..f05352376 100644 --- a/test/TestFees.sol +++ b/test/TestFees.sol @@ -194,8 +194,7 @@ contract TestFees_Local is TestBaseWorkflow { }); // Calculate the fee from the allowance use. - uint256 _feeAmount = - _nativeDistLimit * _terminal.FEE() / JBConstants.MAX_FEE; + uint256 _feeAmount = _nativeDistLimit * _terminal.FEE() / JBConstants.MAX_FEE; uint256 _afterFee = _nativeDistLimit - _feeAmount; diff --git a/test/TestMultipleAccessLimits.sol b/test/TestMultipleAccessLimits.sol index fbeb4526d..ebcff8023 100644 --- a/test/TestMultipleAccessLimits.sol +++ b/test/TestMultipleAccessLimits.sol @@ -168,8 +168,8 @@ contract TestMultipleAccessLimits_Local is TestBaseWorkflow { // Make sure the balance has changed, accounting for the fee that stays. assertEq( address(__terminal).balance, - initTerminalBalance - - _payoutLimits[0].amount + mulDiv(_payoutLimits[0].amount, __terminal.FEE(), JBConstants.MAX_FEE) + initTerminalBalance - _payoutLimits[0].amount + + mulDiv(_payoutLimits[0].amount, __terminal.FEE(), JBConstants.MAX_FEE) ); // Price for the amount (in USD) that can be paid out based on the terminal's current balance. @@ -619,8 +619,7 @@ contract TestMultipleAccessLimits_Local is TestBaseWorkflow { assertEq( _projectOwner.balance, - ownerBalanceBeforeFirst - + _amountPaidOut - mulDiv(_amountPaidOut, __terminal.FEE(), JBConstants.MAX_FEE) + ownerBalanceBeforeFirst + _amountPaidOut - mulDiv(_amountPaidOut, __terminal.FEE(), JBConstants.MAX_FEE) ); // Funds leaving the ecosystem -> fee taken. From 5aa807f52c744fa6913b688bbf3b1a64dee0ee4e Mon Sep 17 00:00:00 2001 From: mejango Date: Sat, 18 Jan 2025 19:32:06 -0300 Subject: [PATCH 3/4] touchup --- src/JBMultiTerminal.sol | 4 ++-- src/libraries/JBFees.sol | 4 ++-- test/trees/JBMultiTerminal/addToBalanceOf.tree | 2 +- .../static/JBMultiTerminal/TestAddToBalanceOf.sol | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/JBMultiTerminal.sol b/src/JBMultiTerminal.sol index 8f28c4e43..3414d3de9 100644 --- a/src/JBMultiTerminal.sol +++ b/src/JBMultiTerminal.sol @@ -1637,7 +1637,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { if (leftoverAmount == 0) { break; } else { - // Notice here we take `feeAmountIn` on the stored `.amount`. + // Notice here we take `feeAmountFrom` on the stored `.amount`. uint256 feeAmount = JBFees.feeAmountFrom({amountBeforeFee: heldFee.amount, feePercent: FEE}); // Keep a reference to the amount from which the fee was taken. @@ -1653,7 +1653,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { newStartIndex = startIndex + i + 1; } else { // And here we overwrite with `feeAmountFrom` the `leftoverAmount` - feeAmount = JBFees.feeAmountIn({amountAfterFee: leftoverAmount, feePercent: FEE}); + feeAmount = JBFees.feeAmountResultingIn({amountAfterFee: leftoverAmount, feePercent: FEE}); // Get fee from `leftoverAmount`. unchecked { diff --git a/src/libraries/JBFees.sol b/src/libraries/JBFees.sol index e6fa14045..0cf9146c9 100644 --- a/src/libraries/JBFees.sol +++ b/src/libraries/JBFees.sol @@ -7,12 +7,12 @@ import {JBConstants} from "./../libraries/JBConstants.sol"; /// @notice Fee calculations. library JBFees { - /// @notice Returns the amount of tokens to pay as a fee out of the specified `amount`. + /// @notice Returns the amount of tokens to pay as a fee relative to the specified `amount`. /// @param amountAfterFee The amount that the fee is based on, as a fixed point number. /// @param feePercent The fee percent, out of `JBConstants.MAX_FEE`. /// @return The amount of tokens to pay as a fee, as a fixed point number with the same number of decimals as the /// provided `amount`. - function feeAmountIn(uint256 amountAfterFee, uint256 feePercent) internal pure returns (uint256) { + function feeAmountResultingIn(uint256 amountAfterFee, uint256 feePercent) internal pure returns (uint256) { // The amount of tokens from the `amount` to pay as a fee. If reverse, the fee taken from a payout of // `amount`. return mulDiv(amountAfterFee, JBConstants.MAX_FEE, JBConstants.MAX_FEE - feePercent) - amountAfterFee; diff --git a/test/trees/JBMultiTerminal/addToBalanceOf.tree b/test/trees/JBMultiTerminal/addToBalanceOf.tree index 22b18ea20..0f9853b16 100644 --- a/test/trees/JBMultiTerminal/addToBalanceOf.tree +++ b/test/trees/JBMultiTerminal/addToBalanceOf.tree @@ -3,7 +3,7 @@ TestAddToBalanceOf_Local │ ├── given return amount is zero │ │ └── it will set heldFeesOf project to zero │ ├── given return amount is non-zero and leftoverAmount GTEQ amountFromFee -│ │ └── it will return feeAmountIn +│ │ └── it will return feeAmountResultingIn │ └── given return amount is non-zero and leftoverAmount LT amountFromFee │ └── it will set heldFeesOf return feeAmountFrom and set leftoverAmount to zero ├── when shouldReturnHeldFees eq false diff --git a/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol b/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol index a4066e326..370b49229 100644 --- a/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol +++ b/test/units/static/JBMultiTerminal/TestAddToBalanceOf.sol @@ -19,7 +19,7 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup { // set by modifiers uint256 payAmount; uint256 feeAmount; - uint256 feeAmountIn; + uint256 feeAmountFrom; uint256 amountFromFee; uint256 leftOverAmount; bool _shouldReturnHeldFees; @@ -86,9 +86,9 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup { assertEq(setFees[0].amount, feeAmount); payAmount = 2e18; - feeAmountIn = JBFees.feeAmountFrom(feeAmount, 25); + feeAmountFrom = JBFees.feeAmountFrom(feeAmount, 25); - amountFromFee = feeAmount - feeAmountIn; + amountFromFee = feeAmount - feeAmountFrom; leftOverAmount = payAmount - amountFromFee; _shouldReturnHeldFees = true; @@ -125,12 +125,12 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup { // mock call to store recordAddedBalanceFor mockExpect( address(store), - abi.encodeCall(IJBTerminalStore.recordAddedBalanceFor, (_projectId, _native, payAmount + feeAmountIn)), + abi.encodeCall(IJBTerminalStore.recordAddedBalanceFor, (_projectId, _native, payAmount + feeAmountFrom)), "" ); vm.expectEmit(); - emit IJBFeeTerminal.ReturnHeldFees(_projectId, _native, payAmount, feeAmountIn, leftOverAmount, address(this)); + emit IJBFeeTerminal.ReturnHeldFees(_projectId, _native, payAmount, feeAmountFrom, leftOverAmount, address(this)); _terminal.addToBalanceOf{value: payAmount}({ projectId: _projectId, @@ -152,7 +152,7 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup { { // it will set heldFeesOf return feeAmountFrom and set leftoverAmount to zero uint256 lowerPayAmount = 1e8; - uint256 returnedFee = JBFees.feeAmountIn(lowerPayAmount, 25); + uint256 returnedFee = JBFees.feeAmountResultingIn(lowerPayAmount, 25); // mock call to store recordAddedBalanceFor mockExpect( @@ -186,7 +186,7 @@ contract TestAddToBalanceOf_Local is JBMultiTerminalSetup { // mock call to store recordAddedBalanceFor mockExpect( address(store), - abi.encodeCall(IJBTerminalStore.recordAddedBalanceFor, (_projectId, _native, payAmount + feeAmountIn)), + abi.encodeCall(IJBTerminalStore.recordAddedBalanceFor, (_projectId, _native, payAmount + feeAmountFrom)), "" ); From 599ee126215abe04dc1c18ee17b6ce4e3a494024 Mon Sep 17 00:00:00 2001 From: mejango Date: Sat, 18 Jan 2025 19:33:01 -0300 Subject: [PATCH 4/4] touchup --- src/JBMultiTerminal.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JBMultiTerminal.sol b/src/JBMultiTerminal.sol index 3414d3de9..33776d9fd 100644 --- a/src/JBMultiTerminal.sol +++ b/src/JBMultiTerminal.sol @@ -1652,7 +1652,7 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal { // Move the start index forward to the held fee after the current one. newStartIndex = startIndex + i + 1; } else { - // And here we overwrite with `feeAmountFrom` the `leftoverAmount` + // And here we overwrite with `feeAmountResultingIn` the `leftoverAmount` feeAmount = JBFees.feeAmountResultingIn({amountAfterFee: leftoverAmount, feePercent: FEE}); // Get fee from `leftoverAmount`.