Skip to content
This repository has been archived by the owner on Dec 17, 2023. It is now read-only.

kutugu - SafeApprove require allowance is zero #13

Closed
sherlock-admin opened this issue Jun 11, 2023 · 1 comment
Closed

kutugu - SafeApprove require allowance is zero #13

sherlock-admin opened this issue Jun 11, 2023 · 1 comment
Labels
Non-Reward This issue will not receive a payout

Comments

@sherlock-admin
Copy link
Contributor

sherlock-admin commented Jun 11, 2023

kutugu

medium

SafeApprove require allowance is zero

Summary

SafeApprove require allowance is zero, should use forceApprove instead of safeApprove.

Vulnerability Detail

For flashLoan, when repay contract will approve ironBank.

        IERC20(token).safeTransferFrom(address(receiver), address(this), amount);

        uint256 allowance = IERC20(token).allowance(address(this), ironBank);
        if (allowance < amount) {
            IERC20(token).safeApprove(ironBank, type(uint256).max);
        }

        IronBankInterface(ironBank).repay(address(this), address(this), token, amount);

It starts with allowance of 0, which is less than repay amount, so it will approve ironBank type(uint256).max.
Over a long period of flashloan, allowance is gradually reduced until it is eventually less than the repay amount, but greater than 0. Note that flashloan only limits tokens to market ERC20 tokens(any vanilla ERC20s), it does not specify transferFrom won't reduce an allowance of type(uint256).max.
When safeApprove is called again, due to the fact that allowance is not 0, the call will revert, and this token cannot be loaned thereafter, so it can be considered as permanent dos.

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

Of course since type(uint256).max is a huge number which is fine for most tokens for a long time. But note again that the totalSupply of market tokens can be large, which has no limit.

Impact

Medium. If allowance is reduced to less than repay amount, flashloan this market token is not available.

Code Snippet

https://github.com/sherlock-audit/2023-05-ironbank/blob/main/ib-v2/src/flashLoan/FlashLoan.sol#L108

Tool used

Manual Review

Recommendation

use forceApprove instead of safeApprove.

Duplicate of #420

@github-actions github-actions bot added Medium A valid Medium severity issue Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label labels Jun 19, 2023
@sherlock-admin sherlock-admin added Non-Reward This issue will not receive a payout and removed Medium A valid Medium severity issue Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label labels Jun 25, 2023
@0xffff11
Copy link
Collaborator

0xffff11 commented Jul 3, 2023

See the comments in the main issue. Not approving from non 0 to another value. Invalid

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Non-Reward This issue will not receive a payout
Projects
None yet
Development

No branches or pull requests

2 participants