ERC-721 Enumeration: Bytecode → Readable Solidity

Decompiled with EVMDecompiler

Published on July 3, 2025

Abstract

We grabbed an NFT contract that never published its source, ran it through the decompiler, and rebuilt the classic wallet enumeration helper developers love to copy. Watching the while loop, memory allocation, and balance checks fall back into place reminds us why readable output matters for audits.

Here's what stood out while we pieced the function back together:

Original vs Decompiled

Original Implementation

function walletOfOwner(address _owner) public view returns (uint256[] memory) {
    uint256 ownerTokenCount = balanceOf(_owner);
    uint256[] memory ownedTokenIds = new uint256[](ownerTokenCount);
    uint256 currentTokenId = 1;
    uint256 ownedTokenIndex = 0;

    while (ownedTokenIndex < ownerTokenCount && currentTokenId <= supplyLimit) {
        address currentTokenOwner = ownerOf(currentTokenId);
        if (currentTokenOwner == _owner) {
            ownedTokenIds[ownedTokenIndex] = currentTokenId;
            ownedTokenIndex++;
        }
        currentTokenId++;
    }

    return ownedTokenIds;
}

Decompiled Output

function walletOfOwner(address _owner) public view returns (uint256[] memory) {
    uint256 ownerTokenCount = balanceOf(_owner);
    uint256[] memory ownedTokenIds = new uint256[](ownerTokenCount);
    uint256 currentTokenId = 1;
    uint256 ownedTokenIndex = 0;

    while (ownedTokenIndex < ownerTokenCount && currentTokenId <= maxSupply) {
        address currentTokenOwner = ownerOf(currentTokenId);
        if (currentTokenOwner == _owner) {
            ownedTokenIds[ownedTokenIndex] = currentTokenId;
            ownedTokenIndex++;
        }
        currentTokenId++;
    }

    return ownedTokenIds;
}

Why this matters

You see this pattern all over NFT projects. Getting the loop bounds, array allocation, and conditional writes right is how we spot off-by-one bugs or nasty gas bombs. The regenerated version keeps the original's intent but tightens the naming (maxSupply vs supplyLimit) so reviewers don't have to squint.

Decompilation approach

Takeaways