BugcatCodexRenderer

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "@ensdomains/ens-contracts/contracts/registry/ENS.sol": {
      "content": "//SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

interface ENS {
    // Logged when the owner of a node assigns a new owner to a subnode.
    event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);

    // Logged when the owner of a node transfers ownership to a new account.
    event Transfer(bytes32 indexed node, address owner);

    // Logged when the resolver for a node changes.
    event NewResolver(bytes32 indexed node, address resolver);

    // Logged when the TTL of a node changes
    event NewTTL(bytes32 indexed node, uint64 ttl);

    // Logged when an operator is added or removed.
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    function setRecord(
        bytes32 node,
        address owner,
        address resolver,
        uint64 ttl
    ) external;

    function setSubnodeRecord(
        bytes32 node,
        bytes32 label,
        address owner,
        address resolver,
        uint64 ttl
    ) external;

    function setSubnodeOwner(
        bytes32 node,
        bytes32 label,
        address owner
    ) external returns (bytes32);

    function setResolver(bytes32 node, address resolver) external;

    function setOwner(bytes32 node, address owner) external;

    function setTTL(bytes32 node, uint64 ttl) external;

    function setApprovalForAll(address operator, bool approved) external;

    function owner(bytes32 node) external view returns (address);

    function resolver(bytes32 node) external view returns (address);

    function ttl(bytes32 node) external view returns (uint64);

    function recordExists(bytes32 node) external view returns (bool);

    function isApprovedForAll(
        address owner,
        address operator
    ) external view returns (bool);
}
"
    },
    "@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

interface INameResolver {
    event NameChanged(bytes32 indexed node, string name);

    /// Returns the name associated with an ENS node, for reverse records.
    /// Defined in EIP181.
    /// @param node The ENS node to query.
    /// @return The associated name.
    function name(bytes32 node) external view returns (string memory);
}
"
    },
    "@ensdomains/ens-contracts/contracts/reverseRegistrar/IReverseRegistrar.sol": {
      "content": "pragma solidity >=0.8.4;

interface IReverseRegistrar {
    function setDefaultResolver(address resolver) external;

    function claim(address owner) external returns (bytes32);

    function claimForAddr(
        address addr,
        address owner,
        address resolver
    ) external returns (bytes32);

    function claimWithResolver(
        address owner,
        address resolver
    ) external returns (bytes32);

    function setName(string memory name) external returns (bytes32);

    function setNameForAddr(
        address addr,
        address owner,
        address resolver,
        string memory name
    ) external returns (bytes32);

    function node(address addr) external pure returns (bytes32);
}
"
    },
    "@openzeppelin/contracts/utils/Base64.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/Base64.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides a set of functions to operate with Base64 strings.
 */
