The withdraw function in the Treasury contract currently uses the transfer method to send tokens to a recipient. However, this can cause issues with certain ERC-20 tokens like USDC and USDT, which do not revert on failure but instead return a boolean value. If the function does not check the return value of transfer, it may incorrectly assume that the transfer was successful even if it failed. This could lead to incorrect token accounting, leaving the contract in an inconsistent state where the recorded balances do not match the actual token balances.
Issue:
The function currently uses IERC20(token).transfer(recipient, amount); for token transfers.
Some ERC-20 tokens, such as USDC and USDT, do not revert on failure. Instead, they return false when a transfer fails.
The contract does not check the return value of transfer, so it assumes that the transfer always succeeds.
Problematic Code:
Root Cause:
The ERC-20 standard is loosely defined, and some implementations (such as USDC and USDT) return a boolean rather than reverting on failure.
The contract does not handle tokens that return a boolean, leading to possible silent failures in transfers.
Expected Behavior:
Instead of assuming the transfer always succeeds, the contract should explicitly check the return value and revert if the transfer fails.
Alternatively, it can use OpenZeppelin’s SafeERC20 library, which correctly handles different ERC-20 implementations.
Incorrect Token Accounting:
If a transfer fails and the contract does not detect it, the _balances state variable will be reduced even though the actual tokens remain in the contract. This creates an inconsistency between the contract’s internal state and the actual token balance.
Manual Code Review
Analysis of Non-Standard ERC-20 Implementations (USDC, USDT)
Use SafeERC20 for Transfers:
The best approach is to use OpenZeppelin’s SafeERC20 library, which ensures compatibility with tokens that return a boolean instead of reverting.
Fixed Code:
Manually Check the Return Value (Alternative Fix):
If avoiding external dependencies, explicitly check the return value of transfer and revert if it fails.
Alternative Code Fix:
LightChaser Low-60
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.