Skip to main content
Sigvex

Short Address Attack Remediation

Validate calldata length on token transfers so truncated addresses cannot left-shift the amount parameter.

Short Address Attack Remediation

Overview

The ABI encoder zero-pads missing calldata bytes on the right. If a caller submits a 19-byte address (dropping a trailing 0x00), the decoder shifts the following amount parameter left by 8 bits, multiplying the transfer by 256. The fix is to verify that calldata is at least as long as the encoded parameters before acting on the decoded values.

Related Detector: Short Address Attack

Before (Vulnerable)

function transfer(address to, uint256 amount) public returns (bool) {
    require(balances[msg.sender] >= amount);
    balances[msg.sender] -= amount;
    balances[to] += amount;
    return true;
}

After (Fixed)

function transfer(address to, uint256 amount) public returns (bool) {
    require(msg.data.length >= 68, "Invalid calldata length"); // 4 + 32 + 32
    require(balances[msg.sender] >= amount);
    balances[msg.sender] -= amount;
    balances[to] += amount;
    return true;
}

The length check (4 selector bytes plus two 32-byte words) rejects any call where the encoder would have padded a truncated argument, so the decoded amount can never be silently scaled by missing bytes.

Alternative Mitigations

  • Compile with a recent Solidity release. Versions since 0.5.0 emit automatic calldata-length validation, which removes this attack for normally compiled contracts. Upgrading is the most durable fix.
  • Validate inputs at the user-facing boundary (wallet, frontend, relayer) so malformed addresses never reach the contract — though on-chain validation must remain the authoritative line of defense.
  • Avoid hand-rolled inline-assembly ABI decoding, which is where modern contracts most often reintroduce this gap.

Common Mistakes

  • Adding the length check only to transfer while leaving transferFrom, approve, and other multi-argument functions unguarded.
  • Using a strict == comparison on msg.data.length, which breaks legitimate callers that append extra data (for example, ERC-2771 meta-transaction suffixes). Use >= against the minimum.
  • Assuming a modern compiler protects forwarded calls in a proxy; calldata relayed via DELEGATECALL may bypass checks the implementation expects.

References