Skip to main content
Sigvex

ERC-1155 Standard Violations

Detects ERC-1155 contracts missing receiver callbacks, batch array-length validation, ERC-165 support, or required functions.

ERC-1155 Standard Violations

Overview

Remediation Guide: ERC-1155 Standard Violations Remediation

The ERC-1155 violations detector classifies a contract as a multi-token by its selector surface (balanceOf, balanceOfBatch, safeTransferFrom, safeBatchTransferFrom, approval functions), then checks it against the standard. It reports six finding types with per-finding severities:

Finding Severity
Missing array-length validation in batch operations Critical
Missing required function High
Missing onERC1155Received check in safeTransferFrom High
Missing onERC1155BatchReceived check in safeBatchTransferFrom High
Potential reentrancy in safe transfer functions High
Missing ERC-165 supportsInterface / zero-address checks Medium

The array-length finding is the most severe: safeBatchTransferFrom takes parallel ids[] and amounts[] arrays, and skipping the length-equality check lets a caller pass mismatched arrays — reading out of bounds or transferring unintended amounts.

Why This Is an Issue

ERC-1155’s batch semantics are strict: transfers must be atomic, arrays must be parallel, and recipients that are contracts must acknowledge receipt via the receiver callbacks. Violating any of these breaks integrations and loses tokens. A missing onERC1155BatchReceived check means every batch transfer to a non-receiver contract permanently locks the tokens. A missing length check turns the batch interface into a memory-safety bug. And because both receiver callbacks hand execution to the recipient, a transfer that writes balances after the callback is re-enterable while balances are stale.

How to Resolve

// Before: no length check, no receiver callback
function safeBatchTransferFrom(
    address from, address to,
    uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data
) external {
    for (uint256 i = 0; i < ids.length; i++) {
        balances[ids[i]][from] -= amounts[i];
        balances[ids[i]][to] += amounts[i];
    }
}

// After: lengths validated, effects before the callback, receipt verified
function safeBatchTransferFrom(
    address from, address to,
    uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data
) external {
    require(to != address(0), "zero address");
    require(ids.length == amounts.length, "length mismatch");
    for (uint256 i = 0; i < ids.length; i++) {
        balances[ids[i]][from] -= amounts[i];
        balances[ids[i]][to] += amounts[i];
    }
    emit TransferBatch(msg.sender, from, to, ids, amounts);
    if (to.code.length > 0) {
        require(
            IERC1155Receiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data)
                == IERC1155Receiver.onERC1155BatchReceived.selector,
            "unsafe recipient"
        );
    }
}

Inheriting an audited implementation (OpenZeppelin ERC1155) covers all six checks.

Examples

Sample Sigvex Output

{
  "detector_id": "erc1155-violations",
  "severity": "critical",
  "confidence": 0.8,
  "description": "Missing array length validation in safeBatchTransferFrom: ids[] and amounts[] lengths are never compared before the transfer loop.",
  "location": { "function": "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)", "offset": 0 }
}

Detection Methodology

Selectors are matched against the canonical ERC-1155 and ERC-165 tables. For each safe-transfer function, the detector inspects the body for an external call carrying the appropriate receiver-callback selector, a length-equality branch over the two calldata arrays, zero-address guards, and the ordering of balance writes relative to the callback. Per-finding confidences (roughly 0.75–0.85) account for implementations split across proxy layers or parent libraries.

Limitations

  • Proxies are scanned as deployed; a callback check living in the implementation contract is not visible from the proxy bytecode alone.
  • ERC-165 declarations in a parent or library may be flattened in ways the selector scan misses, so that finding fires at reduced confidence.
  • Event topic/index correctness is only partially verifiable from bytecode.

References