Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Invalid

Silent ERC20 Transfer Failures Due to Ignored Return Values

Summary

Many smart contracts use ERC20's transfer() function but fail to check the return value. Some ERC20 tokens do not revert on failure but instead return false, leading to silent transaction failures.


Vulnerability Details

  1. Problem:

    • The ERC20 standard (EIP-20) allows transfer() and transferFrom() to return a boolean (true/false).

    • Some tokens (e.g., USDT/Tether) return false instead of reverting if a transfer fails.

    • If a contract ignores this return value, it assumes the transfer always succeeds, which can lead to incorrect balance updates.

  2. Example of Vulnerable Code:

    function pay(address token, address recipient, uint256 amount) external {
    IERC20(token).transfer(recipient, amount); // Return value ignored!
    }

    What Happens?

    • If the transfer fails (e.g., insufficient balance, frozen account), the function does not revert.

    • The contract assumes the payment was successful, leading to incorrect logic.


Impact

Low Severity: This does not directly break security but can cause incorrect accounting or logic errors.

Silent Transaction Failures – Funds may not be transferred, but the contract behaves as if they were.
Incorrect Balance Calculations – Contracts that rely on successful transfers may assume the wrong state.
Potential Fund Loss – Users may be misled into thinking they have received funds when they haven’t.


Tools Used

Manual Code Review – Check all transfer() and transferFrom() calls for return value verification.
Static Analysis (Slither, Mythril) – Detects missing return value checks.
Hardhat / Foundry Tests – Simulate transfers using non-reverting ERC20 tokens like USDT.


Recommendations

Use OpenZeppelin’s safeTransfer() Instead of transfer()

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
using SafeERC20 for IERC20;
function pay(address token, address recipient, uint256 amount) external {
IERC20(token).safeTransfer(recipient, amount); // ✅ Properly handles failures.
}

Manually Check Return Values (If Not Using OpenZeppelin)

bool success = IERC20(token).transfer(recipient, amount);
require(success, "Transfer failed"); // ✅ Ensures transfer actually worked.
Updates

Lead Judging Commences

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

[INVALID] SafeERC20 not used

LightChaser Low-60

Support

FAQs

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