# 56658 sc insight transmuter s tokenuri does not revert for nonexistent tokenids

**Submitted on Oct 19th 2025 at 02:53:26 UTC by @tygra for** [**Audit Comp | Alchemix V3**](https://immunefi.com/audit-competition/alchemix-v3-audit-competition)

* **Report ID:** #56658
* **Report Type:** Smart Contract
* **Report severity:** Insight
* **Target:** <https://github.com/alchemix-finance/v3-poc/blob/immunefi\\_audit/src/Transmuter.sol>
* **Impacts:**
  * Contract fails to deliver promised returns, but doesn't lose value

## Description

## Brief/Intro

NFTs the Transmuter mints to represent redemptions have a `tokenURI` method, but this differs from the EIP-721 spec as it does not revert for invalid tokenIds.

## Vulnerability Details

The method in question, `tokenURI` calls NFTMetadataGenerator.generateTokenURI in order to return an SVG to describe NFT identified by the requested tokenID.

```
// Transmuter.sol
    function tokenURI(uint256 id) public view override returns (string memory) {
        return NFTMetadataGenerator.generateTokenURI(id, "Transmuter V3 Position");
    }

// NFTMetadataGenerator.sol
    function generateTokenURI(uint256 tokenId, string memory title) internal pure returns (string memory) {
        string memory svg = generateSVG(tokenId, title);
        string memory json = generateJSONString(tokenId, svg);
        return string(abi.encodePacked("data:application/json;base64,", json));
    }

```

Nowhere is the `tokenURI` validated, consequently the contract will return an SVG for nonexistent tokenIDs.

This differs from EIP-721's definition of contracts that implement a `tokenURI` method such that Transmuter.sol fails to deliver the expected behaviour for an EIP-721 compliant contract that includes token metadata.

```
    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
    ///  3986. The URI may point to a JSON file that conforms to the "ERC721
    ///  Metadata JSON Schema".
    function tokenURI(uint256 _tokenId) external view returns (string);
```

## Impact Details

There is no risk of any customer funds being affected. The risk of not reverting for invalid tokenIDs is that onchain or offchain programs attempting to fetch the metadata for a given tokenID can incorrectly believe a tokenID exists due to metadata always being returned.

## References

<https://eips.ethereum.org/EIPS/eip-721>

## Proof of Concept

## Proof of Concept

Add this test to Transmuter.t.sol

```
    function test_tokenURI() public {
        string memory str = transmuter.tokenURI(1e16);
        console.log(str);
    }
```

It returns the following metadata even though token #1e16 does not exist

{"name": "AlchemistV3 Position #10000000000000000", "description": "Position token for Alchemist V3", "image": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMDAgNDg0IiB3aWR0aD0iMzAwIiBoZWlnaHQ9IjQ4NCI+PHJlY3Qgd2lkdGg9IjMwMCIgaGVpZ2h0PSI0ODQiIGZpbGw9IiNkNGMzYjciIC8+PGNpcmNsZSBjeD0iMTUwIiBjeT0iMTUwIiByPSIxMjAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzBhM2E2MCIgc3Ryb2tlLXdpZHRoPSI0IiAvPjx0ZXh0IHg9IjE1MCIgeT0iMTIwIiBmb250LWZhbWlseT0iQXJpYWwiIGZvbnQtc2l6ZT0iMjQiIGZpbGw9IiMwYTNhNjAiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlRyYW5zbXV0ZXIgVjMgUG9zaXRpb248L3RleHQ+PHRleHQgeD0iMTUwIiB5PSIxNTAiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIyOCIgZmlsbD0iIzBhM2E2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC13ZWlnaHQ9ImJvbGQiPlBvc2l0aW9uPC90ZXh0Pjx0ZXh0IHg9IjE1MCIgeT0iMTkwIiBmb250LWZhbWlseT0ibW9ub3NwYWNlIiBmb250LXNpemU9IjI0IiBmaWxsPSIjMGEzYTYwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4jMTAwMDAwMDAwMDAwMDAwMDA8L3RleHQ+PC9zdmc+"}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://reports.immunefi.com/alchemix-v3/56658-sc-insight-transmuter-s-tokenuri-does-not-revert-for-nonexistent-tokenids.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
