hats-finance / Spectra-0x4b792db3d2a5d1c1ccf9938380756b200c240e5d

Other
0 stars 1 forks source link

Is not following the SafeERC20 rule. #20

Open hats-bug-reporter[bot] opened 1 week ago

hats-bug-reporter[bot] commented 1 week ago

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

Description:

Description

The Router.sol contract does not implementing the SafeERC20::forceApprove() correctly. As per the SafeERC20::forceApprove() natspec the dev must need to set the allowance to 0 before using forceApprove(), see it here:

Meant to be used with tokens that require the approval
to be set to zero before setting it to a non-zero value, such as USDT

So if USDT is used as token here so the approval should be set to 0 before applying the forceApprove.

Affected code

if (allowance < repayAmount) {
            // Approve the lender to pull the funds if needed
            IERC20(_token).forceApprove(msg.sender, repayAmount);
}

PoC

https://github.com/hats-finance/Spectra-0x4b792db3d2a5d1c1ccf9938380756b200c240e5d/blob/d245fd66e864670457c3d5652ddc1bcd0e6068eb/src/router/Router.sol#L280-L283

yanisepfl commented 1 week ago

Hello,

We classified this issue as Invalid.

Indeed, the SafeERC20::forceApprove() function is explicitly designed to handle tokens like USDT that require the allowance to be reset to zero before setting it to a new value. Its implementation ensures that the intermediate step of setting the allowance to zero is automatically handled. Thus, developers do not need to manually set the allowance to zero when using forceApprove().

When forceApprove() is invoked, it does the following:

This behavior satisfies the requirements of tokens like USDT without requiring additional manual intervention from the us.

The NatSpec comment in SafeERC20::forceApprove() was misunderstood by the reporter. Indeed, it explains the purpose of the method but does not imply that we need to explicitly call approve(0) before using forceApprove(). The method encapsulates this behavior internally.

Thanks