Skip to content
Back to skills

2606 Unchecked Return Values Ae8ce7f8

ASecurity

- Contract uses low-level calls: `.call()`, `.send()`, or `.delegatecall()` - The boolean return value indicating success/failure is not checked - State changes occur after the unchecked call, assuming it succeeded

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 31, 2026
designrust

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 31, 2026

npx -y skills add tools-only/X-Skills --skill 2606-unchecked-return-values_ae8ce7f8 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2606 Unchecked Return Values Ae8ce7f8?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2606 Unchecked Return Values Ae8ce7f8
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2606-unchecked-return-values-ae8ce7f8/badge)](https://www.skillsdirectory.com/skills/tools-only-2606-unchecked-return-values-ae8ce7f8)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Unchecked Return Values

## Preconditions
- Contract uses low-level calls: `.call()`, `.send()`, or `.delegatecall()`
- The boolean return value indicating success/failure is not checked
- State changes occur after the unchecked call, assuming it succeeded

## Vulnerable Pattern
```solidity
function withdraw(uint256 amount) external {
    // .send() returns false on failure but does NOT revert
    msg.sender.send(amount); // Return value ignored
    balances[msg.sender] -= amount; // State updated even if send failed
}

function payout(address to, uint256 amount) external {
    // .call() return value captured but never checked
    (bool success,) = to.call{value: amount}("");
    // success could be false, but execution continues
    totalPaid += amount;
}
```

## Detection Heuristics
1. Search for all `.call(`, `.send(`, `.delegatecall(` invocations
2. For each, check whether the returned boolean is captured AND checked (e.g., `require(success)`, `if (!success) revert`)
3. If the return value is captured but never referenced again, flag it
4. If the return value is not captured at all (e.g., bare `addr.send(amount);`), flag it
5. Check for state changes after unchecked calls — these create inconsistent state on silent failure

## False Positives
- Return value is checked with `require(success)` or equivalent
- The call is intentionally fire-and-forget (documented, no state depends on success) — rare but valid
- Using Solidity's high-level function calls (e.g., `IERC20(token).transfer(...)`) which auto-revert on failure

## Remediation
- Always check the return value: `require(success, "call failed")`
- For ETH transfers to untrusted recipients, consider a pull-payment pattern to avoid DoS if the recipient deliberately reverts
- Prefer high-level Solidity calls when interacting with known interfaces
```solidity
function withdraw(uint256 amount) external {
    balances[msg.sender] -= amount;
    (bool success,) = msg.sender.call{value: amount}("");
    require(success, "ETH transfer failed");
}
```

Files in this skill

  • README.md1.1 KB
  • skill.md2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.