Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jango/fee always from #234

Merged
merged 4 commits into from
Jan 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions src/JBMultiTerminal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -1637,8 +1637,8 @@ contract JBMultiTerminal is JBPermissioned, ERC2771Context, IJBMultiTerminal {
if (leftoverAmount == 0) {
break;
} else {
// Notice here we take `feeAmountIn` on the stored `.amount`.
uint256 feeAmount = JBFees.feeAmountIn({amount: heldFee.amount, feePercent: FEE});
// 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.
uint256 amountPaidOut = heldFee.amount - feeAmount;
Expand All @@ -1652,8 +1652,8 @@ 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`
feeAmount = JBFees.feeAmountFrom({amount: leftoverAmount, feePercent: FEE});
// And here we overwrite with `feeAmountResultingIn` the `leftoverAmount`
feeAmount = JBFees.feeAmountResultingIn({amountAfterFee: leftoverAmount, feePercent: FEE});

// Get fee from `leftoverAmount`.
unchecked {
Expand Down Expand Up @@ -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.feeAmountIn({amount: 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}) {
Expand Down Expand Up @@ -1915,7 +1916,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.
Expand Down
18 changes: 8 additions & 10 deletions src/libraries/JBFees.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,27 @@ 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.
/// @notice Returns the amount of tokens to pay as a fee relative to the specified `amount`.
mejango marked this conversation as resolved.
Show resolved Hide resolved
/// @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 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 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);
}
}
Loading
Loading