library Base64 {
    /**
     * @dev Base64 Encoding/Decoding Table
     * See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648
     */
    string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    string internal constant _TABLE_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

    /**
     * @dev Converts a `bytes` to its Bytes64 `string` representation.
     */
    function encode(bytes memory data) internal pure returns (string memory) {
        return _encode(data, _TABLE, true);
    }

    /**
     * @dev Converts a `bytes` to its Bytes64Url `string` representation.
     * Output is not padded with `=` as specified in https://www.rfc-editor.org/rfc/rfc4648[rfc4648].
     */
    function encodeURL(bytes memory data) internal pure returns (string memory) {
        return _encode(data, _TABLE_URL, false);
    }

    /**
     * @dev Internal table-agnostic conversion
     */
    function _encode(bytes memory data, string memory table, bool withPadding) private pure returns (string memory) {
        /**
         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
         */
        if (data.length == 0) return "";

        // If padding is enabled, the final length should be `bytes` data length divided by 3 rounded up and then
        // multiplied by 4 so that it leaves room for padding the last chunk
        // - `data.length + 2`  -> Prepare for division rounding up
        // - `/ 3`              -> Number of 3-bytes chunks (rounded up)
        // - `4 *`              -> 4 characters for each chunk
        // This is equivalent to: 4 * Math.ceil(data.length / 3)
        //
        // If padding is disabled, the final length should be `bytes` data length multiplied by 4/3 rounded up as
        // opposed to when padding is required to fill the last chunk.
        // - `4 * data.length`  -> 4 characters for each chunk
        // - ` + 2`             -> Prepare for division rounding up
        // - `/ 3`              -> Number of 3-bytes chunks (rounded up)
        // This is equivalent to: Math.ceil((4 * data.length) / 3)
        uint256 resultLength = withPadding ? 4 * ((data.length + 2) / 3) : (4 * data.length + 2) / 3;

        string memory result = new string(resultLength);

        assembly ("memory-safe") {
            // Prepare the lookup table (skip the first "length" byte)
            let tablePtr := add(table, 1)

            // Prepare result pointer, jump over length
            let resultPtr := add(result, 0x20)
            let dataPtr := data
            let endPtr := add(data, mload(data))

            // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and
            // set it to zero to make sure no dirty bytes are read in that section.
            let afterPtr := add(endPtr, 0x20)
            let afterCache := mload(afterPtr)
            mstore(afterPtr, 0x00)

            // Run over the input, 3 bytes at a time
            for {} lt(dataPtr, endPtr) {} {
                // Advance 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // To write each character, shift the 3 byte (24 bits) chunk
                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
                // and apply logical AND with 0x3F to bitmask the least significant 6 bits.
                // Use this as an index into the lookup table, mload an entire word
                // so the desired character is in the least significant byte, and
                // mstore8 this least significant byte into the result and continue.

                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance
            }

            // Reset the value that was cached
            mstore(afterPtr, afterCache)

            if withPadding {
                // When data `bytes` is not exactly 3 bytes long
                // it is padded with `=` characters at the end
                switch mod(mload(data), 3)
                case 1 {
                    mstore8(sub(resultPtr, 1), 0x3d)
                    mstore8(sub(resultPtr, 2), 0x3d)
                }
                case 2 {
                    mstore8(sub(resultPtr, 1), 0x3d)
                }
            }
        }

        return result;
    }
}
"
    },
    "contracts/BugcatCodexRenderer.sol": {
      "content": "// SPDX-License-Identifier: WTFPL
pragma solidity ^0.8.30;

import "./utils/ENSResolver.sol";
import "solady/src/utils/LibString.sol";
import "@openzeppelin/contracts/utils/Base64.sol";

interface IBugcatsRegistry {
    function bugs(uint256) external view returns (address);
}

contract BugcatCodexRenderer {
    IBugcatsRegistry public immutable bugcatRegistry;
    string private specialCodeLight;
    string private specialCodeDark;

    constructor(address _bugcatRegistry, string memory _specialCodeLight, string memory _specialCodeDark) {
        bugcatRegistry = IBugcatsRegistry(_bugcatRegistry);
        specialCodeLight = _specialCodeLight;
        specialCodeDark = _specialCodeDark;
    }

    function renderImage(uint256 tokenId, address caretaker, uint8 bugcatIndex, string memory code, bool light, bool compiled) external view returns (string memory) {
        address bugcat = bugcatRegistry.bugs(bugcatIndex);
        string memory svg = _generateSvg(tokenId, caretaker, bugcat, code, light, compiled);
        return string.concat("data:image/svg+xml;base64,", Base64.encode(bytes(svg)));
    }

    function renderAnimationUrl(uint256 tokenId, address caretaker, uint8 bugcatIndex, string memory code, bool light, bool compiled, uint8[] memory preservedBugcatIndexes) external view returns (string memory) {
        address bugcat = bugcatRegistry.bugs(bugcatIndex);
        string memory svg = _generateSvg(tokenId, caretaker, bugcat, code, light, compiled);
        string memory backSvg = _generateBackSvg(tokenId, caretaker, preservedBugcatIndexes, light);
        return _wrapInInteractiveHtml(svg, backSvg, light);
    }

    function _generateSvg(uint256 tokenId, address caretaker, address bugcat, string memory code, bool light, bool compiled) internal view returns (string memory) {
        string memory bgColor = light ? "#f5f5f5" : "#0a0a0a";
        string memory boxBgColor = light ? "#ffffff" : "#1a1a1a";
        string memory textColor = light ? "#3a3a3a" : "#e0e0e0";
        string memory hlBg = light ? "#dddddd" : "#444444";

        string memory bytecode = LibString.toHexString(bugcat.code);
        string memory content = compiled ? _twoColsAutoHighlight(bytecode) : _escapeHtml(code);
        string memory comment = compiled ? "" : string.concat("<!-- ", bytecode, " -->");

        return string.concat(
            "<svg width=\"100%\" height=\"100%\" viewBox=\"0 0 1000 1000\" preserveAspectRatio=\"xMidYMid meet\" style=\"background-color: ", bgColor, "\" xmlns=\"http://www.w3.org/2000/svg\">",
            "<defs><style>\
",
            ".header { font-family: monospace; font-size: 14.5px; line-height: 1.0; letter-spacing: 0.005em; white-space: pre-wrap; word-break: break-all; overflow: hidden; height: 100%; color: ", textColor, "; }\
",
            ".code { font-family: monospace; font-size: 14.5px; line-height: 1.3; letter-spacing: 0.005em; white-space: pre-wrap; word-break: break-all; overflow: hidden; height: 100%; color: ", textColor, "; }\
",
            ".cols { display: flex; gap: 28px; }\
",
            ".col { flex: 1 1 0; }\
",
            ".hl { background:", hlBg, "; padding: 0 2px; border-radius: 2px; }\
",
            "</style></defs>",
            "<rect width=\"1000\" height=\"1000\" fill=\"", boxBgColor, "\"/>",
            _getHeader(tokenId, caretaker),
            "<foreignObject x=\"60\" y=\"220\" width=\"880\" height=\"790\">",
            "<div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"code\">",
            content,
            "</div></foreignObject>",
            comment,
            "</svg>"
        );
    }

    function _isComplete(uint8[] memory preservedBugcatIndexes) internal pure returns (bool) {
        if (preservedBugcatIndexes.length < 5) return false;
        bool[5] memory found;
        for (uint i = 0; i < preservedBugcatIndexes.length; i++) {
            uint8 index = preservedBugcatIndexes[i];
            if (index < 5) {
                found[index] = true;
            }
        }
        for (uint i = 0; i < 5; i++) {
            if (!found[i]) return false;
        }
        return true;
    }

    function _generateBackSvg(uint256 tokenId, address caretaker, uint8[] memory preservedBugcatIndexes, bool light) internal view returns (string memory) {
        string memory bgColor = light ? "#f5f5f5" : "#0a0a0a";
        string memory boxBgColor = light ? "#ffffff" : "#1a1a1a";
        string memory textColor = light ? "#3a3a3a" : "#e0e0e0";

        string memory content;
        if (_isComplete(preservedBugcatIndexes)) {
            content = light ? specialCodeLight : specialCodeDark;
        } else {
            content = _buildIncompleteMessage(preservedBugcatIndexes);
        }

        return string.concat(
            "<svg width=\"100%\" height=\"100%\" viewBox=\"0 0 1000 1000\" preserveAspectRatio=\"xMidYMid meet\" style=\"background-color: ", bgColor, "\" xmlns=\"http://www.w3.org/2000/svg\">",
            "<defs><style>\
",
            ".header { font-family: monospace; font-size: 14.5px; line-height: 1.0; letter-spacing: 0.005em; white-space: pre-wrap; word-break: break-all; overflow: hidden; height: 100%; color: ", textColor, "; }\
",
            ".code { font-family: monospace; font-size: 14.5px; line-height: 1.3; letter-spacing: 0.005em; white-space: pre-wrap; word-break: break-all; overflow: hidden; height: 100%; color: ", textColor, "; }\
",
            ".message { font-family: monospace; font-size: 14.5px; line-height: 1.1; letter-spacing: 0.005em; white-space: pre-wrap; word-break: break-all; overflow: hidden; height: 100%; color: ", textColor, "; }\
",
            "</style></defs>",
            "<rect width=\"1000\" height=\"1000\" fill=\"", boxBgColor, "\"/>",
            _getHeader(tokenId, caretaker),
            "<foreignObject x=\"60\" y=\"220\" width=\"880\" height=\"790\">",
            "<div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"message\">",
            content,
            "</div></foreignObject>",
            "</svg>"
        );
    }

    function _getHeader(uint256 tokenId, address caretaker) internal view returns (string memory) {
        string memory caretakerStr;
        try ENSResolver.resolveAddress(caretaker) returns (string memory nameOrAddr) {
            caretakerStr = nameOrAddr;
        } catch {
            caretakerStr = LibString.toHexStringChecksummed(caretaker);
        }
        return string.concat(
            "<foreignObject x=\"55\" y=\"30\" width=\"945\" height=\"30\">",
            "<div class=\"code\" xmlns=\"http://www.w3.org/1999/xhtml\">",
            "Codex #", _toString(tokenId), " preserved by ", caretakerStr, "\
",
            "</div></foreignObject>",

            "<foreignObject x=\"55\" y=\"70\" width=\"925\" height=\"120\">",
            "<div class=\"header\" xmlns=\"http://www.w3.org/1999/xhtml\">",
            "/////////////////////////////////////////////////////////////////////////////////////////////////////\
",
            "//          ____  __ __   ___    ___  ___  ______      ___   ___   ____    ____ _   _              //\
",
            "//          || )) || ||  // \\\\  //   // \\\\ | || |     //    // \\\\  || \\\\  ||    \\\\ //              //\
",
            "//          ||=)  || || (( ___ ((    ||=||   ||      ((    ((   )) ||  )) ||==   )X(               //\
",
            "//          ||_)) \\\\_//  \\\\_||  \\\\__ || ||   ||       \\\\__  \\\\_//  ||_//  ||___ // \\\\              //\
",
            "//                                                                                                 //\
",
            "/////////////////////////////////////////////////////////////////////////////////////////////////////\
",
            "</div></foreignObject>"
        );
    }

    function _buildIncompleteMessage(uint8[] memory preservedBugcatIndexes) internal view returns (string memory) {
        string memory statusLine = "";

        for (uint i = 0; i < 5; i++) {
            bool hasThisBugcat = false;
            string memory woundName = "";

            for (uint j = 0; j < preservedBugcatIndexes.length; j++) {
                if (preservedBugcatIndexes[j] == i) {
                    hasThisBugcat = true;
                    address bugcat = bugcatRegistry.bugs(i);
                    woundName = _extractWoundFromBytecode(bugcat);
                    break;
                }
            }

            woundName = hasThisBugcat ? woundName : "----------";
            statusLine = string.concat(statusLine, "[", woundName, "]");

            if (i < 4) {
                statusLine = string.concat(statusLine, " ");
            }
        }

        return string.concat(
            "BUGCAT CODEX: INCOMPLETE\
\
",
            statusLine,
            "\
\
Some wounds witnessed. The Codex remembers you."
        );
    }

    function _buildWoundsList(uint8[] memory preservedBugcatIndexes) internal view returns (string memory) {
        string memory result = "";
        for (uint i = 0; i < preservedBugcatIndexes.length; i++) {
            uint8 bugcatIndex = preservedBugcatIndexes[i];
            address bugcat = bugcatRegistry.bugs(bugcatIndex);
            string memory wound = _extractWoundFromBytecode(bugcat);
            result = string.concat(
                result,
                "<tspan x=\"100\" dy=\"25\">[x] I remember ", wound, " cat and its wound</tspan>"
            );
        }
        return result;
    }

    function _extractWoundFromBytecode(address bugcat) internal view returns (string memory) {
        bytes memory bytecode = bugcat.code;
        if (bytecode.length == 0) return "n/a";
        (bool found, string memory catName) = _extractFromPushInstructions(bytecode);
        if (found) {
            return catName;
        }
        catName = _findLongestValidString(bytecode);
        if (bytes(catName).length > 0) {
            return catName;
        }
        return "n/a";
    }

    function _extractFromPushInstructions(bytes memory bytecode) internal pure returns (bool found, string memory result) {
        uint256 bestScore = 0;
        bytes memory bestCandidate;

        uint256 pc = 0;
        while (pc < bytecode.length) {
            uint8 opcode = uint8(bytecode[pc]);
            if (opcode >= 0x60 && opcode <= 0x7f) {
                uint256 pushSize = opcode - 0x5f;
                if (pc + pushSize < bytecode.length) {
                    bytes memory data = new bytes(pushSize);
                    for (uint256 i = 0; i < pushSize; i++) {
                        data[i] = bytecode[pc + 1 + i];
                    }
                    if (_isValidWoundString(data)) {
                        uint256 score = pushSize * 10 + 100;
                        if (score > bestScore) {
                            bestScore = score;
                            bestCandidate = data;
                        }
                    }
                }
                pc += 1 + pushSize;
            } else {
                pc++;
            }
        }
        if (bestScore > 0) {
            return (true, string(bestCandidate));
        }

        return (false, "");
    }

    function _findLongestValidString(bytes memory bytecode) internal pure returns (string memory) {
        uint256 bestLength = 0;
        uint256 bestStart = 0;
        for (uint256 i = 0; i < bytecode.length; i++) {
            if (bytecode[i] >= 0x61 && bytecode[i] <= 0x7a) {
                uint256 start = i;
                uint256 end = i + 1;

                while (end < bytecode.length && bytecode[end] >= 0x61 && bytecode[end] <= 0x7a) {
                    end++;
                }

                uint256 length = end - start;

                if (length >= 6 && length <= 15 && length > bestLength) {
                    bytes memory candidate = new bytes(length);
                    for (uint256 j = 0; j < length; j++) {
                        candidate[j] = bytecode[start + j];
                    }

                    if (_isValidWord(candidate)) {
                        bestLength = length;
                        bestStart = start;
                    }
                }

                i = end - 1;
            }
        }

        if (bestLength > 0) {
            bytes memory result = new bytes(bestLength);
            for (uint256 i = 0; i < bestLength; i++) {
                result[i] = bytecode[bestStart + i];
            }
            return string(result);
        }

        return "";
    }

    function _isValidWoundString(bytes memory data) internal pure returns (bool) {
        if (data.length < 6 || data.length > 15) return false;
        
        for (uint256 i = 0; i < data.length; i++) {
            uint8 b = uint8(data[i]);

            if (b == 0x60) return false;

            if (b == 0x20) return false;

            if (b < 0x20 || b > 0x7e) return false;
        }

        bool allLowercase = true;
        for (uint256 i = 0; i < data.length; i++) {
            if (data[i] < 0x61 || data[i] > 0x7a) {
                allLowercase = false;
                break;
            }
        }

        if (allLowercase) {
            return _hasReasonableVowels(data);
        }

        return false;
    }

    function _isValidWord(bytes memory data) internal pure returns (bool) {
        bool hasVowel = false;
        uint256 consonantStreak = 0;
        uint256 maxConsonantStreak = 0;

        for (uint256 i = 0; i < data.length; i++) {
            uint8 b = uint8(data[i]);

            if (b == 0x61 || b == 0x65 || b == 0x69 || b == 0x6f || b == 0x75) {
                hasVowel = true;
                consonantStreak = 0;
            } else {
                consonantStreak++;
                if (consonantStreak > maxConsonantStreak) {
                    maxConsonantStreak = consonantStreak;
                }
            }
        }

        return hasVowel && maxConsonantStreak <= 4;
    }

    function _hasReasonableVowels(bytes memory data) internal pure returns (bool) {
        uint256 vowelCount = 0;

        for (uint256 i = 0; i < data.length; i++) {
            uint8 b = uint8(data[i]);
            if (b == 0x61 || b == 0x65 || b == 0x69 || b == 0x6f || b == 0x75) {
                vowelCount++;
            }
        }

        return vowelCount > 0 && vowelCount * 100 / data.length <= 60;
    }

    function _containsPattern(bytes memory haystack, bytes memory needle) internal pure returns (bool) {
        if (needle.length == 0 || needle.length > haystack.length) {
            return false;
        }

        for (uint256 i = 0; i <= haystack.length - needle.length; i++) {
            bool matched = true;
            for (uint256 j = 0; j < needle.length; j++) {
                if (haystack[i + j] != needle[j]) {
                    matched = false;
                    break;
                }
            }
            if (matched) {
                return true;
            }
        }
        
        return false;
    }

    function _wrapInInteractiveHtml(string memory svg, string memory backSvg, bool light) internal pure returns (string memory) {
        string memory bgColor = light ? "#f5f5f5" : "#0a0a0a";
        string memory html = string.concat(
            "data:text/html;charset=utf-8;base64,",
            Base64.encode(bytes(string.concat(
                "<!DOCTYPE html><html><head><style>",
                "html,body{margin:0;padding:0;width:100%;height:100%;background:", bgColor, ";overflow:hidden;perspective:1000px;}",
                ".card-container{position:absolute;top:0;left:0;width:100vw;height:100vh;display:flex;justify-content:center;align-items:center;}",
                ".card{position:relative;width:100vw;height:100vh;transform-style:preserve-3d;transition:transform 0.6s ease-in-out;}",
                ".card-face{position:absolute;top:0;left:0;width:100vw;height:100vh;backface-visibility:hidden;display:flex;justify-content:center;align-items:center;}",
                ".card-face svg{max-width:100%;max-height:100%;width:auto;height:auto;display:block;}",
                ".card-front{transform:rotateY(0deg);}",
                ".card-back{transform:rotateY(180deg);}",
                "body{cursor:pointer;}",
                "body.flipped .card{transform:rotateY(180deg);}",
                "</style></head><body onclick=\"handleClick(event)\">",
                "<script>",
                "let isSelecting=false;",
                "let mouseDownTime=0;",
                "document.addEventListener('mousedown',()=>mouseDownTime=Date.now());",
                "document.addEventListener('selectstart',()=>isSelecting=true);",
                "document.addEventListener('selectionchange',()=>{",
                "if(window.getSelection().toString()==='')isSelecting=false;",
                "});",
                "function handleClick(e){",
                "const clickDuration=Date.now()-mouseDownTime;",
                "if(isSelecting||clickDuration>200)return;",
                "document.body.classList.toggle('flipped');",
                "}",
                "</script>",
                "<div class=\"card-container\">",
                "<div class=\"card\">",
                "<div class=\"card-face card-front\">", svg, "</div>",
                "<div class=\"card-face card-back\">", backSvg, "</div>",
                "</div>",
                "</div>",
                "</body></html>"
            )))
        );
        return html;
    }

    function _twoColsAutoHighlight(string memory hex0x) internal pure returns (string memory) {
        string memory hexStr = _strip0x(hex0x);
        bytes memory hb = bytes(hexStr);
        bytes memory raw = _hexToBytes(hb);

        uint256 bestStart = type(uint256).max;
        uint256 bestLen = 0;

        (bool found, string memory pushResult) = _extractFromPushInstructions(raw);
        if (found) {
            bytes memory pushBytes = bytes(pushResult);
            bestLen = pushBytes.length;
            for (uint256 i = 0; i <= raw.length - bestLen; i++) {
                bool matched = true;
                for (uint256 j = 0; j < bestLen; j++) {
                    if (raw[i + j] != pushBytes[j]) {
                        matched = false;
                        break;
                    }
                }
                if (matched) {
                    bestStart = i;
                    break;
                }
            }
        }

        if (bestStart == type(uint256).max) {
            uint256 i = 0;
            while (i < raw.length) {
                if (raw[i] >= 0x61 && raw[i] <= 0x7a) {
                    uint256 j = i + 1;
                    while (j < raw.length && raw[j] >= 0x61 && raw[j] <= 0x7a) { unchecked { ++j; } }
                    uint256 len = j - i;

                    if (len >= 6 && len <= 15 && len > bestLen) {
                        bytes memory candidate = new bytes(len);
                        for (uint256 k = 0; k < len; k++) {
                            candidate[k] = raw[i + k];
                        }

                        if (_isValidWord(candidate)) {
                            bestLen = len;
                            bestStart = i;
                        }
                    }
                    i = j;
                } else { unchecked { ++i; } }
            }
        }

        uint256 pairs = hb.length / 2;
        uint256 leftPairs = pairs / 2;
        uint256 split = leftPairs * 2;

        string memory runHex = "";
        uint256 runPosHex = type(uint256).max;
        if (bestLen >= 6) {
            runHex = _bytesToHex(raw, bestStart, bestLen);
            runPosHex = LibString.indexOf(hexStr, runHex);
            if (runPosHex <= split && split < runPosHex + bytes(runHex).length) {
                split = runPosHex + bytes(runHex).length;
                if ((split & 1) == 1) split++;
                if (split > hb.length) split = hb.length;
            }
        }

        string memory left  = LibString.slice(hexStr, 0, split);
        string memory right = LibString.slice(hexStr, split);

        string memory leftG  = _groupPairsHex(left);
        string memory rightG = _groupPairsHex(right);

        if (runPosHex != type(uint256).max) {
            string memory runHexG = _groupPairsHex(runHex);
            string memory wrapped = string.concat("<span class=\"hl\">", runHexG, "</span>");
            if (runPosHex < split) {
                leftG  = _replaceOnce(leftG,  runHexG, wrapped);
            } else {
                rightG = _replaceOnce(rightG, runHexG, wrapped);
            }
        }

        return string.concat(
            "<div class=\"cols\"><div class=\"col\">", leftG, "</div><div class=\"col\">", rightG, "</div></div>"
        );
    }

    function _groupPairsHex(string memory hexWithOpt0x) internal pure returns (string memory) {
        bytes memory s = bytes(hexWithOpt0x);
        uint256 start = 0;
        bool has0x = false;
        if (s.length >= 2 && s[0] == "0" && (s[1] == "x" || s[1] == "X")) { has0x = true; start = 2; }
        uint256 hexLen = s.length - start;
        if (hexLen == 0) return hexWithOpt0x;

        uint256 pairs = hexLen / 2;
        uint256 spaces = pairs > 0 ? pairs - 1 : 0;
        uint256 outLen = (has0x ? 3 : 0) + hexLen + spaces;
        bytes memory out = new bytes(outLen);
        uint256 idx = 0;

        if (has0x) { out[idx++] = "0"; out[idx++] = "x"; out[idx++] = 0x20; }

        for (uint256 i = 0; i < hexLen; i += 2) {
            out[idx++] = s[start + i];
            if (i + 1 < hexLen) out[idx++] = s[start + i + 1];
            if (i + 2 < hexLen) out[idx++] = 0x20;
        }
        return string(out);
    }

    function _replaceOnce(string memory s, string memory needle, string memory replacement) internal pure returns (string memory) {
        uint256 p = LibString.indexOf(s, needle);
        if (p == type(uint256).max) return s;
        string memory head = LibString.slice(s, 0, p);
        string memory tail = LibString.slice(s, p + bytes(needle).length);
        return string.concat(head, replacement, tail);
    }

    function _strip0x(string memory s) internal pure returns (string memory) {
        bytes memory bs = bytes(s);
        if (bs.length >= 2 && bs[0] == "0" && (bs[1] == "x" || bs[1] == "X")) {
            bytes memory out = new bytes(bs.length - 2);
            for (uint256 k = 2; k < bs.length; ++k) out[k-2] = bs[k];
            return string(out);
        }
        return s;
    }

    function _hexToBytes(bytes memory hexChars) internal pure returns (bytes memory) {
        require(hexChars.length % 2 == 0, "hex length");
        bytes memory out = new bytes(hexChars.length / 2);
        for (uint256 k = 0; k < out.length; ++k) {
            out[k] = bytes1(( _nibble(hexChars[2*k]) << 4 ) | _nibble(hexChars[2*k+1]));
        }
        return out;
    }

    function _bytesToHex(bytes memory data, uint256 start, uint256 len) internal pure returns (string memory) {
        bytes memory out = new bytes(len * 2);
        for (uint256 k = 0; k < len; ++k) {
            uint8 b = uint8(data[start + k]);
            out[2*k] = _hexChar(b >> 4);
            out[2*k + 1] = _hexChar(b & 0x0f);
        }
        return string(out);
    }

    function _nibble(bytes1 c) private pure returns (uint8) {
        uint8 u = uint8(c);
        if (u >= 48 && u <= 57) return u - 48;
        if (u >= 65 && u <= 70) return u - 55;
        if (u >= 97 && u <= 102) return u - 87;
        revert("bad hex");
    }

    function _hexChar(uint8 nib) private pure returns (bytes1) {
        return bytes1(nib + (nib < 10 ? 48 : 87));
    }

    function _toString(uint256 value) internal pure returns (string memory str) {
        if (value == 0) return "0";
        uint256 temp = value; uint256 digits;
        while (temp != 0) { digits++; temp /= 10; }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        str = string(buffer);
    }

    function _escapeHtml(string memory input) internal pure returns (string memory) {
        string memory result = LibString.replace(input, "&", "&amp;");
        result = LibString.replace(result, "<", "&lt;");
        result = LibString.replace(result, ">", "&gt;");
        result = LibString.replace(result, "\"", "&quot;");
        result = LibString.replace(result, "'", "&apos;");
        return result;
    }
}
"
    },
    "contracts/utils/ENSResolver.sol": {
      "content": "// SPDX-License-Identifier: MIT
// Author: @yigitduman
// Source: https://github.com/ygtdmn/drakeflipping/blob/main/src/DrakeflippingRenderer.sol
pragma solidity >=0.8.0;

import "solady/src/utils/LibString.sol";
import { ENS } from "@ensdomains/ens-contracts/contracts/registry/ENS.sol";
import { IReverseRegistrar } from "@ensdomains/ens-contracts/contracts/reverseRegistrar/IReverseRegistrar.sol";
import { INameResolver } from "@ensdomains/ens-contracts/contracts/resolvers/profiles/INameResolver.sol";

library ENSResolver {
    /**
     * @notice Retrieves the ENS name or checksummed address for a given address.
     * @param addr The address to retrieve the ENS name or checksummed address for.
     * @return The ENS name if available, otherwise the checksummed address.
     */
    function resolveAddress(address addr) external view returns (string memory) {
        ENS ens = ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e);
        IReverseRegistrar reverseRegistrar = IReverseRegistrar(0xa58E81fe9b61B5c3fE2AFD33CF304c454AbFc7Cb);
        bytes32 node = reverseRegistrar.node(addr);
        address resolverAddress = ens.resolver(node);

        if (resolverAddress != address(0)) {
            // If the resolver is not the zero address, try to get the name from the resolver
            try INameResolver(resolverAddress).name(node) returns (string memory name) {
                // If a name is found and it's not empty, return it
                if (bytes(name).length > 0) {
                    return name;
                }
            } catch {}
        }

        // If no valid name is found, return the address as a string
        return LibString.toHexStringChecksummed(addr);
    }
}
"
    },
    "solady/src/utils/LibBytes.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for byte related operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBytes.sol)
