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

Flash loan fees are wholly awarded to the feeCollector to the detriment of depositors who contributed IBT tokens #17

Open
hats-bug-reporter bot opened this issue Nov 14, 2024 · 1 comment
Labels
bug Something isn't working invalid This doesn't seem right

Comments

@hats-bug-reporter
Copy link

Github username: --
Twitter username: --
Submission hash (on-chain): 0x5a5fa1c1a324a46705aac71c0fdee4745d9bed7bdcc5fd0e9a8d4c8c4ef8821f
Severity: high

Description:
Description
When a borrower borrows tokens from the protocol, they're lent IBT tokens that the PrincipalToken contract has:

function flashLoan(
        IERC3156FlashBorrower _receiver,
        address _token,
        uint256 _amount,
        bytes calldata _data
    ) external override whenNotPaused returns (bool) {
        if (_amount > maxFlashLoan(_token)) revert FlashLoanExceedsMaxAmount();

        uint256 fee = flashFee(_token, _amount);
        _updateFees(fee);

        // Initiate the flash loan by lending the requested IBT amount
        address _ibt = ibt;
        IERC20(_ibt).safeTransfer(address(_receiver), _amount);

        // Execute the flash loan
        if (_receiver.onFlashLoan(msg.sender, _token, _amount, fee, _data) != ON_FLASH_LOAN)
            revert FlashLoanCallbackFailed();

        // Repay the debt + fee
        IERC20(_ibt).safeTransferFrom(address(_receiver), address(this), _amount + fee);

        return true;
    }

These tokens actually come from depositors via deposit:

function deposit(
        uint256 assets,
        address ptReceiver,
        address ytReceiver
    ) public override nonReentrant returns (uint256 shares) {
        address _ibt = ibt;
        address _underlying = underlying_;
        IERC20(_underlying).safeTransferFrom(msg.sender, address(this), assets);
        IERC20(_underlying).safeIncreaseAllowance(_ibt, assets);
        uint256 ibts = IERC4626(_ibt).deposit(assets, address(this));
        shares = _depositIBT(ibts, ptReceiver, ytReceiver);
    }

or via depositIBT:

function depositIBT(
        uint256 ibts,
        address ptReceiver,
        address ytReceiver
    ) public override nonReentrant returns (uint256 shares) {
        IERC20(ibt).safeTransferFrom(msg.sender, address(this), ibts);
        shares = _depositIBT(ibts, ptReceiver, ytReceiver);
    }

The vulnerability arises from the fact that all fee collected is attributed to the feeCollector while depositors earn nothing. This amounts to lost revenue for depositors who actually provided all the tokens being lent out:

uint256 fee = flashFee(_token, _amount);
        _updateFees(fee);

Attack Scenario
Describe how the vulnerability can be exploited.

Attachments

  1. Proof of Concept (PoC) File
  1. Revised Code File (Optional)
    Provide flashloan fee sharing functionality that will also benefit depositors. This will also be an incentive for IBT token holders to use the protocol.
@hats-bug-reporter hats-bug-reporter bot added the bug Something isn't working label Nov 14, 2024
@yanisepfl yanisepfl added the invalid This doesn't seem right label Nov 15, 2024
@yanisepfl
Copy link
Collaborator

Hello,

We classified this issue as Invalid because what is described is the expected behaviour of our protocol.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

1 participant