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

Withdrawal mechanism of `FM_Rebasing_v1` funding tokens can be Dos'd with dust withdrawals #39

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

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

Github username: -- Twitter username: -- Submission hash (on-chain): 0x3f4cafcadc21db7b63735832cdb260e99fd7b78ae7f6e2abbdf4e786e7f1126e Severity: medium

Description: Description

As the 'amount' value is not validated against a minimum amount, a potential attacker can make a large number of micro withdrawal requests such a 1e1 for a token with 1e18 decimals. As such they can prevent other users from withdrawing their assets. A resolution to this is implementing a minimum withdrawal amount, although this will need setter limits of it's own to prevent it from being changed to a number so high, no one can withdraw.

Attack Scenario

1) Bob want's to withdraw his tokens 2) Alice dos's the withdrawal mechanism with back to back 1e1 amount withdrawals 3) Each of these will need to be processed first before Bob can withdraw 4) Bob can't withdraw unless he is willing to pay an unbounded amount of Gas to have his withdrawal processed first

Attachments

  1. Proof of Concept (PoC) File

['140']

140:     function withdraw(uint amount) external {
141:         _withdraw(_msgSender(), _msgSender(), amount);
142:     }

['144']

144:     function withdrawTo(address to, uint amount) external {
145:         _withdraw(_msgSender(), to, amount);
146:     }

['179']

179:     function _withdraw(address from, address to, uint amount) internal {
180:         amount = _burn(from, amount);
181: 
182:         token().safeTransfer(to, amount);
183: 
184:         emit Withdrawal(from, to, amount);
185:     }
  1. Revised Code File (Optional)

This is a heavily simplified fix, the setting of minimumWithdraw should be bounded within reasonable limits to ensure it cannot be set to extream high or low values.

Instance 0

     function withdraw(uint amount) external {
++       require(amount >= minimumWithdraw, "amount too low");
         _withdraw(_msgSender(), _msgSender(), amount);
     }

Instance 1

     function withdrawTo(address to, uint amount) external {
++       require(amount >= minimumWithdraw, "amount too low");
         _withdraw(_msgSender(), to, amount);
     }

Global Changes


++  uint256 public minimumWithdraw;

    function init(
        IOrchestrator_v1 orchestrator_,
        Metadata memory metadata,
        bytes memory configData,
        uint256 minimumWithdraw_
    ) external override(Module_v1) initializer {

++      minimumWithdraw = minimumWithdraw_;
        __Module_init(orchestrator_, metadata);

        address orchestratorTokenAddress = abi.decode(configData, (address));
        _token = IERC20(orchestratorTokenAddress);

        string memory _id = orchestrator_.orchestratorId().toString();
        string memory _name = string(
            abi.encodePacked("Inverter Funding Token - Orchestrator_v1 #", _id)
        );
        string memory _symbol = string(abi.encodePacked("IFT-", _id));
        // Initial upstream contracts.
        __ElasticReceiptToken_init(
            _name, _symbol, IERC20Metadata(orchestratorTokenAddress).decimals()
        );
    }
0xmahdirostami commented 2 months ago

There is no issue here, Alice couldn't DOS Bob.