openzeppelin-contracts icon indicating copy to clipboard operation
openzeppelin-contracts copied to clipboard

Feature request: `Base64.decode`

Open PaulRBerg opened this issue 2 years ago • 4 comments

The current Base64 library offers support only for base64 encoding:

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/5420879d9b834a0579423d668fb60c5fc13b60cc/contracts/utils/Base64.sol

However, with the advent of Foundry, there's also the need for decoding base64-encoded strings in test files.

At the moment, OpenZeppelin users are forced to go look for a solution elsewhere, e.g. in Solady, which provides both encoding and decoding.

It would thus be helpful to provide a decode function on top of encode.

PaulRBerg avatar May 29 '23 09:05 PaulRBerg

Interesting, thanks for sharing.

However, with the advent of Foundry, there's also the need for decoding base64-encoded strings in test files.

Is the idea that you would do this to test the output of one of your functions that uses Base64.encode? Or is there some other reason you would use decode?

frangio avatar May 29 '23 13:05 frangio

Interesting, thanks for sharing.

Happy to give back to the community.

Is the idea that you would do this to test the output of one of your functions that uses Base64.encode?

Yes; this is the use case:

/// @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;
}

PaulRBerg avatar May 29 '23 20:05 PaulRBerg

I see. We will consider this request, but in the meantime I want to share a thought.

The main goal of OpenZeppelin Contracts is to provide secure code for production use, and achieving that goal requires heavy investment and focus. As Solidity becomes more used as a language for Foundry testing and scripting, there are new use cases for Solidity libraries (like the one in this issue) that have less strict security requirements. It isn't practical or necessary to make the same level of investment into that kind of code, so I wonder if those should coexist in the same library.

frangio avatar May 29 '23 21:05 frangio

Interesting, thanks for sharing.

Happy to give back to the community.

Is the idea that you would do this to test the output of one of your functions that uses Base64.encode?

Yes; this is the use case:

/// @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; }

you can use solady: https://github.com/Vectorized/solady/blob/8d868a936ec1a45be294e26de1a64ebfb73c6c20/src/utils/Base64.sol

lilyanB avatar Apr 09 '25 12:04 lilyanB