library LibBytes {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Goated bytes storage struct that totally MOGs, no cap, fr.
    /// Uses less gas and bytecode than Solidity's native bytes storage. It's meta af.
    /// Packs length with the first 31 bytes if <255 bytes, so it’s mad tight.
    struct BytesStorage {
        bytes32 _spacer;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The constant returned when the `search` is not found in the bytes.
    uint256 internal constant NOT_FOUND = type(uint256).max;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  BYTE STORAGE OPERATIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sets the value of the bytes storage `$` to `s`.
    function set(BytesStorage storage $, bytes memory s) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(s)
            let packed := or(0xff, shl(8, n))
            for { let i := 0 } 1 {} {
                if iszero(gt(n, 0xfe)) {
                    i := 0x1f
                    packed := or(n, shl(8, mload(add(s, i))))
                    if iszero(gt(n, i)) { break }
                }
                let o := add(s, 0x20)
                mstore(0x00, $.slot)
                for { let p := keccak256(0x00, 0x20) } 1 {} {
                    sstore(add(p, shr(5, i)), mload(add(o, i)))
                    i := add(i, 0x20)
                    if iszero(lt(i, n)) { break }
                }
                break
            }
            sstore($.slot, packed)
        }
    }

    /// @dev Sets the value of the bytes storage `$` to `s`.
    function setCalldata(BytesStorage storage $, bytes calldata s) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let packed := or(0xff, shl(8, s.length))
            for { let i := 0 } 1 {} {
                if iszero(gt(s.length, 0xfe)) {
                    i := 0x1f
                    packed := or(s.length, shl(8, shr(8, calldataload(s.offset))))
                    if iszero(gt(s.length, i)) { break }
                }
                mstore(0x00, $.slot)
                for { let p := keccak256(0x00, 0x20) } 1 {} {
                    sstore(add(p, shr(5, i)), calldataload(add(s.offset, i)))
                    i := add(i, 0x20)
                    if iszero(lt(i, s.length)) { break }
                }
                break
            }
            sstore($.slot, packed)
        }
    }

    /// @dev Sets the value of the bytes storage `$` to the empty bytes.
    function clear(BytesStorage storage $) internal {
        delete $._spacer;
    }

    /// @dev Returns whether the value stored is `$` is the empty bytes "".
    function isEmpty(BytesStorage storage $) internal view returns (bool) {
        return uint256($._spacer) & 0xff == uint256(0);
    }

    /// @dev Returns the length of the value stored in `$`.
    function length(BytesStorage storage $) internal view returns (uint256 result) {
        result = uint256($._spacer);
        /// @solidity memory-safe-assembly
        assembly {
            let n := and(0xff, result)
            result := or(mul(shr(8, result), eq(0xff, n)), mul(n, iszero(eq(0xff, n))))
        }
    }

    /// @dev Returns the value stored in `$`.
    function get(BytesStorage storage $) internal view returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let o := add(result, 0x20)
            let packed := sload($.slot)
            let n := shr(8, packed)
            for { let i := 0 } 1 {} {
                if iszero(eq(or(packed, 0xff), packed)) {
                    mstore(o, packed)
                    n := and(0xff, packed)
                    i := 0x1f
                    if iszero(gt(n, i)) { break }
                }
                mstore(0x00, $.slot)
                for { let p := keccak256(0x00, 0x20) } 1 {} {
                    mstore(add(o, i), sload(add(p, shr(5, i))))
                    i := add(i, 0x20)
                    if iszero(lt(i, n)) { break }
                }
                break
            }
            mstore(result, n) // Store the length of the memory.
            mstore(add(o, n), 0) // Zeroize the slot after the bytes.
            mstore(0x40, add(add(o, n), 0x20)) // Allocate memory.
        }
    }

    /// @dev Returns the uint8 at index `i`. If out-of-bounds, returns 0.
    function uint8At(BytesStorage storage $, uint256 i) internal view returns (uint8 result) {
        /// @solidity memory-safe-assembly
        assembly {
            for { let packed := sload($.slot) } 1 {} {
                if iszero(eq(or(packed, 0xff), packed)) {
                    if iszero(gt(i, 0x1e)) {
                        result := byte(i, packed)
                        break
                    }
                    if iszero(gt(i, and(0xff, packed))) {
                        mstore(0x00, $.slot)
                        let j := sub(i, 0x1f)
                        result := byte(and(j, 0x1f), sload(add(keccak256(0x00, 0x20), shr(5, j))))
                    }
                    break
                }
                if iszero(gt(i, shr(8, packed))) {
                    mstore(0x00, $.slot)
                    result := byte(and(i, 0x1f), sload(add(keccak256(0x00, 0x20), shr(5, i))))
                }
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      BYTES OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `subject` all occurrences of `needle` replaced with `replacement`.
    function replace(bytes memory subject, bytes memory needle, bytes memory replacement)
        internal
        pure
        returns (bytes memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let needleLen := mload(needle)
            let replacementLen := mload(replacement)
            let d := sub(result, subject) // Memory difference.
            let i := add(subject, 0x20) // Subject bytes pointer.
            mstore(0x00, add(i, mload(subject))) // End of subject.
            if iszero(gt(needleLen, mload(subject))) {
                let subjectSearchEnd := add(sub(mload(0x00), needleLen), 1)
                let h := 0 // The hash of `needle`.
                if iszero(lt(needleLen, 0x20)) { h := keccak256(add(needle, 0x20), needleLen) }
                let s := mload(add(needle, 0x20))
                for { let m := shl(3, sub(0x20, and(needleLen, 0x1f))) } 1 {} {
                    let t := mload(i)
                    // Whether the first `needleLen % 32` bytes of `subject` and `needle` matches.
                    if iszero(shr(m, xor(t, s))) {
                        if h {
                            if iszero(eq(keccak256(i, needleLen), h)) {
                                mstore(add(i, d), t)
                                i := add(i, 1)
                                if iszero(lt(i, subjectSearchEnd)) { break }
                                continue
                            }
                        }
                        // Copy the `replacement` one word at a time.
                        for { let j := 0 } 1 {} {
                            mstore(add(add(i, d), j), mload(add(add(replacement, 0x20), j)))
                            j := add(j, 0x20)
                            if iszero(lt(j, replacementLen)) { break }
                        }
                        d := sub(add(d, replacementLen), needleLen)
                        if needleLen {
                            i := add(i, needleLen)
                            if iszero(lt(i, subjectSearchEnd)) { break }
                            continue
                        }
                    }
                    mstore(add(i, d), t)
                    i := add(i, 1)
                    if iszero(lt(i, subjectSearchEnd)) { break }
                }
            }
            let end := mload(0x00)
            let n := add(sub(d, add(result, 0x20)), end)
            // Copy the rest of the bytes one word at a time.
            for {} lt(i, end) { i := add(i, 0x20) } { mstore(add(i, d), mload(i)) }
            let o := add(i, d)
            mstore(o, 0) // Zeroize the slot after the bytes.
            mstore(0x40, add(o, 0x20)) // Allocate memory.
            mstore(result, n) // Store the length.
        }
    }

    /// @dev Returns the byte index of the first location of `needle` in `subject`,
    /// needleing from left to right, starting from `from`.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found.
    function indexOf(bytes memory subject, bytes memory needle, uint256 from)
        internal
        pure
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := not(0) // Initialize to `NOT_FOUND`.
            for { let subjectLen := mload(subject) } 1 {} {
                if iszero(mload(needle)) {
                    result := from
                    if iszero(gt(from, subjectLen)) { break }
                    result := subjectLen
                    break
                }
                let needleLen := mload(needle)
                let subjectStart := add(subject, 0x20)

                subject := add(subjectStart, from)
                let end := add(sub(add(subjectStart, subjectLen), needleLen), 1)
                let m := shl(3, sub(0x20, and(needleLen, 0x1f)))
                let s := mload(add(needle, 0x20))

                if iszero(and(lt(subject, end), lt(from, subjectLen))) { break }

                if iszero(lt(needleLen, 0x20)) {
                    for { let h := keccak256(add(needle, 0x20), needleLen) } 1 {} {
                        if iszero(shr(m, xor(mload(subject), s))) {
                            if eq(keccak256(subject, needleLen), h) {
                                result := sub(subject, subjectStart)
                                break
                            }
                        }
                        subject := add(subject, 1)
                        if iszero(lt(subject, end)) { break }
                    }
                    break
                }
                for {} 1 {} {
                    if iszero(shr(m, xor(mload(subject), s))) {
                        result := sub(subject, subjectStart)
                        break
                    }
                    subject := add(subject, 1)
                    if iszero(lt(subject, end)) { break }
                }
                break
            }
        }
    }

    /// @dev Returns the byte index of the first location of `needle` in `subject`,
    /// needleing from left to right, starting from `from`. Optimized for byte needles.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found.
    function indexOfByte(bytes memory subject, bytes1 needle, uint256 from)
        internal
        pure
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := not(0) // Initialize to `NOT_FOUND`.
            if gt(mload(subject), from) {
                let start := add(subject, 0x20)
                let end := add(start, mload(subject))
                let m := div(not(0), 255) // `0x0101 ... `.
                let h := mul(byte(0, needle), m) // Replicating needle mask.
                m := not(shl(7, m)) // `0x7f7f ... `.
                for { let i := add(start, from) } 1 {} {
                    let c := xor(mload(i), h) // Load 32-byte chunk and xor with mask.
                    c := not(or(or(add(and(c, m), m), c), m)) // Each needle byte will be `0x80`.
                    if c {
                        c := and(not(shr(shl(3, sub(end, i)), not(0))), c) // Truncate bytes past the end.
                        if c {
                            let r := shl(7, lt(0x8421084210842108cc6318c6db6d54be, c)) // Save bytecode.
                            r := or(shl(6, lt(0xffffffffffffffff, shr(r, c))), r)
                            // forgefmt: disable-next-item
                            result := add(sub(i, start), shr(3, xor(byte(and(0x1f, shr(byte(24,
                                mul(0x02040810204081, shr(r, c))), 0x8421084210842108cc6318c6db6d54be)),
                                0xc0c8c8d0c8e8d0d8c8e8e0e8d0d8e0f0c8d0e8d0e0e0d8f0d0d0e0d8f8f8f8f8), r)))
                            break
                        }
                    }
                    i := add(i, 0x20)
                    if iszero(lt(i, end)) { break }
                }
            }
        }
    }

    /// @dev Returns the byte index of the first location of `needle` in `subject`,
    /// needleing from left to right. Optimized for byte needles.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found.
    function indexOfByte(bytes memory subject, bytes1 needle)
        internal
        pure
        returns (uint256 result)
    {
        return indexOfByte(subject, needle, 0);
    }

    /// @dev Returns the byte index of the first location of `needle` in `subject`,
    /// needleing from left to right.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found.
    function indexOf(bytes memory subject, bytes memory needle) internal pure returns (uint256) {
        return indexOf(subject, needle, 0);
    }

    /// @dev Returns the byte index of the first location of `needle` in `subject`,
    /// needleing from right to left, starting from `from`.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found.
    function lastIndexOf(bytes memory subject, bytes memory needle, uint256 from)
        internal
        pure
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            for {} 1 {} {
                result := not(0) // Initialize to `NOT_FOUND`.
                let needleLen := mload(needle)
                if gt(needleLen, mload(subject)) { break }
                let w := result

                let fromMax := sub(mload(subject), needleLen)
                if iszero(gt(fromMax, from)) { from := fromMax }

                let end := add(add(subject, 0x20), w)
                subject := add(add(subject, 0x20), from)
                if iszero(gt(subject, end)) { break }
                // As this function is not too often used,
                // we shall simply use keccak256 for smaller bytecode size.
                for { let h := keccak256(add(needle, 0x20), needleLen) } 1 {} {
                    if eq(keccak256(subject, needleLen), h) {
                        result := sub(subject, add(end, 1))
                        break
                    }
                    subject := add(subject, w) // `sub(subject, 1)`.
                    if iszero(gt(subject, end)) { break }
                }
                break
            }
        }
    }

    /// @dev Returns the byte index of the first location of `needle` in `subject`,
    /// needleing from right to left.
    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found.
    function lastIndexOf(bytes memory subject, bytes memory needle)
        internal
        pure
        returns (uint256)
    {
        return lastIndexOf(subject, needle, type(uint256).max);
    }

    /// @dev Returns true if `needle` is found in `subject`, false otherwise.
    function contains(bytes memory subject, bytes memory needle) internal pure returns (bool) {
        return indexOf(subject, needle) != NOT_FOUND;
    }

    /// @dev Returns whether `subject` starts with `needle`.
    function startsWith(bytes memory subject, bytes memory needle)
        internal
        pure
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(needle)
            // Just using keccak256 directly is actually cheaper.
            let t := eq(keccak256(add(subject, 0x20), n), keccak256(add(needle, 0x20), n))
            result := lt(gt(n, mload(subject)), t)
        }
    }

    /// @dev Returns whether `subject` ends with `needle`.
    function endsWith(bytes memory subject, bytes memory needle)
        internal
        pure
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(needle)
            let notInRange := gt(n, mload(subject))
            // `subject + 0x20 + max(subject.length - needle.length, 0)`.
            let t := add(add(subject, 0x20), mul(iszero(notInRange), sub(mload(subject), n)))
            // Just using keccak256 directly is actually cheaper.
            result := gt(eq(keccak256(t, n), keccak256(add(needle, 0x20), n)), notInRange)
        }
    }

    /// @dev Returns `subject` repeated `times`.
    function repeat(bytes memory subject, uint256 times)
        internal
        pure
        returns (bytes memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let l := mload(subject) // Subject length.
            if iszero(or(iszero(times), iszero(l))) {
                result := mload(0x40)
                subject := add(subject, 0x20)
                let o := add(result, 0x20)
                for {} 1 {} {
                    // Copy the `subject` one word at a time.
                    for { let j := 0 } 1 {} {
                        mstore(add(o, j), mload(add(subject, j)))
                        j := add(j, 0x20)
                        if iszero(lt(j, l)) { break }
                    }
                    o := add(o, l)
                    times := sub(times, 1)
                    if iszero(times) { break }
                }
                mstore(o, 0) // Zeroize the slot after the bytes.
                mstore(0x40, add(o, 0x20)) // Allocate memory.
                mstore(result, sub(o, add(result, 0x20))) // Store the length.
            }
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function slice(bytes memory subject, uint256 start, uint256 end)
        internal
        pure
        returns (bytes memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let l := mload(subject) // Subject length.
            if iszero(gt(l, end)) { end := l }
            if iszero(gt(l, start)) { start := l }
            if lt(start, end) {
                result := mload(0x40)
                let n := sub(end, start)
                let i := add(subject, start)
                let w := not(0x1f)
                // Copy the `subject` one word at a time, backwards.
                for { let j := and(add(n, 0x1f), w) } 1 {} {
                    mstore(add(result, j), mload(add(i, j)))
                    j := add(j, w) // `sub(j, 0x20)`.
                    if iszero(j) { break }
                }
                let o := add(add(result, 0x20), n)
                mstore(o, 0) // Zeroize the slot after the bytes.
                mstore(0x40, add(o, 0x20)) // Allocate memory.
                mstore(result, n) // Store the length.
            }
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to the end of the bytes.
    /// `start` is a byte offset.
    function slice(bytes memory subject, uint256 start)
        internal
        pure
        returns (bytes memory result)
    {
        result = slice(subject, start, type(uint256).max);
    }

    /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets. Faster than Solidity's native slicing.
    function sliceCalldata(bytes calldata subject, uint256 start, uint256 end)
        internal
        pure
        returns (bytes calldata result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            end := xor(end, mul(xor(end, subject.length), lt(subject.length, end)))
            start := xor(start, mul(xor(start, subject.length), lt(subject.length, start)))
            result.offset := add(subject.offset, start)
            result.length := mul(lt(start, end), sub(end, start))
        }
    }

    /// @dev Returns a copy of `subject` sliced from `start` to the end of the bytes.
    /// `start` is a byte offset. Faster than Solidity's native slicing.
    function sliceCalldata(bytes calldata subject, uint256 start)
        internal
        pure
        returns (bytes calldata result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            start := xor(start, mul(xor(start, subject.length), lt(subject.length, start)))
            result.offset := add(subject.offset, start)
            result.length := mul(lt(start, subject.length), sub(subject.length, start))
        }
    }

    /// @dev Reduces the size of `subject` to `n`.
    /// If `n` is greater than the size of `subject`, this will be a no-op.
    function truncate(bytes memory subject, uint256 n)
        internal
        pure
        returns (bytes memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := subject
            mstore(mul(lt(n, mload(result)), result), n)
        }
    }

    /// @dev Returns a copy of `subject`, with the length reduced to `n`.
    /// If `n` is greater than the size of `subject`, this will be a no-op.
    function truncatedCalldata(bytes calldata subject, uint256 n)
        internal
        pure
        returns (bytes calldata result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result.offset := subject.offset
            result.length := xor(n, mul(xor(n, subject.length), lt(subject.length, n)))
        }
    }

    /// @dev Returns all the indices of `needle` in `subject`.
    /// The indices are byte offsets.
    function indicesOf(bytes memory subject, bytes memory needle)
        internal
        pure
        returns (uint256[] memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let searchLen := mload(needle)
            if iszero(gt(searchLen, mload(subject))) {
                result := mload(0x40)
                let i := add(subject, 0x20)
                let o := add(result, 0x20)
                let subjectSearchEnd := add(sub(add(i, mload(subject)), searchLen), 1)
                let h := 0 // The hash of `needle`.
                if iszero(lt(searchLen, 0x20)) { h := keccak256(add(needle, 0x20), searchLen) }
                let s := mload(add(needle, 0x20))
                for { let m := shl(3, sub(0x20, and(searchLen, 0x1f))) } 1 {} {
                    let t := mload(i)
                    // Whether the first `searchLen % 32` bytes of `subject` and `needle` matches.
                    if iszero(shr(m, xor(t, s))) {
                        if h {
                            if iszero(eq(keccak256(i, searchLen), h)) {
                                i := add(i, 1)
                                if iszero(lt(i, subjectSearchEnd)) { break }
                                continue
                            }
                        }
                        mstore(o, sub(i, add(subject, 0x20))) // Append to `result`.
                        o := add(o, 0x20)
                        i := add(i, searchLen) // Advance `i` by `searchLen`.
                        if searchLen {
                            if iszero(lt(i, subjectSearchEnd)) { break }
                            continue
                        }
                    }
                    i := add(i, 1)
                    if iszero(lt(i, subjectSearchEnd)) { break }
                }
                mstore(result, shr(5, sub(o, add(result, 0x20)))) // Store the length of `result`.
                // Allocate memory for result.
                // We allocate one more word, so this array can be recycled for {split}.
                mstore(0x40, add(o, 0x20))
            }
        }
    }

    /// @dev Returns an arrays of bytess based on the `delimiter` inside of the `subject` bytes.
    function split(bytes memory subject, bytes memory delimiter)
        internal
        pure
        returns (bytes[] memory result)
    {
        uint256[] memory indices = indicesOf(subject, delimiter);
        /// @solidity memory-safe-assembly
        assembly {
            let w := not(0x1f)
            let indexPtr := add(indices, 0x20)
            let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1)))
            mstore(add(indicesEnd, w), mload(subject))
            mstore(indices, add(mload(indices), 1))
            for { let prevIndex := 0 } 1 {} {
                let index := mload(indexPtr)
                mstore(indexPtr, 0x60)
                if iszero(eq(index, prevIndex)) {
                    let element := mload(0x40)
                    let l := sub(index, prevIndex)
                    mstore(element, l) // Store the length of the element.
                    // Copy the `subject` one word at a time, backwards.
                    for { let o := and(add(l, 0x1f), w) } 1 {} {
                        mstore(add(element, o), mload(add(add(subject, prevIndex), o)))
                        o := add(o, w) // `sub(o, 0x20)`.
                        if iszero(o) { break }
                    }
                    mstore(add(add(element, 0x20), l), 0) // Zeroize the slot after the bytes.
                    // Allocate memory for the length and the bytes, rounded up to a multiple of 32.
                    mstore(0x40, add(element, and(add(l, 0x3f), w)))
                    mstore(indexPtr, element) // Store the `element` into the array.
                }
                prevIndex := add(index, mload(delimiter))
                indexPtr := add(indexPtr, 0x20)
                if iszero(lt(indexPtr, indicesEnd)) { break }
            }
            result := indices
            if iszero(mload(delimiter)) {
                result := add(indices, 0x20)
                mstore(result, sub(mload(indices), 2))
            }
        }
    }

    /// @dev Returns a concatenated bytes of `a` and `b`.
    /// Cheaper than `bytes.concat()` and does not de-align the free memory pointer.
    function concat(bytes memory a, bytes memory b) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let w := not(0x1f)
            let aLen := mload(a)
            // Copy `a` one word at a time, backwards.
            for { let o := and(add(aLen, 0x20), w) } 1 {} {
                mstore(add(result, o), mload(add(a, o)))
                o := add(o, w) // `sub(o, 0x20)`.
                if iszero(o) { break }
            }
            let bLen := mload(b)
            let output := add(result, aLen)
            // Copy `b` one word at a time, backwards.
            for { let o := and(add(bLen, 0x20), w) } 1 {} {
                mstore(add(output, o), mload(add(b, o)))
                o := add(o, w) // `sub(o, 0x20)`.
                if iszero(o) { break }
            }
            let totalLen := add(aLen, bLen)
            let last := add(add(result, 0x20), totalLen)
            mstore(last, 0) // Zeroize the

Tags:
Multisig, Multi-Signature, Factory|addr:0xe4bb28232847f0548d15a3c9544ad1ac82e255d5|verified:true|block:23444194|tx:0x62dd78464f3c71e0acfb4717a1f1f63bd5b53c156fd61ae386a07c9c338fe276|first_check:1758876412

Submitted on: 2025-09-26 10:46:55

Comments

Log in to comment.

No comments yet.