-
-
Save Vectorized/e4b5736fdd24c32fb98b790f1bb36bfe to your computer and use it in GitHub Desktop.
Solidity Base64 Encode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
// Author: vectorized.eth | |
pragma solidity ^0.8.0; | |
library Base64 { | |
function encode(bytes memory data) internal pure returns (string memory result) { | |
// Inspired by (https://github.com/Brechtpd/base64/blob/main/base64.sol) | |
// by Brecht Devos - <brecht@loopring.org>. MIT licensed. | |
assembly { | |
let dataLength := mload(data) | |
if dataLength { | |
// Set `result` to point to the start of the free memory. | |
result := mload(0x40) | |
// Write the length of the string: `ceil(dataLength / 3.0 * 4.0)`. | |
mstore(result, shl(2, div(add(dataLength, 2), 3))) | |
// Store the table into the scratch space. | |
// Offsetted by -1 byte so that the `mload` will load the character. | |
// We will overwrite the free memory pointer at `0x40` later | |
// to allocate memory for the string. | |
mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef") | |
mstore(0x3f, "ghijklmnopqrstuvwxyz0123456789+/") | |
// Skip the first slot, which stores the length. | |
let ptr := add(result, 0x20) | |
let end := add(ptr, mload(result)) | |
// Run over the input, 3 bytes at a time. | |
// prettier-ignore | |
for {} iszero(eq(ptr, end)) {} { | |
// Advance 3 bytes. | |
data := add(data, 3) | |
let input := mload(data) | |
// Write 4 characters. | |
mstore8(ptr, mload(and(shr(18, input), 0x3F))) | |
ptr := add(ptr, 1) | |
mstore8(ptr, mload(and(shr(12, input), 0x3F))) | |
ptr := add(ptr, 1) | |
mstore8(ptr, mload(and(shr( 6, input), 0x3F))) | |
ptr := add(ptr, 1) | |
mstore8(ptr, mload(and( input, 0x3F))) | |
ptr := add(ptr, 1) | |
} | |
// Padding with '='. We can simply write over the end. | |
let paddingOffset := byte(mod(dataLength, 3), "\x00\x02\x01") | |
mstore(sub(ptr, paddingOffset), "==") | |
// Updates the free memory pointer to allocate memory for the string. | |
// Add 32 to ensure a minimum of 1 32-byte word allocated. | |
// Then mask with ~31 to round down to a multiple of 32. | |
mstore(0x40, and(add(end, 32), not(0x1f))) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment