DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: high
Invalid

Unrestricted Token Spending Due to Infinite Allowance Setting in Token Approval

Summary

The approve function in the LibTokenApprove library has a vulnerability where setting an allowance to type(uint256).max can lead to unrestricted and unchecked token transfers.

Vulnerability Details

The root cause of the issue is that the approve function allows setting the allowance to type(uint256).max. This effectively grants the spender infinite approval to transfer tokens on behalf of the owner, bypassing the need for future allowance updates and potentially leading to unchecked token transfers.

Proof of concept

Consider this scenario
1: Alice approves Bob to spend an infinite amount of tokens (by setting the allowance to type(uint256).max).

2: Bod can now transfer an unlimited number of tokens from Alice's account without any further approval.

3: Alice has no control over the transfers as the allowance remains effectively infinite

Impact

1: This wil lead to unchecked and potentially unauthorized token transfers, as the spender can continuously transfer tokens without the owner being able to intervene or limit the transfers.

2: The token owner will find it difficult to regain control over their tokens, leading to potential misuse and loss of assets

Tools Used

Manual Review

Recommendations

1: Implement a pattern where the current allowance is set to zero before updating it to a new value. This can prevent the spender from exploiting the allowance update process.

2: Prevent setting the allowance to type(uint256).max or any excessively large value.

3: Use functions like increaseAllowance and decreaseAllowance to adjust allowances incrementally, reducing the risk of setting overly large allowances.

Modified approveToken Function

function approveToken(
address spender,
IERC20 token,
uint256 amount
) external payable fundsSafu noNetFlow noSupplyChange nonReentrant {
require(amount != type(uint256).max, "Cannot set infinite allowance");
LibTokenApprove.approve(LibTractor._user(), spender, token, amount);
}

Modified LibTokenApprove.approve Function

function approve(address account, address spender, IERC20 token, uint256 amount) internal {
AppStorage storage s = LibAppStorage.diamondStorage();
uint256 currentAllowance = s.accts[account].tokenAllowances[spender][token];
// Safe approval pattern: Require allowance to be zero before setting a new value
if (currentAllowance != 0) {
require(currentAllowance == 0 || amount == 0, "Non-zero to non-zero allowance change");
}
s.accts[account].tokenAllowances[spender][token] = amount;
emit TokenApproval(account, spender, token, amount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.