Skip to main content
ClaudeWave
Skill109 estrellas del repoactualizado 2mo ago

external-call-safety

Detects unsafe external call patterns and token integration vulnerabilities in smart contracts. Covers unchecked call/delegatecall/staticcall return values, fee-on-transfer tokens, rebasing tokens, tokens with missing return values (USDT), ERC-777 callback risks, unsafe approve race conditions, return data bombs, gas stipend limitations, and push vs pull payment patterns. Use when auditing contracts that interact with external contracts, integrate arbitrary ERC20 tokens, distribute payments, or make low-level calls.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/quillai-network/quillshield_skills /tmp/external-call-safety && cp -r /tmp/external-call-safety/plugins/external-call-safety/skills/external-call-safety ~/.claude/skills/external-call-safety
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# External Call Safety

Detect vulnerabilities arising from **unsafe interactions with external contracts** and **non-standard token behaviors** that break protocol assumptions. Covers OWASP SC06 (Unchecked External Calls) plus the entire "weird ERC20" problem space.

## When to Use

- Auditing any contract that calls external contracts (token transfers, cross-contract interactions)
- Reviewing protocols that support arbitrary/user-supplied ERC20 tokens
- Analyzing ETH payment distribution logic (airdrops, reward distribution, refunds)
- Verifying low-level call safety (`call`, `delegatecall`, `staticcall`)
- When a protocol claims to support "any ERC20 token"

## When NOT to Use

- Reentrancy-specific analysis (use reentrancy-pattern-analysis — though there is overlap)
- Oracle/price feed analysis (use oracle-flashloan-analysis)
- Pure access control review (use semantic-guard-analysis)

## Part 1: External Call Safety

### Vulnerability Class 1: Unchecked Return Values

Low-level calls (`call`, `delegatecall`, `staticcall`) return a boolean indicating success. If unchecked, failed calls are silently ignored.

```solidity
// VULNERABLE: Return value not checked
function withdraw(uint256 amount) external {
    balances[msg.sender] -= amount;
    payable(msg.sender).call{value: amount}(""); // Can fail silently!
    // User's balance decreased but ETH not sent
}

// SAFE: Check return value
function withdraw(uint256 amount) external {
    balances[msg.sender] -= amount;
    (bool success, ) = payable(msg.sender).call{value: amount}("");
    require(success, "Transfer failed");
}
```

**Detection Algorithm:**

```
For each low-level call expression:
  1. Is the return value captured? (bool success, bytes memory data) = ...
  2. Is the success boolean checked? require(success) or if(!success) revert
  3. If not captured or not checked → UNCHECKED RETURN VALUE

Severity:
  - ETH transfer unchecked → CRITICAL (funds lost)
  - Token operation unchecked → HIGH (state desync)
  - Non-financial call unchecked → MEDIUM
```

### Vulnerability Class 2: Gas Stipend Limitations

```solidity
// DANGEROUS: transfer() and send() forward only 2300 gas
payable(recipient).transfer(amount); // Reverts if recipient needs > 2300 gas
payable(recipient).send(amount);     // Returns false, often unchecked

// SAFE: Use call() with gas
(bool success, ) = payable(recipient).call{value: amount}("");
require(success, "Transfer failed");
```

**Why 2300 gas is dangerous:**
- Contracts with `receive()` or `fallback()` that do more than emit an event will fail
- EIP-1884 changed `SLOAD` gas cost, breaking some existing contracts
- Multi-sig wallets and smart contract wallets often need more gas

### Vulnerability Class 3: Return Data Bomb

A malicious contract can return extremely large data to consume the caller's gas.

```solidity
// Vulnerable to return data bomb
(bool success, bytes memory data) = untrustedContract.call(calldata);
// If untrustedContract returns 1MB of data, copying it costs massive gas

// SAFE: Limit return data or ignore it
(bool success, ) = untrustedContract.call(calldata); // Ignore return data
// Or use assembly to limit return data size
```

### Vulnerability Class 4: Delegatecall to Untrusted Contract

```solidity
// CRITICAL: delegatecall executes untrusted code in OUR storage context
function execute(address target, bytes calldata data) external {
    target.delegatecall(data); // Untrusted code can overwrite ANY storage
}

// delegatecall should ONLY be used with trusted, immutable targets
```

## Part 2: Token Integration Safety ("Weird ERC20" Tokens)

### Issue 1: Fee-on-Transfer Tokens

Some tokens deduct a fee during `transfer()` and `transferFrom()`. The recipient receives less than the specified amount.

```solidity
// VULNERABLE: Assumes received amount equals input amount
function deposit(uint256 amount) external {
    token.transferFrom(msg.sender, address(this), amount);
    balances[msg.sender] += amount; // Credits MORE than actually received!
}

// SAFE: Check actual balance change
function deposit(uint256 amount) external {
    uint256 balanceBefore = token.balanceOf(address(this));
    token.transferFrom(msg.sender, address(this), amount);
    uint256 balanceAfter = token.balanceOf(address(this));
    uint256 actualReceived = balanceAfter - balanceBefore;
    balances[msg.sender] += actualReceived; // Credits actual amount
}
```

