hats-finance / Inverter-Network-0xe47e52c4fea05e555920f1dcdcc6fb8eca103eeb

Fork of the Inverter Smart Contracts Repository
GNU Lesser General Public License v3.0
0 stars 3 forks source link

Block-list tokens are un-sellable due to msg.sender hardcoding #52

Open hats-bug-reporter[bot] opened 3 months ago

hats-bug-reporter[bot] commented 3 months ago

Github username: @PlamenTSV Twitter username: @p_tsanev Submission hash (on-chain): 0x314a2162070e25d8efeb5fdde4a581788be97df0b376b2e703b8b59c760e615f Severity: low

Description: Description\ The RedeemingBondingCurveBase_v1.sol is a part of the Funding Manager Module and involves locking up collateral for minting issuance tokens. It allows to buy/sell for the user himself and buyFor/sellFor to buy on behalf of someone else. However, block-list ERC20's could make collateral unredeemable for certain users, due to the hardcoded msg.sender address.

Attack Scenario\ This occurs inside _sellOrder and sellFor. _sellOrder takes as parameters a receiver who will be the address whose balance is lowered and collateral transfered to. Due to the function sellFor passing the msg.sender as the receiver, instead of letting the user provide a destination address, the collateral can remain stuck if the msg.sender is blocked by these tokens (USDC, USDT most notably)

Attachments

  1. Proof of Concept (PoC) File

  2. Revised Code File (Optional)

    
    -function sell(uint _depositAmount, uint _minAmountOut) public virtual {
    -        sellFor(_msgSender(), _depositAmount, _minAmountOut);
    -}
    +function sell(uint _depositAmount, uint _minAmountOut, address receiver) public virtual {
    +        sellFor(_msgSender(), receiver, _depositAmount, _minAmountOut);
    +    }

function _sellOrder(

The mitigation is as simple as letting users provide a different destination of their choosing. Then set the tokens to be burned from the hardcoded msg.sender, but the collateral to be sent to the given destination. In our case we add a holder=msg.sender and keep the receiver as a standalone variable.

0xRizwan commented 3 months ago

In such case, User can directly call sellFor() which has _receiver param.

    function sellFor(address _receiver, uint _depositAmount, uint _minAmountOut)

Issuance tokens will be burned from sellFor() function caller:

221        // Burn issued token from user
222        _burn(_msgSender(), _depositAmount);

and the passed receiver in sellFor() can get the collateral/USDC/USDT.

259         // Transfer tokens to receiver
260        collateralToken.transfer(_receiver, collateralRedeemAmount);

Correct me, if i am missing something

PlamenTSV commented 3 months ago

Correct, but it deems the regular sell function useless, thus the severity.

0xRizwan commented 3 months ago

Its actually not usless. sell() is for self transferandsellFor()` is desired destination address transfer. Its intended functionality for users.

PlamenTSV commented 3 months ago

I just showcase how said functionality doesn't work in an edge-case scenario.

FHieser commented 2 months ago

I would say invalid, as sellFor() allows for targeted address

0xmahdirostami commented 2 months ago

@FHieser @0xRizwan thanks, yes its invalid