Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write invariant test for tokenURI #519

Open
PaulRBerg opened this issue May 30, 2023 · 0 comments
Open

Write invariant test for tokenURI #519

PaulRBerg opened this issue May 30, 2023 · 0 comments
Labels
effort: high Large or difficult task. priority: 3 Nice-to-have. Willing to ship without this. type: test Adding, updating, or removing tests. work: complicated Sense-analyze-respond. The relationship between cause and effect requires analysis or expertise.

Comments

@PaulRBerg
Copy link
Member

Idea

It would be nice to add an invariant test for the tokenURI implemented in #440.

We could do it like this:

  • Install svglint as a Node.js dev dependency
  • Use vm.ffi to run pnpm svglint from within Solidity
  • Define an invariant test like the one in the code snippet below
  • Use Foundry's recently introduced inline test configuration to override the default number of runs - as this would be a heavy-load test, which would read and write content to files.

I have tried to write it myself now, but I encountered this bug in Foundry, so I will just mark this as "backlog" for the time being.

Code Snippet

import { Base64 } from "solady/utils/Base64.sol";
import { LibString } from "solady/utils/LibString.sol";

/// @dev Extracts the SVG from a base-64 encoded token URI.
function extractSVG(string memory uri) internal returns (string memory) {
    string memory decodedURI = string(Base64.decode(uri));
    string memory sanitizedURI = decodedURI.replace({ search: "data:application/json;base64,", replacement: "" });
    string memory image = vm.parseJsonString(sanitizedURI, ".image");
    string memory sanitizedImage = image.replace({ search: "data:image/svg+xml;base64,", replacement: "" });
    string memory svg = string(Base64.decode(sanitizedImage));
    return svg;
}

/// forge-config: default.invariant.depth = 1
/// forge-config: default.invariant.runs = 1
function invariant_TokenURI() external useCurrentTimestamp {
    uint256 lastStreamId = lockupStore.lastStreamId();
    for (uint256 i = 0; i < lastStreamId; ++i) {
        uint256 streamId = lockupStore.streamIds(i);

        // Skip burned NFTs.
        if (lockup.getRecipient(streamId) == address(0)) {
            continue;
        }

        string memory uri = lockup.tokenURI(streamId);
        string memory svg = extractSVG(uri);
        string memory filePath = "test/nft.svg";
        vm.writeFile(filePath, svg);

        string[] memory inputs = new string[](3);
        inputs[0] = "pnpm";
        inputs[1] = "svglint";
        inputs[2] = filePath;

        // TODO: check result
        bytes memory response = vm.ffi(inputs);
        console2.logBytes(response);
    }
}
@PaulRBerg PaulRBerg added effort: high Large or difficult task. type: test Adding, updating, or removing tests. work: complicated Sense-analyze-respond. The relationship between cause and effect requires analysis or expertise. priority: 3 Nice-to-have. Willing to ship without this. and removed backlog labels Jan 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort: high Large or difficult task. priority: 3 Nice-to-have. Willing to ship without this. type: test Adding, updating, or removing tests. work: complicated Sense-analyze-respond. The relationship between cause and effect requires analysis or expertise.
Projects
None yet
Development

No branches or pull requests

1 participant