Skip to content

Latest commit

 

History

History
661 lines (560 loc) · 21.8 KB

FeesHelper.md

File metadata and controls

661 lines (560 loc) · 21.8 KB

The Fees Helper contract.

  • This contract calculates and pays lending/borrow fees and rewards. (FeesHelper.sol)

View Source: contracts/mixins/FeesHelper.sol

↗ Extends: State, FeesEvents ↘ Derived Contracts: InterestUser, SwapsUser

FeesHelper contract

Functions


_getTradingFee

Calculate trading fee.

function _getTradingFee(uint256 feeTokenAmount) internal view
returns(uint256)

Arguments

Name Type Description
feeTokenAmount uint256 The amount of tokens to trade.

Returns

The fee of the trade.

Source Code
function _getTradingFee(uint256 feeTokenAmount) internal view returns (uint256) {
        return feeTokenAmount.mul(tradingFeePercent).divCeil(10**20);
    }

_getSwapExternalFee

Calculate swap external fee.

function _getSwapExternalFee(uint256 feeTokenAmount) internal view
returns(uint256)

Arguments

Name Type Description
feeTokenAmount uint256 The amount of token to swap.

Returns

The fee of the swap.

Source Code
function _getSwapExternalFee(uint256 feeTokenAmount) internal view returns (uint256) {
        return feeTokenAmount.mul(swapExtrernalFeePercent).divCeil(10**20);
    }

_getBorrowingFee

Calculate the loan origination fee.

function _getBorrowingFee(uint256 feeTokenAmount) internal view
returns(uint256)

Arguments

Name Type Description
feeTokenAmount uint256 The amount of tokens to borrow.

Returns

The fee of the loan.

Source Code
function _getBorrowingFee(uint256 feeTokenAmount) internal view returns (uint256) {
        return feeTokenAmount.mul(borrowingFeePercent).divCeil(10**20);
        /*
		// p3.9 from bzx peckshield-audit-report-bZxV2-v1.0rc1.pdf
		// cannot be applied solely nor with LoanOpenings.sol as it drives to some other tests failure
		uint256 collateralAmountRequired =
			feeTokenAmount.mul(10**20).divCeil(
				10**20 - borrowingFeePercent // never will overflow
			);
		return collateralAmountRequired.sub(feeTokenAmount);*/
    }

_payTradingFeeToAffiliate

Settle the trading fee and pay the token reward to the affiliates referrer. *

function _payTradingFeeToAffiliate(address referrer, address trader, address feeToken, uint256 tradingFee) internal nonpayable
returns(affiliatesBonusSOVAmount uint256, affiliatesBonusTokenAmount uint256)

Arguments

Name Type Description
referrer address The affiliate referrer address to send the reward to.
trader address The account that performs this trade.
feeToken address The address of the token in which the trading fee is paid.
tradingFee uint256 The amount of tokens accrued as fees on the trading. *

Returns

affiliatesBonusSOVAmount the total SOV amount that is distributed to the referrer

Source Code
function _payTradingFeeToAffiliate(
        address referrer,
        address trader,
        address feeToken,
        uint256 tradingFee
    ) internal returns (uint256 affiliatesBonusSOVAmount, uint256 affiliatesBonusTokenAmount) {
        (affiliatesBonusSOVAmount, affiliatesBonusTokenAmount) = ProtocolAffiliatesInterface(
            address(this)
        )
            .payTradingFeeToAffiliatesReferrer(referrer, trader, feeToken, tradingFee);
    }

_payTradingFee

Settle the trading fee and pay the token reward to the user.

function _payTradingFee(address user, bytes32 loanId, address feeToken, address feeTokenPair, uint256 tradingFee) internal nonpayable

Arguments

Name Type Description
user address The address to send the reward to.
loanId bytes32 The Id of the associated loan - used for logging only.
feeToken address The address of the token in which the trading fee is paid.
feeTokenPair address
tradingFee uint256 The amount of tokens accrued as fees on the trading.
Source Code
function _payTradingFee(
        address user,
        bytes32 loanId,
        address feeToken,
        address feeTokenPair,
        uint256 tradingFee
    ) internal {
        uint256 protocolTradingFee = tradingFee; /// Trading fee paid to protocol.
        if (tradingFee != 0) {
            if (affiliatesUserReferrer[user] != address(0)) {
                _payTradingFeeToAffiliate(
                    affiliatesUserReferrer[user],
                    user,
                    feeToken,
                    protocolTradingFee
                );
                protocolTradingFee = (
                    protocolTradingFee.sub(protocolTradingFee.mul(affiliateFeePercent).div(10**20))
                )
                    .sub(protocolTradingFee.mul(affiliateTradingTokenFeePercent).div(10**20));
            }

            /// Increase the storage variable keeping track of the accumulated fees.
            tradingFeeTokensHeld[feeToken] = tradingFeeTokensHeld[feeToken].add(
                protocolTradingFee
            );

            emit PayTradingFee(user, feeToken, loanId, protocolTradingFee);

            /// Pay the token reward to the user.
            _payFeeReward(user, loanId, feeToken, feeTokenPair, tradingFee);
        }
    }

_payBorrowingFee

Settle the borrowing fee and pay the token reward to the user.

function _payBorrowingFee(address user, bytes32 loanId, address feeToken, address feeTokenPair, uint256 borrowingFee) internal nonpayable

Arguments