**Known fee-on-transfer tokens:** STA, PAXG, USDT (fee currently 0 but can be activated), RFI/SAFEMOON forks.

### Issue 2: Rebasing Tokens

Rebasing tokens change all balances proportionally without transfers. Protocol's accounting desynchronizes from actual balances.

```solidity
// VULNERABLE: Stores absolute balance amounts
function deposit(uint256 amount) external {
    token.transferFrom(msg.sender, address(this), amount);
    userDeposit[msg.sender] = amount; // After rebase, actual balance differs!
}

// Mitigation options:
// 1. Store shares instead of amounts
// 2. Wrap rebasing token (wstETH pattern)
// 3. Explicitly state: "rebasing tokens not supported"
```

**Known rebasing tokens:** stETH, AMPL, OHM, YAM, BASED.

### Issue 3: Missing Return Values

Some tokens don't return a boolean from `transfer()`/`transferFrom()`/`approve()`, breaking the ERC20 standard.

```solidity
// VULNERABLE: Assumes return value exists
bool success = token.transfer(recipient, amount); // Reverts if token returns nothing

// SAFE: Use SafeERC20
using SafeERC20 for IERC20;
token.safeTransfer(recipient, amount); // Handles missing return values
```

**Known tokens with missing returns:** USDT, BNB, OMG, KNC (legacy versions).

### Issue 4: Tokens with Callbacks (ERC-777)

ERC-777 tokens trigger `tokensToSend()` on the sender and `tokensReceived()` on the recipient during transfers, enabling reentrancy.

```
ERC-777 callback hooks:
  transfer() → calls tokensReceived() on recipient
  transferFrom() → calls tokensToSend() on sender, tokensReceived() on recipi
behavioral-state-analysisSkill

Token-efficient smart contract security auditing via Behavioral State Analysis (BSA). Scopes analysis to contract type, runs only relevant threat engines, and uses tiered output depth. Use for auditing smart contracts, security reviews, or DeFi threat modeling.

defenderSkill

Blue-team release-gate analysis for smart contract deployment and upgrade readiness. Classifies repositories, checks deploy/upgrade execution paths, CI/CD trust boundaries, config drift, secrets/signer operational security, and outputs evidence-backed release verdicts.

dos-griefing-analysisSkill

Detects Denial of Service and griefing vulnerabilities in smart contracts. Covers unbounded loop DoS, block gas limit exhaustion, external call failure DoS, insufficient gas griefing (63/64 rule), storage bloat attacks, timestamp griefing, self-destruct force-feeding, and push vs pull payment pattern analysis. Use when auditing contracts with batch operations, loops over user data, reward distribution, dividend systems, or any logic that depends on address(this).balance or iterates over growing collections.

input-arithmetic-safetySkill

Detects input validation failures and arithmetic vulnerabilities in smart contracts. Covers missing zero-address and zero-amount checks, division-before-multiplication precision loss, rounding direction exploitation, ERC4626 vault share inflation attacks, unsafe integer casting, dust amount exploitation, and Solidity 0.8+ unchecked block edge cases. Use when auditing contracts with fee calculations, share pricing, exchange rates, unchecked blocks, or any public-facing functions that accept user input.

oracle-flashloan-analysisSkill

Detects price oracle manipulation and flash loan attack vectors in DeFi smart contracts. Classifies oracle trust models (Chainlink, TWAP, spot price, custom), identifies stale price risks, circular price dependencies, and flash loan atomicity exploitation patterns. Use when auditing DeFi protocols that depend on price data, oracle integrations, lending protocols, DEXs, derivatives, or any contract where flash loans could manipulate state within a single transaction.

proxy-upgrade-safetySkill

Detects vulnerabilities in upgradeable proxy smart contracts including storage layout collisions, uninitialized implementations, function selector clashing, delegatecall context issues, and upgrade path safety. Covers Transparent Proxy, UUPS (EIP-1822), Beacon, Diamond (EIP-2535), and Minimal Proxy (EIP-1167) patterns. Use when auditing upgradeable contracts, reviewing implementation upgrades, analyzing delegatecall architectures, or verifying proxy pattern compliance.

reentrancy-pattern-analysisSkill

Systematically detects all reentrancy vulnerability variants in smart contracts — classic, cross-function, cross-contract, and read-only reentrancy. Builds call graphs, verifies CEI (Checks-Effects-Interactions) pattern compliance, traces state changes relative to external calls, and identifies callback vectors through ERC-777/ERC-1155 hooks. Use when auditing contracts that make external calls, transfer ETH or tokens, interact with callback-enabled standards, or have complex multi-contract architectures.

semantic-guard-analysisSkill

Detects logic vulnerabilities in smart contracts by analyzing guard-state consistency patterns. Identifies functions that bypass security checks (require, modifiers) that other functions consistently apply. Uses the Consistency Principle — a contract is its own specification. Use when auditing smart contracts for missing access controls, inconsistent pause checks, logic bugs, forgotten modifiers, or when traditional tools report no issues but logic errors may exist.