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.
Related Detectors
- ERC-721 Standard Violations — the single-token NFT equivalent
- Batch Operation Atomicity — partial-execution risks in batch flows
- Token Hook Reentrancy — reentrancy via token receiver callbacks
- Array Length Assumption — unvalidated parallel arrays in general