Name Type Description
user address The address to send the reward to.
loanId bytes32 The Id of the associated loan - used for logging only.
feeToken address The address of the token in which the borrowig fee is paid.
feeTokenPair address
borrowingFee uint256 The height of the fee.
Source Code
function _payBorrowingFee(
        address user,
        bytes32 loanId,
        address feeToken,
        address feeTokenPair,
        uint256 borrowingFee
    ) internal {
        if (borrowingFee != 0) {
            /// Increase the storage variable keeping track of the accumulated fees.
            borrowingFeeTokensHeld[feeToken] = borrowingFeeTokensHeld[feeToken].add(borrowingFee);

            emit PayBorrowingFee(user, feeToken, loanId, borrowingFee);

            /// Pay the token reward to the user.
            _payFeeReward(user, loanId, feeToken, feeTokenPair, borrowingFee);
        }
    }

_payLendingFee

Settle the lending fee (based on the interest). Pay no token reward to the user.

function _payLendingFee(address user, address feeToken, uint256 lendingFee) internal nonpayable

Arguments

Name Type Description
user address The address to send the reward to.
feeToken address The address of the token in which the lending fee is paid.
lendingFee uint256 The height of the fee.
Source Code
function _payLendingFee(
        address user,
        address feeToken,
        uint256 lendingFee
    ) internal {
        if (lendingFee != 0) {
            /// Increase the storage variable keeping track of the accumulated fees.
            lendingFeeTokensHeld[feeToken] = lendingFeeTokensHeld[feeToken].add(lendingFee);

            emit PayLendingFee(user, feeToken, lendingFee);

            //// NOTE: Lenders do not receive a fee reward ////
        }
    }

_settleFeeRewardForInterestExpense

function _settleFeeRewardForInterestExpense(struct LoanInterestStruct.LoanInterest loanInterestLocal, bytes32 loanId, address feeToken, address feeTokenPair, address user, uint256 interestTime) internal nonpayable

Arguments

Name Type Description
loanInterestLocal struct LoanInterestStruct.LoanInterest
loanId bytes32
feeToken address
feeTokenPair address
user address
interestTime uint256
Source Code
function _settleFeeRewardForInterestExpense(
        LoanInterest storage loanInterestLocal,
        bytes32 loanId,
        address feeToken,
        address feeTokenPair,
        address user,
        uint256 interestTime
    ) internal {
        /// This represents the fee generated by a borrower's interest payment.
        uint256 interestExpenseFee =
            interestTime
                .sub(loanInterestLocal.updatedTimestamp)
                .mul(loanInterestLocal.owedPerDay)
                .mul(lendingFeePercent)
                .div(1 days * 10**20);

        loanInterestLocal.updatedTimestamp = interestTime;

        if (interestExpenseFee != 0) {
            _payFeeReward(user, loanId, feeToken, feeTokenPair, interestExpenseFee);
        }
    }

_payFeeReward

Pay the potocolToken reward to user. The reward is worth 50% of the trading/borrowing fee.

function _payFeeReward(address user, bytes32 loanId, address feeToken, address feeTokenPair, uint256 feeAmount) internal nonpayable

Arguments

Name Type Description
user address The address to send the reward to.
loanId bytes32 The Id of the associeated loan - used for logging only.
feeToken address The address of the token in which the trading/borrowing fee was paid.
feeTokenPair address
feeAmount uint256 The height of the fee.
Source Code
function _payFeeReward(
        address user,
        bytes32 loanId,
        address feeToken,
        address feeTokenPair,
        uint256 feeAmount
    ) internal {
        uint256 rewardAmount;
        uint256 _feeRebatePercent = feeRebatePercent;
        address _priceFeeds = priceFeeds;

        if (specialRebates[feeToken][feeTokenPair] > 0) {
            _feeRebatePercent = specialRebates[feeToken][feeTokenPair];
        }

        /// Note: this should be refactored.
        /// Calculate the reward amount, querying the price feed.
        (bool success, bytes memory data) =
            _priceFeeds.staticcall(
                abi.encodeWithSelector(
                    IPriceFeeds(_priceFeeds).queryReturn.selector,
                    feeToken,
                    sovTokenAddress, /// Price rewards using BZRX price rather than vesting token price.
                    feeAmount.mul(_feeRebatePercent).div(10**20)
                )
            );
        // solhint-disable-next-line no-inline-assembly
        assembly {
            if eq(success, 1) {
                rewardAmount := mload(add(data, 32))
            }
        }

        // Check the dedicated SOV that is used to pay trading rebate rewards
        uint256 dedicatedSOV = ISovryn(address(this)).getDedicatedSOVRebate();
        if (rewardAmount != 0 && dedicatedSOV >= rewardAmount) {
            IERC20(sovTokenAddress).approve(lockedSOVAddress, rewardAmount);

            (bool success, ) =
                lockedSOVAddress.call(
                    abi.encodeWithSignature(
                        "deposit(address,uint256,uint256)",
                        user,
                        rewardAmount,
                        tradingRebateRewardsBasisPoint
                    )
                );

            if (success) {
                protocolTokenPaid = protocolTokenPaid.add(rewardAmount);

                emit EarnReward(
                    user,
                    sovTokenAddress,
                    loanId,
                    _feeRebatePercent,
                    rewardAmount,
                    tradingRebateRewardsBasisPoint
                );
            } else {
                emit EarnRewardFail(
                    user,
                    sovTokenAddress,
                    loanId,
                    _feeRebatePercent,
                    rewardAmount,
                    tradingRebateRewardsBasisPoint
                );
            }
        } else if (rewardAmount != 0 && dedicatedSOV < rewardAmount) {
            emit EarnRewardFail(
                user,
                sovTokenAddress,
                loanId,
                _feeRebatePercent,
                rewardAmount,
                tradingRebateRewardsBasisPoint
            );
        }
    }

Contracts