{"sources":{"contracts/lib/render/Render.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\ninterface IRender {\n    function tokenURI(uint256 id) external view returns (string memory);\n}\n"},"contracts/lib/report/IReportRoot.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\ninterface IReportRoot {\n    function report(address from) external payable;\n    function split() external payable;\n    function splitEnd() external payable;\n    function receiver() external view returns (address);\n}\n"},"contracts/lib/report/ReportRoot.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\nimport \"solady/src/utils/SSTORE2.sol\";\nimport \"./IReportRoot.sol\";\n\ncontract ReportRoot is IReportRoot {\n    struct Metadata {\n        address sender;\n        uint96 amount;\n        address receiver;\n        uint48 timestamp;\n    }\n\n    event Activation(address indexed sender, address indexed receiver, uint256 amount);\n\n    error NotANode();\n    error ActivationRunning();\n\n    uint8 public constant INDEX_BYTES = 2;\n    uint256 constant RESERVED_BYTES = 12;\n    uint256 constant PAIR_BYTES = uint256(INDEX_BYTES) * 2;\n    uint256 constant REPORTS_PER_BUFFER = 32 / PAIR_BYTES;\n    uint256 constant RESERVED_PAIRS = RESERVED_BYTES / PAIR_BYTES;\n    uint256 constant SPLIT_START = type(uint16).max;\n    uint256 constant SPLIT_END = type(uint16).max - 1;\n\n    uint256 constant RUNNING = 1;\n    uint256 constant RUN_COUNTER = 2;\n    uint256 constant NEXT_INDEX = 3;\n    uint256 constant REPORT_INDEX = 4;\n    uint256 constant SPLIT_COUNT = 5;\n    uint256 constant SENDER = 6;\n    uint256 constant RECEIVER = 7;\n    uint256 constant AMOUNT = 8;\n    uint256 constant BUFFER_OFFSET = 100;\n    uint256 constant RUN_STRIDE_BITS = 32;\n\n    uint256 public totalReports;\n    mapping(uint256 => address) public reportPointer;\n    mapping(uint256 => Metadata) public metadata;\n    mapping(address => bool) private _registered;\n\n    /*//////////////////////////////////////////////////////////////\n                                REPORTS\n    //////////////////////////////////////////////////////////////*/\n\n    function getReport(uint256 index) public view returns (bytes32[] memory, Metadata memory) {\n        return (_report(index), metadata[index]);\n    }\n\n    function getMostRecentReport() public view returns (bytes32[] memory, Metadata memory) {\n        Metadata memory none;\n        if (totalReports == 0) return (new bytes32[](0), none);\n        return (_report(totalReports - 1), metadata[totalReports - 1]);\n    }\n\n    function getReports(uint256 count, uint256 offset) public view returns (bytes32[][] memory, Metadata[] memory) {\n        uint256 n;\n        if (offset < totalReports) {\n            n = totalReports - offset;\n            if (n > count) n = count;\n        }\n        bytes32[][] memory reports = new bytes32[][](n);\n        Metadata[] memory metadatas = new Metadata[](n);\n        for (uint256 i = 0; i < n; i++) {\n            reports[i] = _report(offset + i);\n            metadatas[i] = metadata[offset + i];\n        }\n        return (reports, metadatas);\n    }\n\n    function getRecentReports(uint256 n) public view returns (bytes32[][] memory, Metadata[] memory) {\n        if (n > totalReports) n = totalReports;\n        return getReports(n, totalReports - n);\n    }\n\n    function _report(uint256 index) internal view returns (bytes32[] memory out) {\n        address pointer = reportPointer[index];\n        if (pointer == address(0)) return out;\n        bytes memory blob = SSTORE2.read(pointer);\n        uint256 n = blob.length / 32;\n        out = new bytes32[](n);\n        for (uint256 i = 0; i < n; i++) {\n            assembly (\"memory-safe\") {\n                let offset := mul(i, 0x20)\n                mstore(add(add(out, 0x20), offset), mload(add(add(blob, 0x20), offset)))\n            }\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                 NODES\n    //////////////////////////////////////////////////////////////*/\n\n    function _node(address node) internal returns (address) {\n        _registered[node] = true;\n        return node;\n    }\n\n    function _isNode(address a) internal view virtual returns (bool) {\n        return _registered[a];\n    }\n\n    function isNode(address a) external view returns (bool) {\n        return _isNode(a);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                               RECORDING\n    //////////////////////////////////////////////////////////////*/\n\n    function begin(address sender_, address receiver_, uint256 amount) internal {\n        if (_running()) revert ActivationRunning();\n        assembly {\n            tstore(RUNNING, 1)\n            tstore(RUN_COUNTER, add(tload(RUN_COUNTER), 1))\n            tstore(SENDER, sender_)\n            tstore(RECEIVER, receiver_)\n            tstore(AMOUNT, amount)\n        }\n    }\n\n    function report(address from) public payable {\n        if (!_isNode(msg.sender) || !_isNode(from)) revert NotANode();\n        if (!_running()) return;\n        uint256 run;\n        assembly {\n            run := tload(RUN_COUNTER)\n        }\n        uint32 fromIndex = _transientIndex(from, run);\n        uint32 toIndex = _transientIndex(msg.sender, run);\n        _write(run, fromIndex, toIndex);\n    }\n\n    function split() external payable {\n        if (!_isNode(msg.sender)) revert NotANode();\n        _split();\n    }\n\n    function splitEnd() external payable {\n        if (!_isNode(msg.sender)) revert NotANode();\n        _splitEnd();\n    }\n\n    function _split() internal {\n        if (!_running()) return;\n        uint256 run;\n        assembly {\n            run := tload(RUN_COUNTER)\n            tstore(SPLIT_COUNT, add(1, tload(SPLIT_COUNT)))\n        }\n        _write(run, SPLIT_START, SPLIT_START);\n    }\n\n    function _splitEnd() internal {\n        if (!_running()) return;\n        uint256 run;\n        assembly {\n            run := tload(RUN_COUNTER)\n        }\n        _write(run, SPLIT_END, SPLIT_END);\n    }\n\n    function _write(uint256 run, uint256 from, uint256 to) private {\n        uint256 reportIndex;\n        assembly {\n            reportIndex := tload(REPORT_INDEX)\n        }\n        unchecked {\n            uint256 slotIndex = reportIndex + RESERVED_PAIRS;\n            uint256 bufferIndex = slotIndex / REPORTS_PER_BUFFER;\n            uint256 shift = (slotIndex % REPORTS_PER_BUFFER) * PAIR_BYTES * 8;\n            uint256 pair = (from | (to << (INDEX_BYTES * 8))) << shift;\n            assembly {\n                let slot := add(add(BUFFER_OFFSET, shl(RUN_STRIDE_BITS, run)), bufferIndex)\n                tstore(slot, or(tload(slot), pair))\n                tstore(REPORT_INDEX, add(1, reportIndex))\n            }\n        }\n    }\n\n    function _transientIndex(address a, uint256 run) private returns (uint32 index) {\n        bytes32 slot = keccak256(abi.encodePacked(a, run));\n        assembly {\n            index := tload(slot)\n            if iszero(index) {\n                index := tload(NEXT_INDEX)\n                if iszero(index) { index := 1 }\n                tstore(NEXT_INDEX, add(index, 1))\n                tstore(slot, index)\n            }\n        }\n    }\n\n    function end() internal {\n        if (!_running()) revert();\n        uint256 reportIndex;\n        uint256 addressCount;\n        uint256 splitCount;\n        address sender_;\n        address receiver_;\n        uint256 amount;\n        assembly {\n            reportIndex := tload(REPORT_INDEX)\n            let next := tload(NEXT_INDEX)\n            if gt(next, 0) { addressCount := sub(next, 1) }\n            splitCount := tload(SPLIT_COUNT)\n            sender_ := tload(SENDER)\n            receiver_ := tload(RECEIVER)\n            amount := tload(AMOUNT)\n        }\n\n        uint256 totalBuffers;\n        unchecked {\n            totalBuffers = (reportIndex + RESERVED_PAIRS + REPORTS_PER_BUFFER - 1) / REPORTS_PER_BUFFER;\n        }\n\n        bytes memory blob = new bytes(totalBuffers * 32);\n        for (uint256 bufferIndex = 0; bufferIndex < totalBuffers; bufferIndex++) {\n            bytes32 buffer;\n            assembly {\n                buffer := tload(add(add(BUFFER_OFFSET, shl(RUN_STRIDE_BITS, tload(RUN_COUNTER))), bufferIndex))\n            }\n            if (bufferIndex == 0) {\n                buffer |= bytes32(uint256(INDEX_BYTES)) | bytes32(addressCount << 8)\n                | bytes32(uint256(uint32(reportIndex)) << 32) | bytes32(uint256(uint32(splitCount)) << 64);\n            }\n            assembly (\"memory-safe\") {\n                mstore(add(add(blob, 0x20), mul(bufferIndex, 0x20)), buffer)\n            }\n        }\n\n        reportPointer[totalReports] = SSTORE2.write(blob);\n        metadata[totalReports] = Metadata({\n            sender: sender_, amount: uint96(amount), receiver: receiver_, timestamp: uint48(block.timestamp)\n        });\n        totalReports++;\n\n        assembly {\n            tstore(REPORT_INDEX, 0)\n            tstore(RUNNING, 0)\n            tstore(NEXT_INDEX, 0)\n            tstore(SPLIT_COUNT, 0)\n        }\n\n        emit Activation(sender_, receiver_, amount);\n    }\n\n    function receiver() external view returns (address) {\n        if (!_running()) revert();\n        address receiver_;\n        assembly {\n            receiver_ := tload(RECEIVER)\n        }\n        return receiver_;\n    }\n\n    function _running() internal view returns (bool running) {\n        assembly {\n            running := iszero(iszero(tload(RUNNING)))\n        }\n    }\n}\n"},"contracts/lib/report/TxReport.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\nimport \"./IReportRoot.sol\";\nimport \"../tx/RecoverableNode.sol\";\n\nabstract contract TxReport is RecoverableNode {\n    constructor(address _root) RecoverableNode(_root) {}\n\n    receive() external payable {\n        _arrive();\n    }\n\n    fallback() external payable {\n        _arrive();\n    }\n\n    function _arrive() private {\n        if (msg.sender != root) {\n            IReportRoot(root).report(msg.sender);\n        }\n        onReceive();\n    }\n\n    function onReceive() internal virtual;\n}\n"},"contracts/lib/sculpture/ILegacyUntitled.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\ninterface ILegacyUntitled {\n    struct ReportMetadata {\n        uint256 timestamp;\n        address sender;\n    }\n\n    function ownerOf(uint256 id) external view returns (address);\n    function transferFrom(address from, address to, uint256 id) external;\n    function safeTransferFrom(address from, address to, uint256 id) external;\n    function withdraw() external;\n    function totalReports() external view returns (uint256);\n    function getReport(uint256 index) external view returns (bytes32[] memory, ReportMetadata memory);\n}\n\ninterface ILegacyMetadata {\n    function collection() external view returns (address);\n    function wrapper() external view returns (address);\n    function sculpture() external view returns (address);\n    function ready() external view returns (bool);\n    function tokenURI(uint256 id) external view returns (string memory);\n}\n"},"contracts/lib/sculpture/SculptureToken.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\nimport \"solady/src/tokens/ERC721.sol\";\n\nabstract contract SculptureToken is ERC721 {\n    error UnexpectedValue();\n    error InvalidTokenRecipient();\n\n    function approve(address account, uint256 tokenId) public payable override {\n        if (msg.value != 0) revert UnexpectedValue();\n        super.approve(account, tokenId);\n    }\n\n    function _beforeTokenTransfer(address, address to, uint256) internal virtual override {\n        if (msg.value != 0) revert UnexpectedValue();\n        if (to == address(this)) revert InvalidTokenRecipient();\n    }\n}\n"},"contracts/lib/sculpture/TransactionSculpture.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\nimport \"solady/src/tokens/ERC721.sol\";\nimport \"solady/src/utils/LibString.sol\";\nimport \"solady/src/utils/ReentrancyGuard.sol\";\nimport \"../report/ReportRoot.sol\";\nimport \"../render/Render.sol\";\nimport \"../../TX.sol\";\nimport \"./SculptureToken.sol\";\nimport \"../tx/RecoverableNode.sol\";\n\nabstract contract TransactionSculpture is SculptureToken, ReportRoot, ReentrancyGuard {\n    address public render;\n    address public immutable t;\n    uint256 private constant BUSY = uint256(keccak256(\"transaction-sculpture.busy\"));\n\n    event RendererSet(address indexed renderer);\n    event ETHRecovered(address indexed source, address indexed to, uint256 amount);\n\n    error NothingToSend();\n    error OnlyTX();\n    error AlreadyMinted();\n    error NotOwner();\n    error NotArtist();\n    error InvalidRenderer();\n    error InvalidReceiver();\n    error InvalidNode();\n\n    constructor(address _tx, address _render) {\n        t = _tx;\n        render = _render;\n    }\n\n    modifier moves(address receiver) {\n        if (msg.value == 0) revert NothingToSend();\n        _checkReceiver(receiver);\n        _enter();\n        _;\n        _leave();\n    }\n\n    modifier idle() {\n        _enter();\n        _;\n        _leave();\n    }\n\n    function _enter() private {\n        uint256 slot = BUSY;\n        bool busy;\n        assembly {\n            busy := tload(slot)\n        }\n        if (busy || _running()) revert ActivationRunning();\n        assembly {\n            tstore(slot, 1)\n        }\n    }\n\n    function _leave() private {\n        uint256 slot = BUSY;\n        assembly {\n            tstore(slot, 0)\n        }\n    }\n\n    function _checkReceiver(address receiver) internal view {\n        if (receiver == address(0) || receiver == address(this) || _isNode(receiver)) revert InvalidReceiver();\n    }\n\n    function setRender(address renderer) external {\n        if (msg.sender != TX(payable(t)).owner()) revert NotArtist();\n        if (renderer.code.length == 0) revert InvalidRenderer();\n        render = renderer;\n        emit RendererSet(renderer);\n    }\n\n    receive() external payable {\n        send(msg.sender);\n    }\n\n    function send(address receiver) public payable virtual;\n\n    function id() public pure virtual returns (uint256);\n\n    function mint(address to) external virtual {\n        _mintOriginal(to);\n    }\n\n    function _mintOriginal(address to) internal {\n        if (msg.sender != t) revert OnlyTX();\n        if (_exists(id())) revert AlreadyMinted();\n        _mint(to, id());\n    }\n\n    function _exists(uint256 tokenId) internal view override returns (bool) {\n        return _ownerOf(tokenId) != address(0);\n    }\n\n    function withdraw() external virtual idle nonReentrant {\n        if (msg.sender != owner()) revert NotOwner();\n        (bool sent,) = msg.sender.call{value: address(this).balance}(\"\");\n        require(sent);\n    }\n\n    function recoverETH(address node, address payable to) external idle nonReentrant {\n        if (msg.sender != owner()) revert NotOwner();\n        _checkReceiver(to);\n        uint256 amount = node.balance;\n        if (node == address(this)) {\n            (bool sent,) = to.call{value: amount}(\"\");\n            require(sent);\n        } else {\n            if (!_isNode(node)) revert InvalidNode();\n            RecoverableNode(node).recoverETH(to);\n        }\n        emit ETHRecovered(node, to, amount);\n    }\n\n    function addresses() public view virtual returns (address[] memory addrs) {\n        addrs = new address[](1);\n        addrs[0] = address(this);\n    }\n\n    function owner() public view virtual returns (address own) {\n        own = _ownerOf(id());\n        if (own != address(0) && own == t) {\n            (address sculptureAddr, bool wrapped,) = TX(payable(t)).sculptures(id());\n            if (sculptureAddr == address(this) && wrapped) {\n                own = ERC721(t).ownerOf(id());\n            }\n        }\n    }\n\n    function title() public view virtual returns (string memory) {\n        return \"Untitled\";\n    }\n\n    function authors() external view virtual returns (string[] memory authors_) {\n        authors_ = new string[](1);\n        authors_[0] = \"0xfff\";\n    }\n\n    function urls() external view virtual returns (string[] memory urls_) {\n        return urls_;\n    }\n\n    function text() external view virtual returns (string memory) {\n        return \"\";\n    }\n\n    function name() public view override returns (string memory) {\n        return title();\n    }\n\n    function symbol() public pure override returns (string memory) {\n        return string.concat(\"TX\", LibString.toString(id()));\n    }\n\n    function tokenURI(uint256 tokenId) public view override returns (string memory) {\n        if (!_exists(tokenId)) revert TokenDoesNotExist();\n        if (render == address(0)) return \"\";\n        return IRender(render).tokenURI(tokenId);\n    }\n}\n"},"contracts/lib/sculpture/TransactionSculptureDiminishing.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\nimport \"./TransactionSculptureStaged.sol\";\nimport \"../tx/Table.sol\";\n\nabstract contract TransactionSculptureDiminishing is TransactionSculptureStaged {\n    uint256 constant COUNT = Nodes.COUNT;\n    uint256 constant NODES_PER_SETUP = 16;\n    uint256 constant ROT_BITS_PER_DAY = 1;\n    uint256 constant ROT_CAP = 64;\n\n    bytes32 public immutable seed;\n    uint8 public immutable initialLife;\n\n    uint48 private _lastActivation;\n    uint208 private _rotBacklog;\n\n    error InvalidLife();\n    error NodeOutOfPlace();\n    error CouldNotDeliver();\n\n    constructor(address t, address r, bytes32 _seed, uint8 _initialLife) TransactionSculptureStaged(t, r) {\n        if (_initialLife > 7) revert InvalidLife();\n        seed = _seed;\n        initialLife = _initialLife;\n        _lastActivation = uint48(block.timestamp);\n    }\n\n    function setupBatches() public pure override returns (uint256) {\n        return _batches(COUNT, NODES_PER_SETUP);\n    }\n\n    function _setupBatch(uint256 batch) internal override {\n        (uint256 from, uint256 until) = _slice(batch, NODES_PER_SETUP, COUNT);\n        for (uint256 i = from; i < until; i++) {\n            address node = _node(address(new Table(uint8(i), initialTable(seed, i, initialLife))));\n            if (node != Nodes.addr(address(this), i)) revert NodeOutOfPlace();\n        }\n    }\n\n    fallback() external payable {\n        send(msg.sender);\n    }\n\n    function send(address receiver) public payable override built moves(receiver) {\n        uint256 activation = totalReports;\n        rot(activation);\n        begin(msg.sender, receiver, msg.value);\n\n        bytes32 h = keccak256(abi.encodePacked(block.prevrandao, block.timestamp, msg.sender, msg.value, activation));\n        uint256 start = uint256(h) & 31;\n        (bool sent, bytes memory ret) =\n            Nodes.addr(address(this), start).call{value: msg.value}(abi.encodePacked(activation, receiver, uint8(0)));\n        if (!sent) {\n            if (ret.length > 0) {\n                assembly {\n                    revert(add(ret, 32), mload(ret))\n                }\n            }\n            (sent,) = receiver.call{value: msg.value}(\"\");\n        }\n        if (!sent) revert CouldNotDeliver();\n\n        end();\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                  ROT\n    //////////////////////////////////////////////////////////////*/\n\n    function rot(uint256 activation) internal {\n        uint256 last = _lastActivation;\n        uint256 elapsedDays = (block.timestamp - last) / 1 days;\n        uint256 owed = _rotBacklog + elapsedDays * ROT_BITS_PER_DAY;\n        if (owed == 0) return;\n\n        uint256 units = owed > ROT_CAP ? ROT_CAP : owed;\n        if (elapsedDays > 0) _lastActivation = uint48(last + elapsedDays * 1 days);\n        _rotBacklog = uint208(owed - units);\n\n        for (uint256 n = 0; n < units; n++) {\n            uint256 r = uint256(keccak256(abi.encodePacked(activation, block.prevrandao, n)));\n            try Table(payable(Nodes.addr(address(this), r & 31))).rot(uint8((r >> 8) & 255)) {} catch {}\n        }\n    }\n\n    function lastActivation() external view returns (uint256) {\n        return _lastActivation;\n    }\n\n    function rotBacklog() external view returns (uint256) {\n        return _rotBacklog;\n    }\n\n    function pendingRot() external view returns (uint256) {\n        uint256 owed = _rotBacklog + ((block.timestamp - _lastActivation) / 1 days) * ROT_BITS_PER_DAY;\n        return owed > ROT_CAP ? ROT_CAP : owed;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                 TABLES\n    //////////////////////////////////////////////////////////////*/\n\n    function initialTable(bytes32 _seed, uint256 i, uint8 life) public pure returns (bytes32) {\n        uint256 r = uint256(keccak256(abi.encodePacked(_seed, i)));\n        uint256 t;\n        for (uint256 k = 0; k < 32; k++) {\n            uint256 neighbour = (i + 1 + ((r >> (k << 3)) & 0xff) % (COUNT - 1)) % COUNT;\n            t |= ((neighbour << 3) | life) << (k << 3);\n        }\n        return bytes32(t);\n    }\n\n    function nodeAt(uint256 i) public view returns (address) {\n        return Nodes.addr(address(this), i);\n    }\n\n    function nodes() external view returns (address[32] memory out) {\n        for (uint256 i = 0; i < COUNT; i++) {\n            out[i] = Nodes.addr(address(this), i);\n        }\n    }\n\n    function tables() external view returns (bytes32[32] memory out) {\n        for (uint256 i = 0; i < COUNT; i++) {\n            out[i] = _table(i);\n        }\n    }\n\n    function health() external view returns (uint256 totalLife, uint256 deadBytes) {\n        for (uint256 i = 0; i < COUNT; i++) {\n            if (Nodes.addr(address(this), i).code.length == 0) continue;\n            uint256 t = uint256(_table(i));\n            for (uint256 k = 0; k < 32; k++) {\n                uint256 life = (t >> (k << 3)) & 7;\n                totalLife += life;\n                if (life == 0) deadBytes++;\n            }\n        }\n    }\n\n    function _table(uint256 i) private view returns (bytes32) {\n        address node = Nodes.addr(address(this), i);\n        return node.code.length == 0 ? bytes32(0) : Table(payable(node)).table();\n    }\n\n    function addresses() public view override returns (address[] memory addrs) {\n        addrs = new address[](COUNT + 1);\n        addrs[0] = address(this);\n        for (uint256 i = 0; i < COUNT; i++) {\n            addrs[i + 1] = Nodes.addr(address(this), i);\n        }\n    }\n}\n"},"contracts/lib/sculpture/TransactionSculptureStaged.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\nimport \"solady/src/utils/LibRLP.sol\";\nimport \"./TransactionSculpture.sol\";\n\nabstract contract TransactionSculptureStaged is TransactionSculpture {\n    address public immutable deployer;\n\n    uint256 private constant CURSOR_SLOT = uint256(keccak256(\"transaction-sculpture.staged.cursor\")) - 1;\n\n    event SetupBatch(uint256 batch, uint256 batches);\n    event SetUp();\n\n    error NotSetUp();\n    error NotDeployer();\n\n    constructor(address t, address r) TransactionSculpture(t, r) {\n        deployer = msg.sender;\n    }\n\n    modifier built() {\n        if (!isSetUp()) revert NotSetUp();\n        _;\n    }\n\n    function setupBatches() public pure virtual returns (uint256);\n\n    function _setupBatch(uint256 batch) internal virtual;\n\n    function setupCursor() public view returns (uint256 cursor) {\n        uint256 slot = CURSOR_SLOT;\n        assembly {\n            cursor := sload(slot)\n        }\n    }\n\n    function isSetUp() public view returns (bool) {\n        return setupCursor() >= setupBatches();\n    }\n\n    function setup() external {\n        if (msg.sender != deployer) revert NotDeployer();\n        uint256 batch = setupCursor();\n        uint256 batches = setupBatches();\n        if (batch >= batches) return;\n        _setupBatch(batch);\n        uint256 slot = CURSOR_SLOT;\n        assembly {\n            sstore(slot, add(batch, 1))\n        }\n        emit SetupBatch(batch + 1, batches);\n        if (batch + 1 == batches) emit SetUp();\n    }\n\n    function mint(address to) external override built {\n        _mintOriginal(to);\n    }\n\n    function _slice(uint256 batch, uint256 per, uint256 total) internal pure returns (uint256 from, uint256 until) {\n        from = batch * per;\n        until = from + per;\n        if (from > total) from = total;\n        if (until > total) until = total;\n    }\n\n    function _batches(uint256 total, uint256 per) internal pure returns (uint256) {\n        return (total + per - 1) / per;\n    }\n\n    function _created(uint256 n) internal view returns (address) {\n        return LibRLP.computeAddress(address(this), n);\n    }\n}\n"},"contracts/lib/tx/RecoverableNode.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\nabstract contract RecoverableNode {\n    address internal immutable root;\n\n    error RecoveryDenied();\n    error RecoveryFailed();\n\n    constructor(address root_) {\n        root = root_;\n    }\n\n    function recoverETH(address payable to) external {\n        if (msg.sender != root) revert RecoveryDenied();\n        (bool sent,) = to.call{value: address(this).balance}(\"\");\n        if (!sent) revert RecoveryFailed();\n    }\n}\n"},"contracts/lib/tx/Table.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\nimport \"../report/TxReport.sol\";\n\nlibrary Nodes {\n    uint256 internal constant COUNT = 32;\n\n    function addr(address root, uint256 i) internal pure returns (address) {\n        bytes32 h = keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), root, bytes1(uint8(i + 1))));\n        return address(uint160(uint256(h)));\n    }\n}\n\ncontract Table is TxReport {\n    event Wear(uint8 node, uint8 byteIndex, uint8 newLife);\n    event Flip(uint8 node, uint8 bitIndex);\n    event Rot(uint8 node, uint8 bitIndex, bool wasSet);\n    event Hop(uint8 fromNode, uint8 toNode, uint256 value, uint256 activationId);\n    event Delivered(uint8 node, address to, uint256 value, uint256 activationId);\n\n    error NotRoot();\n    error CouldNotDeliver();\n\n    uint256 constant MAX_HOPS = 32;\n    uint256 constant CALLDATA_BYTES = 53;\n\n    uint8 immutable index;\n    bytes32 public table;\n\n    constructor(uint8 _index, bytes32 _table) TxReport(msg.sender) {\n        index = _index;\n        table = _table;\n    }\n\n    function onReceive() internal override {\n        address to;\n        uint256 hop;\n        uint256 id;\n        assembly {\n            id := calldataload(0)\n            to := shr(96, calldataload(32))\n            hop := byte(0, calldataload(52))\n        }\n        if (msg.data.length < CALLDATA_BYTES) to = msg.sender;\n\n        uint256 r = uint256(keccak256(abi.encodePacked(block.prevrandao, block.timestamp, id, hop)));\n        uint256 i = r & 31;\n        uint256 b = (r >> 8) & 255;\n\n        uint256 t = uint256(table);\n        uint256 cell = (t >> (i << 3)) & 0xff;\n        uint256 life = cell & 7;\n        bool onward = life > 0 && hop + 1 < MAX_HOPS;\n\n        if (onward) {\n            unchecked {\n                t -= 1 << (i << 3);\n            }\n            emit Wear(index, uint8(i), uint8(life - 1));\n        }\n        t ^= 1 << b;\n        table = bytes32(t);\n        emit Flip(index, uint8(b));\n\n        if (onward) {\n            uint8 next = uint8(cell >> 3);\n            emit Hop(index, next, msg.value, id);\n            (bool ok, bytes memory ret) =\n                Nodes.addr(root, next).call{value: msg.value}(abi.encodePacked(id, to, uint8(hop + 1)));\n            if (ok) return;\n            if (ret.length > 0) {\n                assembly {\n                    revert(add(ret, 32), mload(ret))\n                }\n            }\n        }\n\n        emit Delivered(index, to, msg.value, id);\n        (bool sent,) = to.call{value: msg.value}(\"\");\n        if (!sent) revert CouldNotDeliver();\n    }\n\n    function rot(uint8 bit) external {\n        if (msg.sender != root) revert NotRoot();\n        uint256 mask = 1 << bit;\n        uint256 t = uint256(table);\n        bool wasSet = t & mask != 0;\n        if (wasSet) table = bytes32(t ^ mask);\n        emit Rot(index, bit, wasSet);\n    }\n}\n"},"contracts/sculptures/DiminishingReturns.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\n////////////////////////////////////////////////////////////////////////\n//                                                                    //\n//                                                                    //\n//      |    |    |    |    |    |    |----|    |    |    |    |      //\n//      |    |    |    |    |    |    |    |----|    |    |    |      //\n//      |    |    |----|----|----|----|----|----|    |    |    |      //\n//      |    |    |----|----|----|----|----|----|----|    |    |      //\n//      |----|----|----|----|----|----|----|----|----|    |    |      //\n//      |----|----|----|----|----|    |    |    |    |    |    |      //\n//      |    |    |----|----|----|    |    |    |    |    |    |      //\n//      |    |    |----|----|----|----|----|----|----|----|    |      //\n//      |    |----|----|----|----|----|----|----|----|----|    |      //\n//      |    |----|----|----|----|----|----|----|----|----|    |      //\n//      |    |    |----|----|----|----|----|----|----|----|    |      //\n//      |    |    |----|----|----|----|----|----|----|----|----|      //\n//      |    |    |    |----|----|----|----|----|----|----|----|      //\n//      |    |    |    |----|    |    |    |    |    |    |    |      //\n//                                                                    //\n//                        Diminishing Returns                         //\n//                                                             fff    //\n//                                                                    //\n////////////////////////////////////////////////////////////////////////\n\nimport \"../lib/sculpture/TransactionSculptureDiminishing.sol\";\n\ncontract DiminishingReturns is TransactionSculptureDiminishing {\n    bytes32 constant SEED = 0x0000000000000000000000000000000000000000000000000000000000000fff;\n    uint8 constant LIFE = 7;\n\n    constructor(address t, address r) TransactionSculptureDiminishing(t, r, SEED, LIFE) {}\n\n    function id() public pure override returns (uint256) {\n        return 7;\n    }\n\n    function title() public pure override returns (string memory) {\n        return \"Diminishing Returns\";\n    }\n}\n"},"contracts/TX.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\n////////////////////////////////////////////////////////////////////////\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                             |--|__|                                //\n//                                                                    //\n//                      Transaction Sculptures                        //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                             fff    //\n//                                                                    //\n////////////////////////////////////////////////////////////////////////\n\nimport \"solady/src/auth/Ownable.sol\";\nimport \"solady/src/utils/ReentrancyGuard.sol\";\nimport \"./lib/sculpture/SculptureToken.sol\";\nimport \"./lib/sculpture/TransactionSculpture.sol\";\nimport \"./lib/sculpture/ILegacyUntitled.sol\";\nimport \"./UntitledTXWrapper.sol\";\n\ncontract TX is SculptureToken, Ownable, ReentrancyGuard {\n    struct Sculpture {\n        address sculpture;\n        bool wrapped;\n        bool minted;\n    }\n\n    address public constant LEGACY_UNTITLED = 0x117553ba213Ee4fa51d91DbafF7059F0BE3A6779;\n    address public immutable legacyWrapper;\n    address public legacyMetadata;\n    address public legacyAsset;\n\n    mapping(uint256 => Sculpture) public sculptures;\n\n    event LegacyMetadataSet(address indexed metadata);\n    event ETHRecovered(address indexed to, uint256 amount);\n    event LegacyBalanceWithdrawn(address indexed owner, uint256 amount);\n    event Wrapped(uint256 indexed txId, address indexed sculpture, address indexed owner);\n    event Unwrapped(uint256 indexed txId, address indexed sculpture, address indexed owner);\n    event Recovered(uint256 indexed txId, address indexed sculpture, address indexed to);\n\n    error MetadataNotSet();\n    error InvalidMetadata();\n    error InvalidReceiver();\n    error WrongCollection();\n    error WrongSculpture();\n    error WrongWrapper();\n    error BundleNotSet();\n    error InvalidSculpture();\n    error SculptureAlreadySet();\n    error SculptureNotSet();\n    error WrongId();\n    error AlreadyMinted();\n    error NotMinted();\n    error AlreadyWrapped();\n    error NotWrapped();\n    error NotOwner();\n    error CustodyFailed();\n    error UnknownAsset();\n    error NotStranded();\n    error NotHeld();\n    error WithdrawalFailed();\n    error OnlyLegacy();\n\n    constructor(address wrapper) {\n        legacyWrapper = wrapper;\n        _initializeOwner(msg.sender);\n        sculptures[0] = Sculpture({sculpture: LEGACY_UNTITLED, wrapped: false, minted: true});\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                 SETUP\n    //////////////////////////////////////////////////////////////*/\n\n    function setLegacyMetadata(address metadata) external onlyOwner {\n        if (metadata.code.length == 0) revert InvalidMetadata();\n        if (ILegacyMetadata(metadata).collection() != address(this)) revert WrongCollection();\n        if (ILegacyMetadata(metadata).sculpture() != LEGACY_UNTITLED) revert WrongSculpture();\n        if (ILegacyMetadata(metadata).wrapper() != legacyWrapper) revert WrongWrapper();\n        if (!ILegacyMetadata(metadata).ready()) revert BundleNotSet();\n        legacyMetadata = metadata;\n        emit LegacyMetadataSet(metadata);\n    }\n\n    function set(uint256 id, address sculpture) external onlyOwner {\n        if (sculpture == address(0)) revert InvalidSculpture();\n        if (sculptures[id].sculpture != address(0)) revert SculptureAlreadySet();\n        if (sculpture.code.length == 0) revert InvalidSculpture();\n        if (TransactionSculpture(payable(sculpture)).id() != id) revert WrongId();\n        if (TransactionSculpture(payable(sculpture)).t() != address(this)) revert WrongCollection();\n        sculptures[id].sculpture = sculpture;\n    }\n\n    function mint(uint256 id, address to) external onlyOwner nonReentrant {\n        if (sculptures[id].sculpture == address(0)) revert SculptureNotSet();\n        if (sculptures[id].minted) revert AlreadyMinted();\n        sculptures[id].wrapped = true;\n        sculptures[id].minted = true;\n        address sculpture = sculptures[id].sculpture;\n        TransactionSculpture(payable(sculpture)).mint(address(this));\n        if (ERC721(sculpture).ownerOf(id) != address(this)) revert CustodyFailed();\n        _safeMint(to, id);\n        emit Wrapped(id, sculpture, to);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                CUSTODY\n    //////////////////////////////////////////////////////////////*/\n\n    function wrap(uint256 id) external nonReentrant {\n        if (id == 0) return _wrapLegacy(LEGACY_UNTITLED);\n        if (sculptures[id].sculpture == address(0)) revert SculptureNotSet();\n        if (sculptures[id].wrapped) revert AlreadyWrapped();\n        if (!sculptures[id].minted) revert NotMinted();\n        address sculpture = sculptures[id].sculpture;\n        if (ERC721(sculpture).ownerOf(id) != msg.sender) revert NotOwner();\n        sculptures[id].wrapped = true;\n        ERC721(sculpture).transferFrom(msg.sender, address(this), id);\n        if (ERC721(sculpture).ownerOf(id) != address(this)) revert CustodyFailed();\n        _safeMint(msg.sender, id);\n        emit Wrapped(id, sculpture, msg.sender);\n    }\n\n    function wrapLegacy(address asset) external nonReentrant {\n        _wrapLegacy(asset);\n    }\n\n    function _wrapLegacy(address asset) private {\n        if (asset != LEGACY_UNTITLED && (asset == address(0) || asset != legacyWrapper)) revert UnknownAsset();\n        if (sculptures[0].wrapped) revert AlreadyWrapped();\n        if (ERC721(asset).ownerOf(0) != msg.sender) revert NotOwner();\n        if (legacyMetadata == address(0)) revert MetadataNotSet();\n        sculptures[0].wrapped = true;\n        legacyAsset = asset;\n        ERC721(asset).transferFrom(msg.sender, address(this), 0);\n        if (ERC721(asset).ownerOf(0) != address(this)) revert CustodyFailed();\n        _safeMint(msg.sender, 0);\n        emit Wrapped(0, asset, msg.sender);\n    }\n\n    function unwrap(uint256 id) external nonReentrant {\n        if (sculptures[id].sculpture == address(0)) revert SculptureNotSet();\n        if (ownerOf(id) != msg.sender) revert NotOwner();\n        if (!sculptures[id].wrapped) revert NotWrapped();\n        address sculpture = id == 0 ? legacyAsset : sculptures[id].sculpture;\n        _burn(id);\n        sculptures[id].wrapped = false;\n        if (id == 0) legacyAsset = address(0);\n        ERC721(sculpture).safeTransferFrom(address(this), msg.sender, id);\n        emit Unwrapped(id, sculpture, msg.sender);\n    }\n\n    function recover(uint256 id, address to) external onlyOwner nonReentrant {\n        address sculpture = sculptures[id].sculpture;\n        if (sculpture == address(0)) revert SculptureNotSet();\n        if (!sculptures[id].minted || sculptures[id].wrapped || _exists(id)) revert NotStranded();\n        if (id == 0) {\n            if (legacyMetadata == address(0)) revert MetadataNotSet();\n            if (ERC721(sculpture).ownerOf(0) == legacyWrapper) sculpture = legacyWrapper;\n            legacyAsset = sculpture;\n        }\n        if (ERC721(sculpture).ownerOf(id) != address(this)) revert NotHeld();\n        sculptures[id].wrapped = true;\n        _safeMint(to, id);\n        emit Recovered(id, sculpture, to);\n        emit Wrapped(id, sculpture, to);\n    }\n\n    function withdrawLegacyBalance() external nonReentrant {\n        if (ownerOf(0) != msg.sender) revert NotOwner();\n        if (!sculptures[0].wrapped) revert NotWrapped();\n        uint256 beforeBalance = address(this).balance;\n        if (legacyAsset == LEGACY_UNTITLED) ILegacyUntitled(LEGACY_UNTITLED).withdraw();\n        else UntitledTXWrapper(payable(legacyAsset)).withdrawLegacyBalance();\n        uint256 amount = address(this).balance - beforeBalance;\n        (bool sent,) = msg.sender.call{value: amount}(\"\");\n        if (!sent) revert WithdrawalFailed();\n        emit LegacyBalanceWithdrawn(msg.sender, amount);\n    }\n\n    function recoverETH(address payable to) external onlyOwner nonReentrant {\n        if (to == address(0) || to == address(this)) revert InvalidReceiver();\n        uint256 amount = address(this).balance;\n        (bool sent,) = to.call{value: amount}(\"\");\n        if (!sent) revert WithdrawalFailed();\n        emit ETHRecovered(to, amount);\n    }\n\n    receive() external payable {\n        if (msg.sender != LEGACY_UNTITLED && (msg.sender != legacyWrapper || msg.sender == address(0))) {\n            revert OnlyLegacy();\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                 ERC721\n    //////////////////////////////////////////////////////////////*/\n\n    function name() public pure override returns (string memory) {\n        return \"Transaction Sculptures\";\n    }\n\n    function symbol() public pure override returns (string memory) {\n        return \"TX\";\n    }\n\n    function tokenURI(uint256 id) public view override returns (string memory) {\n        address sculpture = sculptures[id].sculpture;\n        if (sculpture == address(0)) revert SculptureNotSet();\n        if (!_exists(id)) revert TokenDoesNotExist();\n        if (id == 0) return ILegacyMetadata(legacyMetadata).tokenURI(0);\n        return TransactionSculpture(payable(sculpture)).tokenURI(TransactionSculpture(payable(sculpture)).id());\n    }\n\n    function _exists(uint256 id) internal view override returns (bool) {\n        return _ownerOf(id) != address(0);\n    }\n}\n"},"contracts/UntitledTXWrapper.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.37;\n\n////////////////////////////////////////////////////////////////////////\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                             |--|__|                                //\n//                                                                    //\n//                            0 (Wrapped)                             //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n//                                                                    //\n////////////////////////////////////////////////////////////////////////\n\nimport \"solady/src/auth/Ownable.sol\";\nimport \"solady/src/utils/ReentrancyGuard.sol\";\nimport \"./lib/sculpture/SculptureToken.sol\";\nimport \"./lib/sculpture/ILegacyUntitled.sol\";\n\ncontract UntitledTXWrapper is SculptureToken, Ownable, ReentrancyGuard {\n    address public constant ORIGINAL = 0x117553ba213Ee4fa51d91DbafF7059F0BE3A6779;\n    address public metadata;\n\n    event MetadataSet(address indexed metadata);\n    event Wrapped(address indexed owner);\n    event Unwrapped(address indexed owner);\n    event ETHRecovered(address indexed to, uint256 amount);\n    event LegacyBalanceWithdrawn(address indexed owner, uint256 amount);\n    event Recovered(address indexed to);\n\n    error InvalidOwner();\n    error MetadataNotSet();\n    error InvalidMetadata();\n    error InvalidReceiver();\n    error WrongWrapper();\n    error WrongCollection();\n    error WrongSculpture();\n    error BundleNotSet();\n    error NotOwner();\n    error CustodyFailed();\n    error NotStranded();\n    error NotHeld();\n    error WithdrawalFailed();\n    error OnlyLegacy();\n\n    constructor(address owner_) {\n        if (owner_ == address(0)) revert InvalidOwner();\n        _initializeOwner(owner_);\n    }\n\n    function setMetadata(address metadata_) external onlyOwner {\n        if (metadata_.code.length == 0) revert InvalidMetadata();\n        if (ILegacyMetadata(metadata_).wrapper() != address(this)) revert WrongWrapper();\n        if (ILegacyMetadata(metadata_).sculpture() != ORIGINAL) revert WrongSculpture();\n        if (metadata != address(0) && ILegacyMetadata(metadata_).collection() != ILegacyMetadata(metadata).collection()) {\n            revert WrongCollection();\n        }\n        if (!ILegacyMetadata(metadata_).ready()) revert BundleNotSet();\n        metadata = metadata_;\n        emit MetadataSet(metadata_);\n    }\n\n    function wrap() external nonReentrant {\n        if (metadata == address(0)) revert MetadataNotSet();\n        if (ILegacyUntitled(ORIGINAL).ownerOf(0) != msg.sender) revert NotOwner();\n        ILegacyUntitled(ORIGINAL).transferFrom(msg.sender, address(this), 0);\n        if (ILegacyUntitled(ORIGINAL).ownerOf(0) != address(this)) revert CustodyFailed();\n        _safeMint(msg.sender, 0);\n        emit Wrapped(msg.sender);\n    }\n\n    function unwrap() external nonReentrant {\n        if (ownerOf(0) != msg.sender) revert NotOwner();\n        _burn(0);\n        ILegacyUntitled(ORIGINAL).safeTransferFrom(address(this), msg.sender, 0);\n        emit Unwrapped(msg.sender);\n    }\n\n    function recover(address to) external onlyOwner nonReentrant {\n        if (metadata == address(0)) revert MetadataNotSet();\n        if (_exists(0)) revert NotStranded();\n        if (ILegacyUntitled(ORIGINAL).ownerOf(0) != address(this)) revert NotHeld();\n        _safeMint(to, 0);\n        emit Recovered(to);\n        emit Wrapped(to);\n    }\n\n    function withdrawLegacyBalance() external nonReentrant {\n        if (ownerOf(0) != msg.sender) revert NotOwner();\n        uint256 beforeBalance = address(this).balance;\n        ILegacyUntitled(ORIGINAL).withdraw();\n        uint256 amount = address(this).balance - beforeBalance;\n        (bool sent,) = msg.sender.call{value: amount}(\"\");\n        if (!sent) revert WithdrawalFailed();\n        emit LegacyBalanceWithdrawn(msg.sender, amount);\n    }\n\n    function recoverETH(address payable to) external onlyOwner nonReentrant {\n        if (to == address(0) || to == address(this)) revert InvalidReceiver();\n        uint256 amount = address(this).balance;\n        (bool sent,) = to.call{value: amount}(\"\");\n        if (!sent) revert WithdrawalFailed();\n        emit ETHRecovered(to, amount);\n    }\n\n    receive() external payable {\n        if (msg.sender != ORIGINAL) revert OnlyLegacy();\n    }\n\n    function name() public pure override returns (string memory) {\n        return \"Untitled (Transaction Sculpture)\";\n    }\n\n    function symbol() public pure override returns (string memory) {\n        return \"TX0\";\n    }\n\n    function tokenURI(uint256 id) public view override returns (string memory) {\n        if (!_exists(id)) revert TokenDoesNotExist();\n        return ILegacyMetadata(metadata).tokenURI(0);\n    }\n}\n"},"solady/src/auth/Ownable.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)\n///\n/// @dev Note:\n/// This implementation does NOT auto-initialize the owner to `msg.sender`.\n/// You MUST call the `_initializeOwner` in the constructor / initializer.\n///\n/// While the ownable portion follows\n/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,\n/// the nomenclature for the 2-step ownership handover may be unique to this codebase.\nabstract contract Ownable {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The caller is not authorized to call the function.\n    error Unauthorized();\n\n    /// @dev The `newOwner` cannot be the zero address.\n    error NewOwnerIsZeroAddress();\n\n    /// @dev The `pendingOwner` does not have a valid handover request.\n    error NoHandoverRequest();\n\n    /// @dev Cannot double-initialize.\n    error AlreadyInitialized();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                           EVENTS                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.\n    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be\n    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),\n    /// despite it not being as lightweight as a single argument event.\n    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);\n\n    /// @dev An ownership handover to `pendingOwner` has been requested.\n    event OwnershipHandoverRequested(address indexed pendingOwner);\n\n    /// @dev The ownership handover to `pendingOwner` has been canceled.\n    event OwnershipHandoverCanceled(address indexed pendingOwner);\n\n    /// @dev `keccak256(bytes(\"OwnershipTransferred(address,address)\"))`.\n    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =\n        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;\n\n    /// @dev `keccak256(bytes(\"OwnershipHandoverRequested(address)\"))`.\n    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =\n        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;\n\n    /// @dev `keccak256(bytes(\"OwnershipHandoverCanceled(address)\"))`.\n    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =\n        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                          STORAGE                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The owner slot is given by:\n    /// `bytes32(~uint256(uint32(bytes4(keccak256(\"_OWNER_SLOT_NOT\")))))`.\n    /// It is intentionally chosen to be a high value\n    /// to avoid collision with lower slots.\n    /// The choice of manual storage layout is to enable compatibility\n    /// with both regular and upgradeable contracts.\n    bytes32 internal constant _OWNER_SLOT =\n        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;\n\n    /// The ownership handover slot of `newOwner` is given by:\n    /// ```\n    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))\n    ///     let handoverSlot := keccak256(0x00, 0x20)\n    /// ```\n    /// It stores the expiry timestamp of the two-step ownership handover.\n    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     INTERNAL FUNCTIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.\n    function _guardInitializeOwner() internal pure virtual returns (bool guard) {}\n\n    /// @dev Initializes the owner directly without authorization guard.\n    /// This function must be called upon initialization,\n    /// regardless of whether the contract is upgradeable or not.\n    /// This is to enable generalization to both regular and upgradeable contracts,\n    /// and to save gas in case the initial owner is not the caller.\n    /// For performance reasons, this function will not check if there\n    /// is an existing owner.\n    function _initializeOwner(address newOwner) internal virtual {\n        if (_guardInitializeOwner()) {\n            /// @solidity memory-safe-assembly\n            assembly {\n                let ownerSlot := _OWNER_SLOT\n                if sload(ownerSlot) {\n                    mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.\n                    revert(0x1c, 0x04)\n                }\n                // Clean the upper 96 bits.\n                newOwner := shr(96, shl(96, newOwner))\n                // Store the new value.\n                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))\n                // Emit the {OwnershipTransferred} event.\n                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)\n            }\n        } else {\n            /// @solidity memory-safe-assembly\n            assembly {\n                // Clean the upper 96 bits.\n                newOwner := shr(96, shl(96, newOwner))\n                // Store the new value.\n                sstore(_OWNER_SLOT, newOwner)\n                // Emit the {OwnershipTransferred} event.\n                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)\n            }\n        }\n    }\n\n    /// @dev Sets the owner directly without authorization guard.\n    function _setOwner(address newOwner) internal virtual {\n        if (_guardInitializeOwner()) {\n            /// @solidity memory-safe-assembly\n            assembly {\n                let ownerSlot := _OWNER_SLOT\n                // Clean the upper 96 bits.\n                newOwner := shr(96, shl(96, newOwner))\n                // Emit the {OwnershipTransferred} event.\n                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)\n                // Store the new value.\n                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))\n            }\n        } else {\n            /// @solidity memory-safe-assembly\n            assembly {\n                let ownerSlot := _OWNER_SLOT\n                // Clean the upper 96 bits.\n                newOwner := shr(96, shl(96, newOwner))\n                // Emit the {OwnershipTransferred} event.\n                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)\n                // Store the new value.\n                sstore(ownerSlot, newOwner)\n            }\n        }\n    }\n\n    /// @dev Throws if the sender is not the owner.\n    function _checkOwner() internal view virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // If the caller is not the stored owner, revert.\n            if iszero(eq(caller(), sload(_OWNER_SLOT))) {\n                mstore(0x00, 0x82b42900) // `Unauthorized()`.\n                revert(0x1c, 0x04)\n            }\n        }\n    }\n\n    /// @dev Returns how long a two-step ownership handover is valid for in seconds.\n    /// Override to return a different value if needed.\n    /// Made internal to conserve bytecode. Wrap it in a public function if needed.\n    function _ownershipHandoverValidFor() internal view virtual returns (uint64) {\n        return 48 * 3600;\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  PUBLIC UPDATE FUNCTIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Allows the owner to transfer the ownership to `newOwner`.\n    function transferOwnership(address newOwner) public payable virtual onlyOwner {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(shl(96, newOwner)) {\n                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.\n                revert(0x1c, 0x04)\n            }\n        }\n        _setOwner(newOwner);\n    }\n\n    /// @dev Allows the owner to renounce their ownership.\n    function renounceOwnership() public payable virtual onlyOwner {\n        _setOwner(address(0));\n    }\n\n    /// @dev Request a two-step ownership handover to the caller.\n    /// The request will automatically expire in 48 hours (172800 seconds) by default.\n    function requestOwnershipHandover() public payable virtual {\n        unchecked {\n            uint256 expires = block.timestamp + _ownershipHandoverValidFor();\n            /// @solidity memory-safe-assembly\n            assembly {\n                // Compute and set the handover slot to `expires`.\n                mstore(0x0c, _HANDOVER_SLOT_SEED)\n                mstore(0x00, caller())\n                sstore(keccak256(0x0c, 0x20), expires)\n                // Emit the {OwnershipHandoverRequested} event.\n                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())\n            }\n        }\n    }\n\n    /// @dev Cancels the two-step ownership handover to the caller, if any.\n    function cancelOwnershipHandover() public payable virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute and set the handover slot to 0.\n            mstore(0x0c, _HANDOVER_SLOT_SEED)\n            mstore(0x00, caller())\n            sstore(keccak256(0x0c, 0x20), 0)\n            // Emit the {OwnershipHandoverCanceled} event.\n            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())\n        }\n    }\n\n    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.\n    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.\n    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute and set the handover slot to 0.\n            mstore(0x0c, _HANDOVER_SLOT_SEED)\n            mstore(0x00, pendingOwner)\n            let handoverSlot := keccak256(0x0c, 0x20)\n            // If the handover does not exist, or has expired.\n            if gt(timestamp(), sload(handoverSlot)) {\n                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.\n                revert(0x1c, 0x04)\n            }\n            // Set the handover slot to 0.\n            sstore(handoverSlot, 0)\n        }\n        _setOwner(pendingOwner);\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   PUBLIC READ FUNCTIONS                    */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the owner of the contract.\n    function owner() public view virtual returns (address result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := sload(_OWNER_SLOT)\n        }\n    }\n\n    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.\n    function ownershipHandoverExpiresAt(address pendingOwner)\n        public\n        view\n        virtual\n        returns (uint256 result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute the handover slot.\n            mstore(0x0c, _HANDOVER_SLOT_SEED)\n            mstore(0x00, pendingOwner)\n            // Load the handover slot.\n            result := sload(keccak256(0x0c, 0x20))\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         MODIFIERS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Marks a function as only callable by the owner.\n    modifier onlyOwner() virtual {\n        _checkOwner();\n        _;\n    }\n}\n"},"solady/src/tokens/ERC721.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Simple ERC721 implementation with storage hitchhiking.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC721.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721/ERC721.sol)\n///\n/// @dev Note:\n/// - The ERC721 standard allows for self-approvals.\n///   For performance, this implementation WILL NOT revert for such actions.\n///   Please add any checks with overrides if desired.\n/// - For performance, methods are made payable where permitted by the ERC721 standard.\n/// - The `safeTransfer` functions use the identity precompile (0x4)\n///   to copy memory internally.\n///\n/// If you are overriding:\n/// - NEVER violate the ERC721 invariant:\n///   the balance of an owner MUST always be equal to their number of ownership slots.\n///   The transfer functions do not have an underflow guard for user token balances.\n/// - Make sure all variables written to storage are properly cleaned\n//    (e.g. the bool value for `isApprovedForAll` MUST be either 1 or 0 under the hood).\n/// - Check that the overridden function is actually used in the function you want to\n///   change the behavior of. Much of the code has been manually inlined for performance.\nabstract contract ERC721 {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         CONSTANTS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev An account can hold up to 4294967295 tokens.\n    uint256 internal constant _MAX_ACCOUNT_BALANCE = 0xffffffff;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Only the token owner or an approved account can manage the token.\n    error NotOwnerNorApproved();\n\n    /// @dev The token does not exist.\n    error TokenDoesNotExist();\n\n    /// @dev The token already exists.\n    error TokenAlreadyExists();\n\n    /// @dev Cannot query the balance for the zero address.\n    error BalanceQueryForZeroAddress();\n\n    /// @dev Cannot mint or transfer to the zero address.\n    error TransferToZeroAddress();\n\n    /// @dev The token must be owned by `from`.\n    error TransferFromIncorrectOwner();\n\n    /// @dev The recipient's balance has overflowed.\n    error AccountBalanceOverflow();\n\n    /// @dev Cannot safely transfer to a contract that does not implement\n    /// the ERC721Receiver interface.\n    error TransferToNonERC721ReceiverImplementer();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                           EVENTS                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Emitted when token `id` is transferred from `from` to `to`.\n    event Transfer(address indexed from, address indexed to, uint256 indexed id);\n\n    /// @dev Emitted when `owner` enables `account` to manage the `id` token.\n    event Approval(address indexed owner, address indexed account, uint256 indexed id);\n\n    /// @dev Emitted when `owner` enables or disables `operator` to manage all of their tokens.\n    event ApprovalForAll(address indexed owner, address indexed operator, bool isApproved);\n\n    /// @dev `keccak256(bytes(\"Transfer(address,address,uint256)\"))`.\n    uint256 private constant _TRANSFER_EVENT_SIGNATURE =\n        0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;\n\n    /// @dev `keccak256(bytes(\"Approval(address,address,uint256)\"))`.\n    uint256 private constant _APPROVAL_EVENT_SIGNATURE =\n        0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;\n\n    /// @dev `keccak256(bytes(\"ApprovalForAll(address,address,bool)\"))`.\n    uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE =\n        0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                          STORAGE                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The ownership data slot of `id` is given by:\n    /// ```\n    ///     mstore(0x00, id)\n    ///     mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n    ///     let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))\n    /// ```\n    /// Bits Layout:\n    /// - [0..159]   `addr`\n    /// - [160..255] `extraData`\n    ///\n    /// The approved address slot is given by: `add(1, ownershipSlot)`.\n    ///\n    /// See: https://notes.ethereum.org/%40vbuterin/verkle_tree_eip\n    ///\n    /// The balance slot of `owner` is given by:\n    /// ```\n    ///     mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n    ///     mstore(0x00, owner)\n    ///     let balanceSlot := keccak256(0x0c, 0x1c)\n    /// ```\n    /// Bits Layout:\n    /// - [0..31]   `balance`\n    /// - [32..255] `aux`\n    ///\n    /// The `operator` approval slot of `owner` is given by:\n    /// ```\n    ///     mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator))\n    ///     mstore(0x00, owner)\n    ///     let operatorApprovalSlot := keccak256(0x0c, 0x30)\n    /// ```\n    uint256 private constant _ERC721_MASTER_SLOT_SEED = 0x7d8825530a5a2e7a << 192;\n\n    /// @dev Pre-shifted and pre-masked constant.\n    uint256 private constant _ERC721_MASTER_SLOT_SEED_MASKED = 0x0a5a2e7a00000000;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                      ERC721 METADATA                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the token collection name.\n    function name() public view virtual returns (string memory);\n\n    /// @dev Returns the token collection symbol.\n    function symbol() public view virtual returns (string memory);\n\n    /// @dev Returns the Uniform Resource Identifier (URI) for token `id`.\n    function tokenURI(uint256 id) public view virtual returns (string memory);\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                           ERC721                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the owner of token `id`.\n    ///\n    /// Requirements:\n    /// - Token `id` must exist.\n    function ownerOf(uint256 id) public view virtual returns (address result) {\n        result = _ownerOf(id);\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(result) {\n                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.\n                revert(0x1c, 0x04)\n            }\n        }\n    }\n\n    /// @dev Returns the number of tokens owned by `owner`.\n    ///\n    /// Requirements:\n    /// - `owner` must not be the zero address.\n    function balanceOf(address owner) public view virtual returns (uint256 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Revert if the `owner` is the zero address.\n            if iszero(owner) {\n                mstore(0x00, 0x8f4eb604) // `BalanceQueryForZeroAddress()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            mstore(0x00, owner)\n            result := and(sload(keccak256(0x0c, 0x1c)), _MAX_ACCOUNT_BALANCE)\n        }\n    }\n\n    /// @dev Returns the account approved to manage token `id`.\n    ///\n    /// Requirements:\n    /// - Token `id` must exist.\n    function getApproved(uint256 id) public view virtual returns (address result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, id)\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))\n            if iszero(shl(96, sload(ownershipSlot))) {\n                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.\n                revert(0x1c, 0x04)\n            }\n            result := sload(add(1, ownershipSlot))\n        }\n    }\n\n    /// @dev Sets `account` as the approved account to manage token `id`.\n    ///\n    /// Requirements:\n    /// - Token `id` must exist.\n    /// - The caller must be the owner of the token,\n    ///   or an approved operator for the token owner.\n    ///\n    /// Emits an {Approval} event.\n    function approve(address account, uint256 id) public payable virtual {\n        _approve(msg.sender, account, id);\n    }\n\n    /// @dev Returns whether `operator` is approved to manage the tokens of `owner`.\n    function isApprovedForAll(address owner, address operator)\n        public\n        view\n        virtual\n        returns (bool result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x1c, operator)\n            mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED)\n            mstore(0x00, owner)\n            result := sload(keccak256(0x0c, 0x30))\n        }\n    }\n\n    /// @dev Sets whether `operator` is approved to manage the tokens of the caller.\n    ///\n    /// Emits an {ApprovalForAll} event.\n    function setApprovalForAll(address operator, bool isApproved) public virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Convert to 0 or 1.\n            isApproved := iszero(iszero(isApproved))\n            // Update the `isApproved` for (`msg.sender`, `operator`).\n            mstore(0x1c, operator)\n            mstore(0x08, _ERC721_MASTER_SLOT_SEED_MASKED)\n            mstore(0x00, caller())\n            sstore(keccak256(0x0c, 0x30), isApproved)\n            // Emit the {ApprovalForAll} event.\n            mstore(0x00, isApproved)\n            // forgefmt: disable-next-item\n            log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), shr(96, shl(96, operator)))\n        }\n    }\n\n    /// @dev Transfers token `id` from `from` to `to`.\n    ///\n    /// Requirements:\n    ///\n    /// - Token `id` must exist.\n    /// - `from` must be the owner of the token.\n    /// - `to` cannot be the zero address.\n    /// - The caller must be the owner of the token, or be approved to manage the token.\n    ///\n    /// Emits a {Transfer} event.\n    function transferFrom(address from, address to, uint256 id) public payable virtual {\n        _beforeTokenTransfer(from, to, id);\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Clear the upper 96 bits.\n            let bitmaskAddress := shr(96, not(0))\n            from := and(bitmaskAddress, from)\n            to := and(bitmaskAddress, to)\n            // Load the ownership data.\n            mstore(0x00, id)\n            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, caller()))\n            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))\n            let ownershipPacked := sload(ownershipSlot)\n            let owner := and(bitmaskAddress, ownershipPacked)\n            // Revert if the token does not exist, or if `from` is not the owner.\n            if iszero(mul(owner, eq(owner, from))) {\n                // `TokenDoesNotExist()`, `TransferFromIncorrectOwner()`.\n                mstore(shl(2, iszero(owner)), 0xceea21b6a1148100)\n                revert(0x1c, 0x04)\n            }\n            // Load, check, and update the token approval.\n            {\n                mstore(0x00, from)\n                let approvedAddress := sload(add(1, ownershipSlot))\n                // Revert if the caller is not the owner, nor approved.\n                if iszero(or(eq(caller(), from), eq(caller(), approvedAddress))) {\n                    if iszero(sload(keccak256(0x0c, 0x30))) {\n                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.\n                        revert(0x1c, 0x04)\n                    }\n                }\n                // Delete the approved address if any.\n                if approvedAddress { sstore(add(1, ownershipSlot), 0) }\n            }\n            // Update with the new owner.\n            sstore(ownershipSlot, xor(ownershipPacked, xor(from, to)))\n            // Decrement the balance of `from`.\n            {\n                let fromBalanceSlot := keccak256(0x0c, 0x1c)\n                sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1))\n            }\n            // Increment the balance of `to`.\n            {\n                mstore(0x00, to)\n                let toBalanceSlot := keccak256(0x0c, 0x1c)\n                let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)\n                // Revert if `to` is the zero address, or if the account balance overflows.\n                if iszero(mul(to, and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {\n                    // `TransferToZeroAddress()`, `AccountBalanceOverflow()`.\n                    mstore(shl(2, iszero(to)), 0xea553b3401336cea)\n                    revert(0x1c, 0x04)\n                }\n                sstore(toBalanceSlot, toBalanceSlotPacked)\n            }\n            // Emit the {Transfer} event.\n            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)\n        }\n        _afterTokenTransfer(from, to, id);\n    }\n\n    /// @dev Equivalent to `safeTransferFrom(from, to, id, \"\")`.\n    function safeTransferFrom(address from, address to, uint256 id) public payable virtual {\n        transferFrom(from, to, id);\n        if (_hasCode(to)) _checkOnERC721Received(from, to, id, \"\");\n    }\n\n    /// @dev Transfers token `id` from `from` to `to`.\n    ///\n    /// Requirements:\n    ///\n    /// - Token `id` must exist.\n    /// - `from` must be the owner of the token.\n    /// - `to` cannot be the zero address.\n    /// - The caller must be the owner of the token, or be approved to manage the token.\n    /// - If `to` refers to a smart contract, it must implement\n    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n    ///\n    /// Emits a {Transfer} event.\n    function safeTransferFrom(address from, address to, uint256 id, bytes calldata data)\n        public\n        payable\n        virtual\n    {\n        transferFrom(from, to, id);\n        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);\n    }\n\n    /// @dev Returns true if this contract implements the interface defined by `interfaceId`.\n    /// See: https://eips.ethereum.org/EIPS/eip-165\n    /// This function call must use less than 30000 gas.\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let s := shr(224, interfaceId)\n            // ERC165: 0x01ffc9a7, ERC721: 0x80ac58cd, ERC721Metadata: 0x5b5e139f.\n            result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x80ac58cd)), eq(s, 0x5b5e139f))\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  INTERNAL QUERY FUNCTIONS                  */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns if token `id` exists.\n    function _exists(uint256 id) internal view virtual returns (bool result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, id)\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            result := iszero(iszero(shl(96, sload(add(id, add(id, keccak256(0x00, 0x20)))))))\n        }\n    }\n\n    /// @dev Returns the owner of token `id`.\n    /// Returns the zero address instead of reverting if the token does not exist.\n    function _ownerOf(uint256 id) internal view virtual returns (address result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, id)\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            result := shr(96, shl(96, sload(add(id, add(id, keccak256(0x00, 0x20))))))\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*            INTERNAL DATA HITCHHIKING FUNCTIONS             */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // For performance, no events are emitted for the hitchhiking setters.\n    // Please emit your own events if required.\n\n    /// @dev Returns the auxiliary data for `owner`.\n    /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data.\n    /// Auxiliary data can be set for any address, even if it does not have any tokens.\n    function _getAux(address owner) internal view virtual returns (uint224 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            mstore(0x00, owner)\n            result := shr(32, sload(keccak256(0x0c, 0x1c)))\n        }\n    }\n\n    /// @dev Set the auxiliary data for `owner` to `value`.\n    /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data.\n    /// Auxiliary data can be set for any address, even if it does not have any tokens.\n    function _setAux(address owner, uint224 value) internal virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            mstore(0x00, owner)\n            let balanceSlot := keccak256(0x0c, 0x1c)\n            let packed := sload(balanceSlot)\n            sstore(balanceSlot, xor(packed, shl(32, xor(value, shr(32, packed)))))\n        }\n    }\n\n    /// @dev Returns the extra data for token `id`.\n    /// Minting, transferring, burning a token will not change the extra data.\n    /// The extra data can be set on a non-existent token.\n    function _getExtraData(uint256 id) internal view virtual returns (uint96 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, id)\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            result := shr(160, sload(add(id, add(id, keccak256(0x00, 0x20)))))\n        }\n    }\n\n    /// @dev Sets the extra data for token `id` to `value`.\n    /// Minting, transferring, burning a token will not change the extra data.\n    /// The extra data can be set on a non-existent token.\n    function _setExtraData(uint256 id, uint96 value) internal virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, id)\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))\n            let packed := sload(ownershipSlot)\n            sstore(ownershipSlot, xor(packed, shl(160, xor(value, shr(160, packed)))))\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  INTERNAL MINT FUNCTIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Mints token `id` to `to`.\n    ///\n    /// Requirements:\n    ///\n    /// - Token `id` must not exist.\n    /// - `to` cannot be the zero address.\n    ///\n    /// Emits a {Transfer} event.\n    function _mint(address to, uint256 id) internal virtual {\n        _beforeTokenTransfer(address(0), to, id);\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Clear the upper 96 bits.\n            to := shr(96, shl(96, to))\n            // Load the ownership data.\n            mstore(0x00, id)\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))\n            let ownershipPacked := sload(ownershipSlot)\n            // Revert if the token already exists.\n            if shl(96, ownershipPacked) {\n                mstore(0x00, 0xc991cbb1) // `TokenAlreadyExists()`.\n                revert(0x1c, 0x04)\n            }\n            // Update with the owner.\n            sstore(ownershipSlot, or(ownershipPacked, to))\n            // Increment the balance of the owner.\n            {\n                mstore(0x00, to)\n                let balanceSlot := keccak256(0x0c, 0x1c)\n                let balanceSlotPacked := add(sload(balanceSlot), 1)\n                // Revert if `to` is the zero address, or if the account balance overflows.\n                if iszero(mul(to, and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {\n                    // `TransferToZeroAddress()`, `AccountBalanceOverflow()`.\n                    mstore(shl(2, iszero(to)), 0xea553b3401336cea)\n                    revert(0x1c, 0x04)\n                }\n                sstore(balanceSlot, balanceSlotPacked)\n            }\n            // Emit the {Transfer} event.\n            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, 0, to, id)\n        }\n        _afterTokenTransfer(address(0), to, id);\n    }\n\n    /// @dev Mints token `id` to `to`, and updates the extra data for token `id` to `value`.\n    /// Does NOT check if token `id` already exists (assumes `id` is auto-incrementing).\n    ///\n    /// Requirements:\n    ///\n    /// - `to` cannot be the zero address.\n    ///\n    /// Emits a {Transfer} event.\n    function _mintAndSetExtraDataUnchecked(address to, uint256 id, uint96 value) internal virtual {\n        _beforeTokenTransfer(address(0), to, id);\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Clear the upper 96 bits.\n            to := shr(96, shl(96, to))\n            // Update with the owner and extra data.\n            mstore(0x00, id)\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            sstore(add(id, add(id, keccak256(0x00, 0x20))), or(shl(160, value), to))\n            // Increment the balance of the owner.\n            {\n                mstore(0x00, to)\n                let balanceSlot := keccak256(0x0c, 0x1c)\n                let balanceSlotPacked := add(sload(balanceSlot), 1)\n                // Revert if `to` is the zero address, or if the account balance overflows.\n                if iszero(mul(to, and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {\n                    // `TransferToZeroAddress()`, `AccountBalanceOverflow()`.\n                    mstore(shl(2, iszero(to)), 0xea553b3401336cea)\n                    revert(0x1c, 0x04)\n                }\n                sstore(balanceSlot, balanceSlotPacked)\n            }\n            // Emit the {Transfer} event.\n            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, 0, to, id)\n        }\n        _afterTokenTransfer(address(0), to, id);\n    }\n\n    /// @dev Equivalent to `_safeMint(to, id, \"\")`.\n    function _safeMint(address to, uint256 id) internal virtual {\n        _safeMint(to, id, \"\");\n    }\n\n    /// @dev Mints token `id` to `to`.\n    ///\n    /// Requirements:\n    ///\n    /// - Token `id` must not exist.\n    /// - `to` cannot be the zero address.\n    /// - If `to` refers to a smart contract, it must implement\n    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n    ///\n    /// Emits a {Transfer} event.\n    function _safeMint(address to, uint256 id, bytes memory data) internal virtual {\n        _mint(to, id);\n        if (_hasCode(to)) _checkOnERC721Received(address(0), to, id, data);\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  INTERNAL BURN FUNCTIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Equivalent to `_burn(address(0), id)`.\n    function _burn(uint256 id) internal virtual {\n        _burn(address(0), id);\n    }\n\n    /// @dev Destroys token `id`, using `by`.\n    ///\n    /// Requirements:\n    ///\n    /// - Token `id` must exist.\n    /// - If `by` is not the zero address,\n    ///   it must be the owner of the token, or be approved to manage the token.\n    ///\n    /// Emits a {Transfer} event.\n    function _burn(address by, uint256 id) internal virtual {\n        address owner = ownerOf(id);\n        _beforeTokenTransfer(owner, address(0), id);\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Clear the upper 96 bits.\n            by := shr(96, shl(96, by))\n            // Load the ownership data.\n            mstore(0x00, id)\n            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))\n            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))\n            let ownershipPacked := sload(ownershipSlot)\n            // Reload the owner in case it is changed in `_beforeTokenTransfer`.\n            owner := shr(96, shl(96, ownershipPacked))\n            // Revert if the token does not exist.\n            if iszero(owner) {\n                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.\n                revert(0x1c, 0x04)\n            }\n            // Load and check the token approval.\n            {\n                mstore(0x00, owner)\n                let approvedAddress := sload(add(1, ownershipSlot))\n                // If `by` is not the zero address, do the authorization check.\n                // Revert if the `by` is not the owner, nor approved.\n                if iszero(or(iszero(by), or(eq(by, owner), eq(by, approvedAddress)))) {\n                    if iszero(sload(keccak256(0x0c, 0x30))) {\n                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.\n                        revert(0x1c, 0x04)\n                    }\n                }\n                // Delete the approved address if any.\n                if approvedAddress { sstore(add(1, ownershipSlot), 0) }\n            }\n            // Clear the owner.\n            sstore(ownershipSlot, xor(ownershipPacked, owner))\n            // Decrement the balance of `owner`.\n            {\n                let balanceSlot := keccak256(0x0c, 0x1c)\n                sstore(balanceSlot, sub(sload(balanceSlot), 1))\n            }\n            // Emit the {Transfer} event.\n            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, owner, 0, id)\n        }\n        _afterTokenTransfer(owner, address(0), id);\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                INTERNAL APPROVAL FUNCTIONS                 */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns whether `account` is the owner of token `id`, or is approved to manage it.\n    ///\n    /// Requirements:\n    /// - Token `id` must exist.\n    function _isApprovedOrOwner(address account, uint256 id)\n        internal\n        view\n        virtual\n        returns (bool result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := 1\n            // Clear the upper 96 bits.\n            account := shr(96, shl(96, account))\n            // Load the ownership data.\n            mstore(0x00, id)\n            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, account))\n            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))\n            let owner := shr(96, shl(96, sload(ownershipSlot)))\n            // Revert if the token does not exist.\n            if iszero(owner) {\n                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.\n                revert(0x1c, 0x04)\n            }\n            // Check if `account` is the `owner`.\n            if iszero(eq(account, owner)) {\n                mstore(0x00, owner)\n                // Check if `account` is approved to manage the token.\n                if iszero(sload(keccak256(0x0c, 0x30))) {\n                    result := eq(account, sload(add(1, ownershipSlot)))\n                }\n            }\n        }\n    }\n\n    /// @dev Returns the account approved to manage token `id`.\n    /// Returns the zero address instead of reverting if the token does not exist.\n    function _getApproved(uint256 id) internal view virtual returns (address result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, id)\n            mstore(0x1c, _ERC721_MASTER_SLOT_SEED)\n            result := sload(add(1, add(id, add(id, keccak256(0x00, 0x20)))))\n        }\n    }\n\n    /// @dev Equivalent to `_approve(address(0), account, id)`.\n    function _approve(address account, uint256 id) internal virtual {\n        _approve(address(0), account, id);\n    }\n\n    /// @dev Sets `account` as the approved account to manage token `id`, using `by`.\n    ///\n    /// Requirements:\n    /// - Token `id` must exist.\n    /// - If `by` is not the zero address, `by` must be the owner\n    ///   or an approved operator for the token owner.\n    ///\n    /// Emits a {Approval} event.\n    function _approve(address by, address account, uint256 id) internal virtual {\n        assembly {\n            // Clear the upper 96 bits.\n            let bitmaskAddress := shr(96, not(0))\n            account := and(bitmaskAddress, account)\n            by := and(bitmaskAddress, by)\n            // Load the owner of the token.\n            mstore(0x00, id)\n            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))\n            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))\n            let owner := and(bitmaskAddress, sload(ownershipSlot))\n            // Revert if the token does not exist.\n            if iszero(owner) {\n                mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`.\n                revert(0x1c, 0x04)\n            }\n            // If `by` is not the zero address, do the authorization check.\n            // Revert if `by` is not the owner, nor approved.\n            if iszero(or(iszero(by), eq(by, owner))) {\n                mstore(0x00, owner)\n                if iszero(sload(keccak256(0x0c, 0x30))) {\n                    mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n            // Sets `account` as the approved account to manage `id`.\n            sstore(add(1, ownershipSlot), account)\n            // Emit the {Approval} event.\n            log4(codesize(), 0x00, _APPROVAL_EVENT_SIGNATURE, owner, account, id)\n        }\n    }\n\n    /// @dev Approve or remove the `operator` as an operator for `by`,\n    /// without authorization checks.\n    ///\n    /// Emits an {ApprovalForAll} event.\n    function _setApprovalForAll(address by, address operator, bool isApproved) internal virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Clear the upper 96 bits.\n            by := shr(96, shl(96, by))\n            operator := shr(96, shl(96, operator))\n            // Convert to 0 or 1.\n            isApproved := iszero(iszero(isApproved))\n            // Update the `isApproved` for (`by`, `operator`).\n            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator))\n            mstore(0x00, by)\n            sstore(keccak256(0x0c, 0x30), isApproved)\n            // Emit the {ApprovalForAll} event.\n            mstore(0x00, isApproved)\n            log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, by, operator)\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                INTERNAL TRANSFER FUNCTIONS                 */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Equivalent to `_transfer(address(0), from, to, id)`.\n    function _transfer(address from, address to, uint256 id) internal virtual {\n        _transfer(address(0), from, to, id);\n    }\n\n    /// @dev Transfers token `id` from `from` to `to`.\n    ///\n    /// Requirements:\n    ///\n    /// - Token `id` must exist.\n    /// - `from` must be the owner of the token.\n    /// - `to` cannot be the zero address.\n    /// - If `by` is not the zero address,\n    ///   it must be the owner of the token, or be approved to manage the token.\n    ///\n    /// Emits a {Transfer} event.\n    function _transfer(address by, address from, address to, uint256 id) internal virtual {\n        _beforeTokenTransfer(from, to, id);\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Clear the upper 96 bits.\n            let bitmaskAddress := shr(96, not(0))\n            from := and(bitmaskAddress, from)\n            to := and(bitmaskAddress, to)\n            by := and(bitmaskAddress, by)\n            // Load the ownership data.\n            mstore(0x00, id)\n            mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by))\n            let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20)))\n            let ownershipPacked := sload(ownershipSlot)\n            let owner := and(bitmaskAddress, ownershipPacked)\n            // Revert if the token does not exist, or if `from` is not the owner.\n            if iszero(mul(owner, eq(owner, from))) {\n                // `TokenDoesNotExist()`, `TransferFromIncorrectOwner()`.\n                mstore(shl(2, iszero(owner)), 0xceea21b6a1148100)\n                revert(0x1c, 0x04)\n            }\n            // Load, check, and update the token approval.\n            {\n                mstore(0x00, from)\n                let approvedAddress := sload(add(1, ownershipSlot))\n                // If `by` is not the zero address, do the authorization check.\n                // Revert if the `by` is not the owner, nor approved.\n                if iszero(or(iszero(by), or(eq(by, from), eq(by, approvedAddress)))) {\n                    if iszero(sload(keccak256(0x0c, 0x30))) {\n                        mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`.\n                        revert(0x1c, 0x04)\n                    }\n                }\n                // Delete the approved address if any.\n                if approvedAddress { sstore(add(1, ownershipSlot), 0) }\n            }\n            // Update with the new owner.\n            sstore(ownershipSlot, xor(ownershipPacked, xor(from, to)))\n            // Decrement the balance of `from`.\n            {\n                let fromBalanceSlot := keccak256(0x0c, 0x1c)\n                sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1))\n            }\n            // Increment the balance of `to`.\n            {\n                mstore(0x00, to)\n                let toBalanceSlot := keccak256(0x0c, 0x1c)\n                let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)\n                // Revert if `to` is the zero address, or if the account balance overflows.\n                if iszero(mul(to, and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {\n                    // `TransferToZeroAddress()`, `AccountBalanceOverflow()`.\n                    mstore(shl(2, iszero(to)), 0xea553b3401336cea)\n                    revert(0x1c, 0x04)\n                }\n                sstore(toBalanceSlot, toBalanceSlotPacked)\n            }\n            // Emit the {Transfer} event.\n            log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)\n        }\n        _afterTokenTransfer(from, to, id);\n    }\n\n    /// @dev Equivalent to `_safeTransfer(from, to, id, \"\")`.\n    function _safeTransfer(address from, address to, uint256 id) internal virtual {\n        _safeTransfer(from, to, id, \"\");\n    }\n\n    /// @dev Transfers token `id` from `from` to `to`.\n    ///\n    /// Requirements:\n    ///\n    /// - Token `id` must exist.\n    /// - `from` must be the owner of the token.\n    /// - `to` cannot be the zero address.\n    /// - The caller must be the owner of the token, or be approved to manage the token.\n    /// - If `to` refers to a smart contract, it must implement\n    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n    ///\n    /// Emits a {Transfer} event.\n    function _safeTransfer(address from, address to, uint256 id, bytes memory data)\n        internal\n        virtual\n    {\n        _transfer(address(0), from, to, id);\n        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);\n    }\n\n    /// @dev Equivalent to `_safeTransfer(by, from, to, id, \"\")`.\n    function _safeTransfer(address by, address from, address to, uint256 id) internal virtual {\n        _safeTransfer(by, from, to, id, \"\");\n    }\n\n    /// @dev Transfers token `id` from `from` to `to`.\n    ///\n    /// Requirements:\n    ///\n    /// - Token `id` must exist.\n    /// - `from` must be the owner of the token.\n    /// - `to` cannot be the zero address.\n    /// - If `by` is not the zero address,\n    ///   it must be the owner of the token, or be approved to manage the token.\n    /// - If `to` refers to a smart contract, it must implement\n    ///   {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n    ///\n    /// Emits a {Transfer} event.\n    function _safeTransfer(address by, address from, address to, uint256 id, bytes memory data)\n        internal\n        virtual\n    {\n        _transfer(by, from, to, id);\n        if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                    HOOKS FOR OVERRIDING                    */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Hook that is called before any token transfers, including minting and burning.\n    function _beforeTokenTransfer(address from, address to, uint256 id) internal virtual {}\n\n    /// @dev Hook that is called after any token transfers, including minting and burning.\n    function _afterTokenTransfer(address from, address to, uint256 id) internal virtual {}\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                      PRIVATE HELPERS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns if `a` has bytecode of non-zero length.\n    function _hasCode(address a) private view returns (bool result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := extcodesize(a) // Can handle dirty upper bits.\n        }\n    }\n\n    /// @dev Perform a call to invoke {IERC721Receiver-onERC721Received} on `to`.\n    /// Reverts if the target does not support the function correctly.\n    function _checkOnERC721Received(address from, address to, uint256 id, bytes memory data)\n        private\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Prepare the calldata.\n            let m := mload(0x40)\n            let onERC721ReceivedSelector := 0x150b7a02\n            mstore(m, onERC721ReceivedSelector)\n            mstore(add(m, 0x20), caller()) // The `operator`, which is always `msg.sender`.\n            mstore(add(m, 0x40), shr(96, shl(96, from)))\n            mstore(add(m, 0x60), id)\n            mstore(add(m, 0x80), 0x80)\n            let n := mload(data)\n            mstore(add(m, 0xa0), n)\n            if n { pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xc0), n)) }\n            // Revert if the call reverts.\n            if iszero(call(gas(), to, 0, add(m, 0x1c), add(n, 0xa4), m, 0x20)) {\n                if returndatasize() {\n                    // Bubble up the revert if the call reverts.\n                    returndatacopy(m, 0x00, returndatasize())\n                    revert(m, returndatasize())\n                }\n            }\n            // Load the returndata and compare it.\n            if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) {\n                mstore(0x00, 0xd1a57ed6) // `TransferToNonERC721ReceiverImplementer()`.\n                revert(0x1c, 0x04)\n            }\n        }\n    }\n}\n"},"solady/src/utils/LibRLP.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Library for RLP encoding and CREATE address computation.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibRLP.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibRLP.sol)\nlibrary LibRLP {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                          STRUCTS                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev A pointer to a RLP item list in memory.\n    struct List {\n        // Do NOT modify the `_data` directly.\n        uint256 _data;\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                 CREATE ADDRESS PREDICTION                  */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the address where a contract will be stored if deployed via\n    /// `deployer` with `nonce` using the `CREATE` opcode.\n    /// For the specification of the Recursive Length Prefix (RLP)\n    /// encoding scheme, please refer to p. 19 of the Ethereum Yellow Paper\n    /// (https://ethereum.github.io/yellowpaper/paper.pdf)\n    /// and the Ethereum Wiki (https://eth.wiki/fundamentals/rlp).\n    ///\n    /// Based on the EIP-161 (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-161.md)\n    /// specification, all contract accounts on the Ethereum mainnet are initiated with\n    /// `nonce = 1`. Thus, the first contract address created by another contract\n    /// is calculated with a non-zero nonce.\n    ///\n    /// The theoretical allowed limit, based on EIP-2681\n    /// (https://eips.ethereum.org/EIPS/eip-2681), for an account nonce is 2**64-2.\n    ///\n    /// Caution! This function will NOT check that the nonce is within the theoretical range.\n    /// This is for performance, as exceeding the range is extremely impractical.\n    /// It is the user's responsibility to ensure that the nonce is valid\n    /// (e.g. no dirty bits after packing / unpacking).\n    ///\n    /// This is equivalent to:\n    /// `address(uint160(uint256(keccak256(LibRLP.l(deployer).p(nonce).encode()))))`.\n    ///\n    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n    function computeAddress(address deployer, uint256 nonce)\n        internal\n        pure\n        returns (address deployed)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for {} 1 {} {\n                // The integer zero is treated as an empty byte string,\n                // and as a result it only has a length prefix, 0x80,\n                // computed via `0x80 + 0`.\n\n                // A one-byte integer in the [0x00, 0x7f] range uses its\n                // own value as a length prefix,\n                // there is no additional `0x80 + length` prefix that precedes it.\n                if iszero(gt(nonce, 0x7f)) {\n                    mstore(0x00, deployer)\n                    // Using `mstore8` instead of `or` naturally cleans\n                    // any dirty upper bits of `deployer`.\n                    mstore8(0x0b, 0x94)\n                    mstore8(0x0a, 0xd6)\n                    // `shl` 7 is equivalent to multiplying by 0x80.\n                    mstore8(0x20, or(shl(7, iszero(nonce)), nonce))\n                    deployed := keccak256(0x0a, 0x17)\n                    break\n                }\n                let i := 8\n                // Just use a loop to generalize all the way with minimal bytecode size.\n                for {} shr(i, nonce) { i := add(i, 8) } {}\n                // `shr` 3 is equivalent to dividing by 8.\n                i := shr(3, i)\n                // Store in descending slot sequence to overlap the values correctly.\n                mstore(i, nonce)\n                mstore(0x00, shl(8, deployer))\n                mstore8(0x1f, add(0x80, i))\n                mstore8(0x0a, 0x94)\n                mstore8(0x09, add(0xd6, i))\n                deployed := keccak256(0x09, add(0x17, i))\n                break\n            }\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  RLP ENCODING OPERATIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // Note:\n    // - addresses are treated like byte strings of length 20, agnostic of leading zero bytes.\n    // - uint256s are converted to byte strings, stripped of leading zero bytes, and encoded.\n    // - bools are converted to uint256s (`b ? 1 : 0`), then encoded with the uint256.\n    // - For bytes1 to bytes32, you must manually convert them to bytes memory\n    //   with `abi.encodePacked(x)` before encoding.\n\n    /// @dev Returns a new empty list.\n    function l() internal pure returns (List memory result) {}\n\n    /// @dev Returns a new list with `x` as the only element. Equivalent to `LibRLP.l().p(x)`.\n    function l(uint256 x) internal pure returns (List memory result) {\n        p(result, x);\n    }\n\n    /// @dev Returns a new list with `x` as the only element. Equivalent to `LibRLP.l().p(x)`.\n    function l(address x) internal pure returns (List memory result) {\n        p(result, x);\n    }\n\n    /// @dev Returns a new list with `x` as the only element. Equivalent to `LibRLP.l().p(x)`.\n    function l(bool x) internal pure returns (List memory result) {\n        p(result, x);\n    }\n\n    /// @dev Returns a new list with `x` as the only element. Equivalent to `LibRLP.l().p(x)`.\n    function l(bytes memory x) internal pure returns (List memory result) {\n        p(result, x);\n    }\n\n    /// @dev Returns a new list with `x` as the only element. Equivalent to `LibRLP.l().p(x)`.\n    function l(List memory x) internal pure returns (List memory result) {\n        p(result, x);\n    }\n\n    /// @dev Appends `x` to `list`. Returns `list` for function chaining.\n    function p(List memory list, uint256 x) internal pure returns (List memory result) {\n        result._data = x << 48;\n        _updateTail(list, result);\n        /// @solidity memory-safe-assembly\n        assembly {\n            // If `x` is too big, we cannot pack it inline with the node.\n            // We'll have to allocate a new slot for `x` and store the pointer to it in the node.\n            if shr(208, x) {\n                let m := mload(0x40)\n                mstore(m, x)\n                mstore(0x40, add(m, 0x20))\n                mstore(result, shl(40, or(1, shl(8, m))))\n            }\n        }\n        result = list;\n    }\n\n    /// @dev Appends `x` to `list`. Returns `list` for function chaining.\n    function p(List memory list, address x) internal pure returns (List memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(result, shl(40, or(4, shl(8, x))))\n        }\n        _updateTail(list, result);\n        result = list;\n    }\n\n    /// @dev Appends `x` to `list`. Returns `list` for function chaining.\n    function p(List memory list, bool x) internal pure returns (List memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(result, shl(48, iszero(iszero(x))))\n        }\n        _updateTail(list, result);\n        result = list;\n    }\n\n    /// @dev Appends `x` to `list`. Returns `list` for function chaining.\n    function p(List memory list, bytes memory x) internal pure returns (List memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(result, shl(40, or(2, shl(8, x))))\n        }\n        _updateTail(list, result);\n        result = list;\n    }\n\n    /// @dev Appends `x` to `list`. Returns `list` for function chaining.\n    function p(List memory list, List memory x) internal pure returns (List memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(result, shl(40, or(3, shl(8, x))))\n        }\n        _updateTail(list, result);\n        result = list;\n    }\n\n    /// @dev Returns the RLP encoding of `list`.\n    function encode(List memory list) internal pure returns (bytes memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            function encodeUint(x_, o_) -> _o {\n                _o := add(o_, 1)\n                if iszero(gt(x_, 0x7f)) {\n                    mstore8(o_, or(shl(7, iszero(x_)), x_)) // Copy `x_`.\n                    leave\n                }\n                let r_ := shl(7, lt(0xffffffffffffffffffffffffffffffff, x_))\n                r_ := or(r_, shl(6, lt(0xffffffffffffffff, shr(r_, x_))))\n                r_ := or(r_, shl(5, lt(0xffffffff, shr(r_, x_))))\n                r_ := or(r_, shl(4, lt(0xffff, shr(r_, x_))))\n                r_ := or(shr(3, r_), lt(0xff, shr(r_, x_)))\n                mstore8(o_, add(r_, 0x81)) // Store the prefix.\n                mstore(0x00, x_)\n                mstore(_o, mload(xor(31, r_))) // Copy `x_`.\n                _o := add(add(1, r_), _o)\n            }\n            function encodeAddress(x_, o_) -> _o {\n                _o := add(o_, 0x15)\n                mstore(o_, shl(88, x_))\n                mstore8(o_, 0x94)\n            }\n            function encodeBytes(x_, o_, c_) -> _o {\n                _o := add(o_, 1)\n                let n_ := mload(x_)\n                if iszero(gt(n_, 55)) {\n                    let f_ := mload(add(0x20, x_))\n                    if iszero(and(eq(1, n_), lt(byte(0, f_), 0x80))) {\n                        mstore8(o_, add(n_, c_)) // Store the prefix.\n                        mstore(add(0x21, o_), mload(add(0x40, x_)))\n                        mstore(_o, f_)\n                        _o := add(n_, _o)\n                        leave\n                    }\n                    mstore(o_, f_) // Copy `x_`.\n                    leave\n                }\n                returndatacopy(returndatasize(), returndatasize(), shr(32, n_))\n                let r_ := add(1, add(lt(0xff, n_), add(lt(0xffff, n_), lt(0xffffff, n_))))\n                mstore(o_, shl(248, add(r_, add(c_, 55)))) // Store the prefix.\n                // Copy `x`.\n                let i_ := add(r_, _o)\n                _o := add(i_, n_)\n                for { let d_ := sub(add(0x20, x_), i_) } 1 {} {\n                    mstore(i_, mload(add(d_, i_)))\n                    i_ := add(i_, 0x20)\n                    if iszero(lt(i_, _o)) { break }\n                }\n                mstore(o_, or(mload(o_), shl(sub(248, shl(3, r_)), n_))) // Store the prefix.\n            }\n            function encodeList(l_, o_) -> _o {\n                if iszero(mload(l_)) {\n                    mstore8(o_, 0xc0)\n                    _o := add(o_, 1)\n                    leave\n                }\n                let j_ := add(o_, 0x20)\n                for { let h_ := l_ } 1 {} {\n                    h_ := and(mload(h_), 0xffffffffff)\n                    if iszero(h_) { break }\n                    let t_ := byte(26, mload(h_))\n                    if iszero(gt(t_, 1)) {\n                        if iszero(t_) {\n                            j_ := encodeUint(shr(48, mload(h_)), j_)\n                            continue\n                        }\n                        j_ := encodeUint(mload(shr(48, mload(h_))), j_)\n                        continue\n                    }\n                    if eq(t_, 2) {\n                        j_ := encodeBytes(shr(48, mload(h_)), j_, 0x80)\n                        continue\n                    }\n                    if eq(t_, 3) {\n                        j_ := encodeList(shr(48, mload(h_)), j_)\n                        continue\n                    }\n                    j_ := encodeAddress(shr(48, mload(h_)), j_)\n                }\n                mstore(o_, sub(j_, add(o_, 0x20)))\n                _o := encodeBytes(o_, o_, 0xc0)\n            }\n            result := mload(0x40)\n            let begin := add(result, 0x20)\n            let end := encodeList(list, begin)\n            mstore(result, sub(end, begin)) // Store the length of `result`.\n            mstore(end, 0) // Zeroize the slot after `result`.\n            mstore(0x40, add(end, 0x20)) // Allocate memory for `result`.\n        }\n    }\n\n    /// @dev Returns the RLP encoding of `x`.\n    function encode(uint256 x) internal pure returns (bytes memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for {} 1 {} {\n                result := mload(0x40)\n                if iszero(gt(x, 0x7f)) {\n                    mstore(result, 1) // Store the length of `result`.\n                    mstore(add(result, 0x20), shl(248, or(shl(7, iszero(x)), x))) // Copy `x`.\n                    mstore(0x40, add(result, 0x40)) // Allocate memory for `result`.\n                    break\n                }\n                let r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n                r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n                r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n                r := or(r, shl(4, lt(0xffff, shr(r, x))))\n                r := add(2, or(shr(3, r), lt(0xff, shr(r, x))))\n                mstore(add(r, result), x) // Copy `x`.\n                mstore(add(result, 1), add(r, 0x7f)) // Store the prefix.\n                mstore(result, r) // Store the length of `result`.\n                mstore(add(r, add(result, 0x20)), 0) // Zeroize the slot after `result`.\n                mstore(0x40, add(result, 0x60)) // Allocate memory for `result`.\n                break\n            }\n        }\n    }\n\n    /// @dev Returns the RLP encoding of `x`.\n    function encode(address x) internal pure returns (bytes memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := mload(0x40)\n            mstore(result, 0x15)\n            let o := add(0x20, result)\n            mstore(o, shl(88, x))\n            mstore8(o, 0x94)\n            mstore(0x40, add(0x20, o))\n        }\n    }\n\n    /// @dev Returns the RLP encoding of `x`.\n    function encode(bool x) internal pure returns (bytes memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := mload(0x40)\n            mstore(result, 1)\n            mstore(add(0x20, result), shl(add(0xf8, mul(7, iszero(x))), 0x01))\n            mstore(0x40, add(0x40, result))\n        }\n    }\n\n    /// @dev Returns the RLP encoding of `x`.\n    function encode(bytes memory x) internal pure returns (bytes memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := x\n\n            for {} iszero(and(eq(1, mload(x)), lt(byte(0, mload(add(x, 0x20))), 0x80))) {} {\n                result := mload(0x40)\n                let n := mload(x) // Length of `x`.\n                if iszero(gt(n, 55)) {\n                    mstore(0x40, add(result, 0x60))\n                    mstore(add(0x41, result), mload(add(0x40, x)))\n                    mstore(add(0x21, result), mload(add(0x20, x)))\n                    mstore(add(1, result), add(n, 0x80)) // Store the prefix.\n                    mstore(result, add(1, n)) // Store the length of `result`.\n                    mstore(add(add(result, 0x21), n), 0) // Zeroize the slot after `result`.\n                    break\n                }\n                returndatacopy(returndatasize(), returndatasize(), shr(32, n)) // out of\n                let r := add(2, add(lt(0xff, n), add(lt(0xffff, n), lt(0xffffff, n))))\n                // Copy `x`.\n                let i := add(r, add(0x20, result))\n                let end := add(i, n)\n                for { let d := sub(add(0x20, x), i) } 1 {} {\n                    mstore(i, mload(add(d, i)))\n                    i := add(i, 0x20)\n                    if iszero(lt(i, end)) { break }\n                }\n                mstore(add(r, result), n) // Store the prefix.\n                mstore(add(1, result), add(r, 0xb6)) // Store the prefix.\n                mstore(result, add(r, n)) // Store the length of `result`.\n                mstore(end, 0) // Zeroize the slot after `result`.\n                mstore(0x40, add(end, 0x20)) // Allocate memory.\n                break\n            }\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                      PRIVATE HELPERS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Updates the tail in `list`.\n    function _updateTail(List memory list, List memory result) private pure {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let v := or(shr(mload(list), result), mload(list))\n            let tail := shr(40, v)\n            mstore(list, xor(shl(40, xor(tail, result)), v)) // Update the tail.\n            mstore(tail, or(mload(tail), result)) // Make the previous tail point to `result`.\n        }\n    }\n}\n"},"solady/src/utils/LibString.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Library for converting numbers into strings and other string operations.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)\n///\n/// @dev Note:\n/// For performance and bytecode compactness, most of the string operations are restricted to\n/// byte strings (7-bit ASCII), except where otherwise specified.\n/// Usage of byte string operations on charsets with runes spanning two or more bytes\n/// can lead to undefined behavior.\nlibrary LibString {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                        CUSTOM ERRORS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The length of the output is too small to contain all the hex digits.\n    error HexLengthInsufficient();\n\n    /// @dev The length of the string is more than 32 bytes.\n    error TooBigForSmallString();\n\n    /// @dev The input string must be a 7-bit ASCII.\n    error StringNot7BitASCII();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         CONSTANTS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The constant returned when the `search` is not found in the string.\n    uint256 internal constant NOT_FOUND = type(uint256).max;\n\n    /// @dev Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.\n    uint128 internal constant ALPHANUMERIC_7_BIT_ASCII = 0x7fffffe07fffffe03ff000000000000;\n\n    /// @dev Lookup for 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.\n    uint128 internal constant LETTERS_7_BIT_ASCII = 0x7fffffe07fffffe0000000000000000;\n\n    /// @dev Lookup for 'abcdefghijklmnopqrstuvwxyz'.\n    uint128 internal constant LOWERCASE_7_BIT_ASCII = 0x7fffffe000000000000000000000000;\n\n    /// @dev Lookup for 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.\n    uint128 internal constant UPPERCASE_7_BIT_ASCII = 0x7fffffe0000000000000000;\n\n    /// @dev Lookup for '0123456789'.\n    uint128 internal constant DIGITS_7_BIT_ASCII = 0x3ff000000000000;\n\n    /// @dev Lookup for '0123456789abcdefABCDEF'.\n    uint128 internal constant HEXDIGITS_7_BIT_ASCII = 0x7e0000007e03ff000000000000;\n\n    /// @dev Lookup for '01234567'.\n    uint128 internal constant OCTDIGITS_7_BIT_ASCII = 0xff000000000000;\n\n    /// @dev Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~ \\t\\n\\r\\x0b\\x0c'.\n    uint128 internal constant PRINTABLE_7_BIT_ASCII = 0x7fffffffffffffffffffffff00003e00;\n\n    /// @dev Lookup for '!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~'.\n    uint128 internal constant PUNCTUATION_7_BIT_ASCII = 0x78000001f8000001fc00fffe00000000;\n\n    /// @dev Lookup for ' \\t\\n\\r\\x0b\\x0c'.\n    uint128 internal constant WHITESPACE_7_BIT_ASCII = 0x100003e00;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     DECIMAL OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the base 10 decimal representation of `value`.\n    function toString(uint256 value) internal pure returns (string memory str) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but\n            // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.\n            // We will need 1 word for the trailing zeros padding, 1 word for the length,\n            // and 3 words for a maximum of 78 digits.\n            str := add(mload(0x40), 0x80)\n            mstore(0x40, add(str, 0x20)) // Allocate the memory.\n            mstore(str, 0) // Zeroize the slot after the string.\n\n            let end := str // Cache the end of the memory to calculate the length later.\n            let w := not(0) // Tsk.\n            // We write the string from rightmost digit to leftmost digit.\n            // The following is essentially a do-while loop that also handles the zero case.\n            for { let temp := value } 1 {} {\n                str := add(str, w) // `sub(str, 1)`.\n                // Store the character to the pointer.\n                // The ASCII index of the '0' character is 48.\n                mstore8(str, add(48, mod(temp, 10)))\n                temp := div(temp, 10) // Keep dividing `temp` until zero.\n                if iszero(temp) { break }\n            }\n            let length := sub(end, str)\n            str := sub(str, 0x20) // Move the pointer 32 bytes back to make room for the length.\n            mstore(str, length) // Store the length.\n        }\n    }\n\n    /// @dev Returns the base 10 decimal representation of `value`.\n    function toString(int256 value) internal pure returns (string memory str) {\n        if (value >= 0) return toString(uint256(value));\n        unchecked {\n            str = toString(~uint256(value) + 1);\n        }\n        /// @solidity memory-safe-assembly\n        assembly {\n            // We still have some spare memory space on the left,\n            // as we have allocated 3 words (96 bytes) for up to 78 digits.\n            let length := mload(str) // Load the string length.\n            mstore(str, 0x2d) // Store the '-' character.\n            str := sub(str, 1) // Move back the string pointer by a byte.\n            mstore(str, add(length, 1)) // Update the string length.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   HEXADECIMAL OPERATIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the hexadecimal representation of `value`,\n    /// left-padded to an input length of `length` bytes.\n    /// The output is prefixed with \"0x\" encoded using 2 hexadecimal digits per byte,\n    /// giving a total length of `length * 2 + 2` bytes.\n    /// Reverts if `length` is too small for the output to contain all the digits.\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(value, length);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let strLength := add(mload(str), 2) // Compute the length.\n            mstore(str, 0x3078) // Store the \"0x\" prefix.\n            str := sub(str, 2) // Move the pointer.\n            mstore(str, strLength) // Store the length.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`,\n    /// left-padded to an input length of `length` bytes.\n    /// The output is prefixed with \"0x\" encoded using 2 hexadecimal digits per byte,\n    /// giving a total length of `length * 2` bytes.\n    /// Reverts if `length` is too small for the output to contain all the digits.\n    function toHexStringNoPrefix(uint256 value, uint256 length)\n        internal\n        pure\n        returns (string memory str)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes\n            // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length.\n            // We add 0x20 to the total and round down to a multiple of 0x20.\n            // (0x20 + 0x20 + 0x02 + 0x20) = 0x62.\n            str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f)))\n            mstore(0x40, add(str, 0x20)) // Allocate the memory.\n            mstore(str, 0) // Zeroize the slot after the string.\n\n            let end := str // Cache the end to calculate the length later.\n            // Store \"0123456789abcdef\" in scratch space.\n            mstore(0x0f, 0x30313233343536373839616263646566)\n\n            let start := sub(str, add(length, length))\n            let w := not(1) // Tsk.\n            let temp := value\n            // We write the string from rightmost digit to leftmost digit.\n            // The following is essentially a do-while loop that also handles the zero case.\n            for {} 1 {} {\n                str := add(str, w) // `sub(str, 2)`.\n                mstore8(add(str, 1), mload(and(temp, 15)))\n                mstore8(str, mload(and(shr(4, temp), 15)))\n                temp := shr(8, temp)\n                if iszero(xor(str, start)) { break }\n            }\n            if temp {\n                mstore(0x00, 0x2194895a) // `HexLengthInsufficient()`.\n                revert(0x1c, 0x04)\n            }\n            let strLength := sub(end, str)\n            str := sub(str, 0x20)\n            mstore(str, strLength) // Store the length.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is prefixed with \"0x\" and encoded using 2 hexadecimal digits per byte.\n    /// As address are 20 bytes long, the output will left-padded to have\n    /// a length of `20 * 2 + 2` bytes.\n    function toHexString(uint256 value) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(value);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let strLength := add(mload(str), 2) // Compute the length.\n            mstore(str, 0x3078) // Store the \"0x\" prefix.\n            str := sub(str, 2) // Move the pointer.\n            mstore(str, strLength) // Store the length.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is prefixed with \"0x\".\n    /// The output excludes leading \"0\" from the `toHexString` output.\n    /// `0x00: \"0x0\", 0x01: \"0x1\", 0x12: \"0x12\", 0x123: \"0x123\"`.\n    function toMinimalHexString(uint256 value) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(value);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present.\n            let strLength := add(mload(str), 2) // Compute the length.\n            mstore(add(str, o), 0x3078) // Store the \"0x\" prefix, accounting for leading zero.\n            str := sub(add(str, o), 2) // Move the pointer, accounting for leading zero.\n            mstore(str, sub(strLength, o)) // Store the length, accounting for leading zero.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output excludes leading \"0\" from the `toHexStringNoPrefix` output.\n    /// `0x00: \"0\", 0x01: \"1\", 0x12: \"12\", 0x123: \"123\"`.\n    function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(value);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present.\n            let strLength := mload(str) // Get the length.\n            str := add(str, o) // Move the pointer, accounting for leading zero.\n            mstore(str, sub(strLength, o)) // Store the length, accounting for leading zero.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is encoded using 2 hexadecimal digits per byte.\n    /// As address are 20 bytes long, the output will left-padded to have\n    /// a length of `20 * 2` bytes.\n    function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,\n            // 0x02 bytes for the prefix, and 0x40 bytes for the digits.\n            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0.\n            str := add(mload(0x40), 0x80)\n            mstore(0x40, add(str, 0x20)) // Allocate the memory.\n            mstore(str, 0) // Zeroize the slot after the string.\n\n            let end := str // Cache the end to calculate the length later.\n            mstore(0x0f, 0x30313233343536373839616263646566) // Store the \"0123456789abcdef\" lookup.\n\n            let w := not(1) // Tsk.\n            // We write the string from rightmost digit to leftmost digit.\n            // The following is essentially a do-while loop that also handles the zero case.\n            for { let temp := value } 1 {} {\n                str := add(str, w) // `sub(str, 2)`.\n                mstore8(add(str, 1), mload(and(temp, 15)))\n                mstore8(str, mload(and(shr(4, temp), 15)))\n                temp := shr(8, temp)\n                if iszero(temp) { break }\n            }\n            let strLength := sub(end, str)\n            str := sub(str, 0x20)\n            mstore(str, strLength) // Store the length.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is prefixed with \"0x\", encoded using 2 hexadecimal digits per byte,\n    /// and the alphabets are capitalized conditionally according to\n    /// https://eips.ethereum.org/EIPS/eip-55\n    function toHexStringChecksummed(address value) internal pure returns (string memory str) {\n        str = toHexString(value);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...`\n            let o := add(str, 0x22)\n            let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... `\n            let t := shl(240, 136) // `0b10001000 << 240`\n            for { let i := 0 } 1 {} {\n                mstore(add(i, i), mul(t, byte(i, hashed)))\n                i := add(i, 1)\n                if eq(i, 20) { break }\n            }\n            mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))\n            o := add(o, 0x20)\n            mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is prefixed with \"0x\" and encoded using 2 hexadecimal digits per byte.\n    function toHexString(address value) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(value);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let strLength := add(mload(str), 2) // Compute the length.\n            mstore(str, 0x3078) // Store the \"0x\" prefix.\n            str := sub(str, 2) // Move the pointer.\n            mstore(str, strLength) // Store the length.\n        }\n    }\n\n    /// @dev Returns the hexadecimal representation of `value`.\n    /// The output is encoded using 2 hexadecimal digits per byte.\n    function toHexStringNoPrefix(address value) internal pure returns (string memory str) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            str := mload(0x40)\n            // Allocate the memory.\n            // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,\n            // 0x02 bytes for the prefix, and 0x28 bytes for the digits.\n            // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.\n            mstore(0x40, add(str, 0x80))\n            mstore(0x0f, 0x30313233343536373839616263646566) // Store the \"0123456789abcdef\" lookup.\n\n            str := add(str, 2)\n            mstore(str, 40) // Store the length.\n            let o := add(str, 0x20)\n            mstore(add(o, 40), 0) // Zeroize the slot after the string.\n            value := shl(96, value)\n            // We write the string from rightmost digit to leftmost digit.\n            // The following is essentially a do-while loop that also handles the zero case.\n            for { let i := 0 } 1 {} {\n                let p := add(o, add(i, i))\n                let temp := byte(i, value)\n                mstore8(add(p, 1), mload(and(temp, 15)))\n                mstore8(p, mload(shr(4, temp)))\n                i := add(i, 1)\n                if eq(i, 20) { break }\n            }\n        }\n    }\n\n    /// @dev Returns the hex encoded string from the raw bytes.\n    /// The output is encoded using 2 hexadecimal digits per byte.\n    function toHexString(bytes memory raw) internal pure returns (string memory str) {\n        str = toHexStringNoPrefix(raw);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let strLength := add(mload(str), 2) // Compute the length.\n            mstore(str, 0x3078) // Store the \"0x\" prefix.\n            str := sub(str, 2) // Move the pointer.\n            mstore(str, strLength) // Store the length.\n        }\n    }\n\n    /// @dev Returns the hex encoded string from the raw bytes.\n    /// The output is encoded using 2 hexadecimal digits per byte.\n    function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let length := mload(raw)\n            str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix.\n            mstore(str, add(length, length)) // Store the length of the output.\n\n            mstore(0x0f, 0x30313233343536373839616263646566) // Store the \"0123456789abcdef\" lookup.\n            let o := add(str, 0x20)\n            let end := add(raw, length)\n            for {} iszero(eq(raw, end)) {} {\n                raw := add(raw, 1)\n                mstore8(add(o, 1), mload(and(mload(raw), 15)))\n                mstore8(o, mload(and(shr(4, mload(raw)), 15)))\n                o := add(o, 2)\n            }\n            mstore(o, 0) // Zeroize the slot after the string.\n            mstore(0x40, add(o, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   RUNE STRING OPERATIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the number of UTF characters in the string.\n    function runeCount(string memory s) internal pure returns (uint256 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if mload(s) {\n                mstore(0x00, div(not(0), 255))\n                mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506)\n                let o := add(s, 0x20)\n                let end := add(o, mload(s))\n                for { result := 1 } 1 { result := add(result, 1) } {\n                    o := add(o, byte(0, mload(shr(250, mload(o)))))\n                    if iszero(lt(o, end)) { break }\n                }\n            }\n        }\n    }\n\n    /// @dev Returns if this string is a 7-bit ASCII string.\n    /// (i.e. all characters codes are in [0..127])\n    function is7BitASCII(string memory s) internal pure returns (bool result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let mask := shl(7, div(not(0), 255))\n            result := 1\n            let n := mload(s)\n            if n {\n                let o := add(s, 0x20)\n                let end := add(o, n)\n                let last := mload(end)\n                mstore(end, 0)\n                for {} 1 {} {\n                    if and(mask, mload(o)) {\n                        result := 0\n                        break\n                    }\n                    o := add(o, 0x20)\n                    if iszero(lt(o, end)) { break }\n                }\n                mstore(end, last)\n            }\n        }\n    }\n\n    /// @dev Returns if this string is a 7-bit ASCII string,\n    /// AND all characters are in the `allowed` lookup.\n    /// Note: If `s` is empty, returns true regardless of `allowed`.\n    function is7BitASCII(string memory s, uint128 allowed) internal pure returns (bool result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := 1\n            if mload(s) {\n                let allowed_ := shr(128, shl(128, allowed))\n                let o := add(s, 0x20)\n                let end := add(o, mload(s))\n                for {} 1 {} {\n                    result := and(result, shr(byte(0, mload(o)), allowed_))\n                    o := add(o, 1)\n                    if iszero(and(result, lt(o, end))) { break }\n                }\n            }\n        }\n    }\n\n    /// @dev Converts the bytes in the 7-bit ASCII string `s` to\n    /// an allowed lookup for use in `is7BitASCII(s, allowed)`.\n    /// To save runtime gas, you can cache the result in an immutable variable.\n    function to7BitASCIIAllowedLookup(string memory s) internal pure returns (uint128 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if mload(s) {\n                let o := add(s, 0x20)\n                let end := add(o, mload(s))\n                for {} 1 {} {\n                    result := or(result, shl(byte(0, mload(o)), 1))\n                    o := add(o, 1)\n                    if iszero(lt(o, end)) { break }\n                }\n                if shr(128, result) {\n                    mstore(0x00, 0xc9807e0d) // `StringNot7BitASCII()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   BYTE STRING OPERATIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // For performance and bytecode compactness, byte string operations are restricted\n    // to 7-bit ASCII strings. All offsets are byte offsets, not UTF character offsets.\n    // Usage of byte string operations on charsets with runes spanning two or more bytes\n    // can lead to undefined behavior.\n\n    /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`.\n    function replace(string memory subject, string memory search, string memory replacement)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let subjectLength := mload(subject)\n            let searchLength := mload(search)\n            let replacementLength := mload(replacement)\n\n            subject := add(subject, 0x20)\n            search := add(search, 0x20)\n            replacement := add(replacement, 0x20)\n            result := add(mload(0x40), 0x20)\n\n            let subjectEnd := add(subject, subjectLength)\n            if iszero(gt(searchLength, subjectLength)) {\n                let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1)\n                let h := 0\n                if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }\n                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))\n                let s := mload(search)\n                for {} 1 {} {\n                    let t := mload(subject)\n                    // Whether the first `searchLength % 32` bytes of\n                    // `subject` and `search` matches.\n                    if iszero(shr(m, xor(t, s))) {\n                        if h {\n                            if iszero(eq(keccak256(subject, searchLength), h)) {\n                                mstore(result, t)\n                                result := add(result, 1)\n                                subject := add(subject, 1)\n                                if iszero(lt(subject, subjectSearchEnd)) { break }\n                                continue\n                            }\n                        }\n                        // Copy the `replacement` one word at a time.\n                        for { let o := 0 } 1 {} {\n                            mstore(add(result, o), mload(add(replacement, o)))\n                            o := add(o, 0x20)\n                            if iszero(lt(o, replacementLength)) { break }\n                        }\n                        result := add(result, replacementLength)\n                        subject := add(subject, searchLength)\n                        if searchLength {\n                            if iszero(lt(subject, subjectSearchEnd)) { break }\n                            continue\n                        }\n                    }\n                    mstore(result, t)\n                    result := add(result, 1)\n                    subject := add(subject, 1)\n                    if iszero(lt(subject, subjectSearchEnd)) { break }\n                }\n            }\n\n            let resultRemainder := result\n            result := add(mload(0x40), 0x20)\n            let k := add(sub(resultRemainder, result), sub(subjectEnd, subject))\n            // Copy the rest of the string one word at a time.\n            for {} lt(subject, subjectEnd) {} {\n                mstore(resultRemainder, mload(subject))\n                resultRemainder := add(resultRemainder, 0x20)\n                subject := add(subject, 0x20)\n            }\n            result := sub(result, 0x20)\n            let last := add(add(result, 0x20), k) // Zeroize the slot after the string.\n            mstore(last, 0)\n            mstore(0x40, add(last, 0x20)) // Allocate the memory.\n            mstore(result, k) // Store the length.\n        }\n    }\n\n    /// @dev Returns the byte index of the first location of `search` in `subject`,\n    /// searching from left to right, starting from `from`.\n    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.\n    function indexOf(string memory subject, string memory search, uint256 from)\n        internal\n        pure\n        returns (uint256 result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for { let subjectLength := mload(subject) } 1 {} {\n                if iszero(mload(search)) {\n                    if iszero(gt(from, subjectLength)) {\n                        result := from\n                        break\n                    }\n                    result := subjectLength\n                    break\n                }\n                let searchLength := mload(search)\n                let subjectStart := add(subject, 0x20)\n\n                result := not(0) // Initialize to `NOT_FOUND`.\n                subject := add(subjectStart, from)\n                let end := add(sub(add(subjectStart, subjectLength), searchLength), 1)\n\n                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))\n                let s := mload(add(search, 0x20))\n\n                if iszero(and(lt(subject, end), lt(from, subjectLength))) { break }\n\n                if iszero(lt(searchLength, 0x20)) {\n                    for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {\n                        if iszero(shr(m, xor(mload(subject), s))) {\n                            if eq(keccak256(subject, searchLength), h) {\n                                result := sub(subject, subjectStart)\n                                break\n                            }\n                        }\n                        subject := add(subject, 1)\n                        if iszero(lt(subject, end)) { break }\n                    }\n                    break\n                }\n                for {} 1 {} {\n                    if iszero(shr(m, xor(mload(subject), s))) {\n                        result := sub(subject, subjectStart)\n                        break\n                    }\n                    subject := add(subject, 1)\n                    if iszero(lt(subject, end)) { break }\n                }\n                break\n            }\n        }\n    }\n\n    /// @dev Returns the byte index of the first location of `search` in `subject`,\n    /// searching from left to right.\n    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.\n    function indexOf(string memory subject, string memory search)\n        internal\n        pure\n        returns (uint256 result)\n    {\n        result = indexOf(subject, search, 0);\n    }\n\n    /// @dev Returns the byte index of the first location of `search` in `subject`,\n    /// searching from right to left, starting from `from`.\n    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.\n    function lastIndexOf(string memory subject, string memory search, uint256 from)\n        internal\n        pure\n        returns (uint256 result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for {} 1 {} {\n                result := not(0) // Initialize to `NOT_FOUND`.\n                let searchLength := mload(search)\n                if gt(searchLength, mload(subject)) { break }\n                let w := result\n\n                let fromMax := sub(mload(subject), searchLength)\n                if iszero(gt(fromMax, from)) { from := fromMax }\n\n                let end := add(add(subject, 0x20), w)\n                subject := add(add(subject, 0x20), from)\n                if iszero(gt(subject, end)) { break }\n                // As this function is not too often used,\n                // we shall simply use keccak256 for smaller bytecode size.\n                for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {\n                    if eq(keccak256(subject, searchLength), h) {\n                        result := sub(subject, add(end, 1))\n                        break\n                    }\n                    subject := add(subject, w) // `sub(subject, 1)`.\n                    if iszero(gt(subject, end)) { break }\n                }\n                break\n            }\n        }\n    }\n\n    /// @dev Returns the byte index of the first location of `search` in `subject`,\n    /// searching from right to left.\n    /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.\n    function lastIndexOf(string memory subject, string memory search)\n        internal\n        pure\n        returns (uint256 result)\n    {\n        result = lastIndexOf(subject, search, uint256(int256(-1)));\n    }\n\n    /// @dev Returns true if `search` is found in `subject`, false otherwise.\n    function contains(string memory subject, string memory search) internal pure returns (bool) {\n        return indexOf(subject, search) != NOT_FOUND;\n    }\n\n    /// @dev Returns whether `subject` starts with `search`.\n    function startsWith(string memory subject, string memory search)\n        internal\n        pure\n        returns (bool result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let searchLength := mload(search)\n            // Just using keccak256 directly is actually cheaper.\n            // forgefmt: disable-next-item\n            result := and(\n                iszero(gt(searchLength, mload(subject))),\n                eq(\n                    keccak256(add(subject, 0x20), searchLength),\n                    keccak256(add(search, 0x20), searchLength)\n                )\n            )\n        }\n    }\n\n    /// @dev Returns whether `subject` ends with `search`.\n    function endsWith(string memory subject, string memory search)\n        internal\n        pure\n        returns (bool result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let searchLength := mload(search)\n            let subjectLength := mload(subject)\n            // Whether `search` is not longer than `subject`.\n            let withinRange := iszero(gt(searchLength, subjectLength))\n            // Just using keccak256 directly is actually cheaper.\n            // forgefmt: disable-next-item\n            result := and(\n                withinRange,\n                eq(\n                    keccak256(\n                        // `subject + 0x20 + max(subjectLength - searchLength, 0)`.\n                        add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))),\n                        searchLength\n                    ),\n                    keccak256(add(search, 0x20), searchLength)\n                )\n            )\n        }\n    }\n\n    /// @dev Returns `subject` repeated `times`.\n    function repeat(string memory subject, uint256 times)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let subjectLength := mload(subject)\n            if iszero(or(iszero(times), iszero(subjectLength))) {\n                subject := add(subject, 0x20)\n                result := mload(0x40)\n                let output := add(result, 0x20)\n                for {} 1 {} {\n                    // Copy the `subject` one word at a time.\n                    for { let o := 0 } 1 {} {\n                        mstore(add(output, o), mload(add(subject, o)))\n                        o := add(o, 0x20)\n                        if iszero(lt(o, subjectLength)) { break }\n                    }\n                    output := add(output, subjectLength)\n                    times := sub(times, 1)\n                    if iszero(times) { break }\n                }\n                mstore(output, 0) // Zeroize the slot after the string.\n                let resultLength := sub(output, add(result, 0x20))\n                mstore(result, resultLength) // Store the length.\n                mstore(0x40, add(result, add(resultLength, 0x40))) // Allocate the memory.\n            }\n        }\n    }\n\n    /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive).\n    /// `start` and `end` are byte offsets.\n    function slice(string memory subject, uint256 start, uint256 end)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let subjectLength := mload(subject)\n            if iszero(gt(subjectLength, end)) { end := subjectLength }\n            if iszero(gt(subjectLength, start)) { start := subjectLength }\n            if lt(start, end) {\n                result := mload(0x40)\n                let resultLength := sub(end, start)\n                mstore(result, resultLength)\n                subject := add(subject, start)\n                let w := not(0x1f)\n                // Copy the `subject` one word at a time, backwards.\n                for { let o := and(add(resultLength, 0x1f), w) } 1 {} {\n                    mstore(add(result, o), mload(add(subject, o)))\n                    o := add(o, w) // `sub(o, 0x20)`.\n                    if iszero(o) { break }\n                }\n                // Zeroize the slot after the string.\n                mstore(add(add(result, 0x20), resultLength), 0)\n                mstore(0x40, add(result, add(resultLength, 0x40))) // Allocate the memory.\n            }\n        }\n    }\n\n    /// @dev Returns a copy of `subject` sliced from `start` to the end of the string.\n    /// `start` is a byte offset.\n    function slice(string memory subject, uint256 start)\n        internal\n        pure\n        returns (string memory result)\n    {\n        result = slice(subject, start, uint256(int256(-1)));\n    }\n\n    /// @dev Returns all the indices of `search` in `subject`.\n    /// The indices are byte offsets.\n    function indicesOf(string memory subject, string memory search)\n        internal\n        pure\n        returns (uint256[] memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let subjectLength := mload(subject)\n            let searchLength := mload(search)\n\n            if iszero(gt(searchLength, subjectLength)) {\n                subject := add(subject, 0x20)\n                search := add(search, 0x20)\n                result := add(mload(0x40), 0x20)\n\n                let subjectStart := subject\n                let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1)\n                let h := 0\n                if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }\n                let m := shl(3, sub(0x20, and(searchLength, 0x1f)))\n                let s := mload(search)\n                for {} 1 {} {\n                    let t := mload(subject)\n                    // Whether the first `searchLength % 32` bytes of\n                    // `subject` and `search` matches.\n                    if iszero(shr(m, xor(t, s))) {\n                        if h {\n                            if iszero(eq(keccak256(subject, searchLength), h)) {\n                                subject := add(subject, 1)\n                                if iszero(lt(subject, subjectSearchEnd)) { break }\n                                continue\n                            }\n                        }\n                        // Append to `result`.\n                        mstore(result, sub(subject, subjectStart))\n                        result := add(result, 0x20)\n                        // Advance `subject` by `searchLength`.\n                        subject := add(subject, searchLength)\n                        if searchLength {\n                            if iszero(lt(subject, subjectSearchEnd)) { break }\n                            continue\n                        }\n                    }\n                    subject := add(subject, 1)\n                    if iszero(lt(subject, subjectSearchEnd)) { break }\n                }\n                let resultEnd := result\n                // Assign `result` to the free memory pointer.\n                result := mload(0x40)\n                // Store the length of `result`.\n                mstore(result, shr(5, sub(resultEnd, add(result, 0x20))))\n                // Allocate memory for result.\n                // We allocate one more word, so this array can be recycled for {split}.\n                mstore(0x40, add(resultEnd, 0x20))\n            }\n        }\n    }\n\n    /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string.\n    function split(string memory subject, string memory delimiter)\n        internal\n        pure\n        returns (string[] memory result)\n    {\n        uint256[] memory indices = indicesOf(subject, delimiter);\n        /// @solidity memory-safe-assembly\n        assembly {\n            let w := not(0x1f)\n            let indexPtr := add(indices, 0x20)\n            let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1)))\n            mstore(add(indicesEnd, w), mload(subject))\n            mstore(indices, add(mload(indices), 1))\n            let prevIndex := 0\n            for {} 1 {} {\n                let index := mload(indexPtr)\n                mstore(indexPtr, 0x60)\n                if iszero(eq(index, prevIndex)) {\n                    let element := mload(0x40)\n                    let elementLength := sub(index, prevIndex)\n                    mstore(element, elementLength)\n                    // Copy the `subject` one word at a time, backwards.\n                    for { let o := and(add(elementLength, 0x1f), w) } 1 {} {\n                        mstore(add(element, o), mload(add(add(subject, prevIndex), o)))\n                        o := add(o, w) // `sub(o, 0x20)`.\n                        if iszero(o) { break }\n                    }\n                    // Zeroize the slot after the string.\n                    mstore(add(add(element, 0x20), elementLength), 0)\n                    // Allocate memory for the length and the bytes,\n                    // rounded up to a multiple of 32.\n                    mstore(0x40, add(element, and(add(elementLength, 0x3f), w)))\n                    // Store the `element` into the array.\n                    mstore(indexPtr, element)\n                }\n                prevIndex := add(index, mload(delimiter))\n                indexPtr := add(indexPtr, 0x20)\n                if iszero(lt(indexPtr, indicesEnd)) { break }\n            }\n            result := indices\n            if iszero(mload(delimiter)) {\n                result := add(indices, 0x20)\n                mstore(result, sub(mload(indices), 2))\n            }\n        }\n    }\n\n    /// @dev Returns a concatenated string of `a` and `b`.\n    /// Cheaper than `string.concat()` and does not de-align the free memory pointer.\n    function concat(string memory a, string memory b)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let w := not(0x1f)\n            result := mload(0x40)\n            let aLength := mload(a)\n            // Copy `a` one word at a time, backwards.\n            for { let o := and(add(aLength, 0x20), w) } 1 {} {\n                mstore(add(result, o), mload(add(a, o)))\n                o := add(o, w) // `sub(o, 0x20)`.\n                if iszero(o) { break }\n            }\n            let bLength := mload(b)\n            let output := add(result, aLength)\n            // Copy `b` one word at a time, backwards.\n            for { let o := and(add(bLength, 0x20), w) } 1 {} {\n                mstore(add(output, o), mload(add(b, o)))\n                o := add(o, w) // `sub(o, 0x20)`.\n                if iszero(o) { break }\n            }\n            let totalLength := add(aLength, bLength)\n            let last := add(add(result, 0x20), totalLength)\n            mstore(last, 0) // Zeroize the slot after the string.\n            mstore(result, totalLength) // Store the length.\n            mstore(0x40, add(last, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /// @dev Returns a copy of the string in either lowercase or UPPERCASE.\n    /// WARNING! This function is only compatible with 7-bit ASCII strings.\n    function toCase(string memory subject, bool toUpper)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let length := mload(subject)\n            if length {\n                result := add(mload(0x40), 0x20)\n                subject := add(subject, 1)\n                let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff)\n                let w := not(0)\n                for { let o := length } 1 {} {\n                    o := add(o, w)\n                    let b := and(0xff, mload(add(subject, o)))\n                    mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20)))\n                    if iszero(o) { break }\n                }\n                result := mload(0x40)\n                mstore(result, length) // Store the length.\n                let last := add(add(result, 0x20), length)\n                mstore(last, 0) // Zeroize the slot after the string.\n                mstore(0x40, add(last, 0x20)) // Allocate the memory.\n            }\n        }\n    }\n\n    /// @dev Returns a string from a small bytes32 string.\n    /// `s` must be null-terminated, or behavior will be undefined.\n    function fromSmallString(bytes32 s) internal pure returns (string memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := mload(0x40)\n            let n := 0\n            for {} byte(n, s) { n := add(n, 1) } {} // Scan for '\\0'.\n            mstore(result, n) // Store the length.\n            let o := add(result, 0x20)\n            mstore(o, s) // Store the bytes of the string.\n            mstore(add(o, n), 0) // Zeroize the slot after the string.\n            mstore(0x40, add(result, 0x40)) // Allocate the memory.\n        }\n    }\n\n    /// @dev Returns the small string, with all bytes after the first null byte zeroized.\n    function normalizeSmallString(bytes32 s) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for {} byte(result, s) { result := add(result, 1) } {} // Scan for '\\0'.\n            mstore(0x00, s)\n            mstore(result, 0x00)\n            result := mload(0x00)\n        }\n    }\n\n    /// @dev Returns the string as a normalized null-terminated small string.\n    function toSmallString(string memory s) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := mload(s)\n            if iszero(lt(result, 33)) {\n                mstore(0x00, 0xec92f9a3) // `TooBigForSmallString()`.\n                revert(0x1c, 0x04)\n            }\n            result := shl(shl(3, sub(32, result)), mload(add(s, result)))\n        }\n    }\n\n    /// @dev Returns a lowercased copy of the string.\n    /// WARNING! This function is only compatible with 7-bit ASCII strings.\n    function lower(string memory subject) internal pure returns (string memory result) {\n        result = toCase(subject, false);\n    }\n\n    /// @dev Returns an UPPERCASED copy of the string.\n    /// WARNING! This function is only compatible with 7-bit ASCII strings.\n    function upper(string memory subject) internal pure returns (string memory result) {\n        result = toCase(subject, true);\n    }\n\n    /// @dev Escapes the string to be used within HTML tags.\n    function escapeHTML(string memory s) internal pure returns (string memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let end := add(s, mload(s))\n            result := add(mload(0x40), 0x20)\n            // Store the bytes of the packed offsets and strides into the scratch space.\n            // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6.\n            mstore(0x1f, 0x900094)\n            mstore(0x08, 0xc0000000a6ab)\n            // Store \"&quot;&amp;&#39;&lt;&gt;\" into the scratch space.\n            mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b))\n            for {} iszero(eq(s, end)) {} {\n                s := add(s, 1)\n                let c := and(mload(s), 0xff)\n                // Not in `[\"\\\"\",\"'\",\"&\",\"<\",\">\"]`.\n                if iszero(and(shl(c, 1), 0x500000c400000000)) {\n                    mstore8(result, c)\n                    result := add(result, 1)\n                    continue\n                }\n                let t := shr(248, mload(c))\n                mstore(result, mload(and(t, 0x1f)))\n                result := add(result, shr(5, t))\n            }\n            let last := result\n            mstore(last, 0) // Zeroize the slot after the string.\n            result := mload(0x40)\n            mstore(result, sub(last, add(result, 0x20))) // Store the length.\n            mstore(0x40, add(last, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /// @dev Escapes the string to be used within double-quotes in a JSON.\n    /// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes.\n    function escapeJSON(string memory s, bool addDoubleQuotes)\n        internal\n        pure\n        returns (string memory result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let end := add(s, mload(s))\n            result := add(mload(0x40), 0x20)\n            if addDoubleQuotes {\n                mstore8(result, 34)\n                result := add(1, result)\n            }\n            // Store \"\\\\u0000\" in scratch space.\n            // Store \"0123456789abcdef\" in scratch space.\n            // Also, store `{0x08:\"b\", 0x09:\"t\", 0x0a:\"n\", 0x0c:\"f\", 0x0d:\"r\"}`.\n            // into the scratch space.\n            mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672)\n            // Bitmask for detecting `[\"\\\"\",\"\\\\\"]`.\n            let e := or(shl(0x22, 1), shl(0x5c, 1))\n            for {} iszero(eq(s, end)) {} {\n                s := add(s, 1)\n                let c := and(mload(s), 0xff)\n                if iszero(lt(c, 0x20)) {\n                    if iszero(and(shl(c, 1), e)) {\n                        // Not in `[\"\\\"\",\"\\\\\"]`.\n                        mstore8(result, c)\n                        result := add(result, 1)\n                        continue\n                    }\n                    mstore8(result, 0x5c) // \"\\\\\".\n                    mstore8(add(result, 1), c)\n                    result := add(result, 2)\n                    continue\n                }\n                if iszero(and(shl(c, 1), 0x3700)) {\n                    // Not in `[\"\\b\",\"\\t\",\"\\n\",\"\\f\",\"\\d\"]`.\n                    mstore8(0x1d, mload(shr(4, c))) // Hex value.\n                    mstore8(0x1e, mload(and(c, 15))) // Hex value.\n                    mstore(result, mload(0x19)) // \"\\\\u00XX\".\n                    result := add(result, 6)\n                    continue\n                }\n                mstore8(result, 0x5c) // \"\\\\\".\n                mstore8(add(result, 1), mload(add(c, 8)))\n                result := add(result, 2)\n            }\n            if addDoubleQuotes {\n                mstore8(result, 34)\n                result := add(1, result)\n            }\n            let last := result\n            mstore(last, 0) // Zeroize the slot after the string.\n            result := mload(0x40)\n            mstore(result, sub(last, add(result, 0x20))) // Store the length.\n            mstore(0x40, add(last, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /// @dev Escapes the string to be used within double-quotes in a JSON.\n    function escapeJSON(string memory s) internal pure returns (string memory result) {\n        result = escapeJSON(s, false);\n    }\n\n    /// @dev Returns whether `a` equals `b`.\n    function eq(string memory a, string memory b) internal pure returns (bool result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b)))\n        }\n    }\n\n    /// @dev Returns whether `a` equals `b`, where `b` is a null-terminated small string.\n    function eqs(string memory a, bytes32 b) internal pure returns (bool result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // These should be evaluated on compile time, as far as possible.\n            let m := not(shl(7, div(not(iszero(b)), 255))) // `0x7f7f ...`.\n            let x := not(or(m, or(b, add(m, and(b, m)))))\n            let r := shl(7, iszero(iszero(shr(128, x))))\n            r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(r, shl(3, lt(0xff, shr(r, x))))\n            // forgefmt: disable-next-item\n            result := gt(eq(mload(a), add(iszero(x), xor(31, shr(3, r)))),\n                xor(shr(add(8, r), b), shr(add(8, r), mload(add(a, 0x20)))))\n        }\n    }\n\n    /// @dev Packs a single string with its length into a single word.\n    /// Returns `bytes32(0)` if the length is zero or greater than 31.\n    function packOne(string memory a) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // We don't need to zero right pad the string,\n            // since this is our own custom non-standard packing scheme.\n            result :=\n                mul(\n                    // Load the length and the bytes.\n                    mload(add(a, 0x1f)),\n                    // `length != 0 && length < 32`. Abuses underflow.\n                    // Assumes that the length is valid and within the block gas limit.\n                    lt(sub(mload(a), 1), 0x1f)\n                )\n        }\n    }\n\n    /// @dev Unpacks a string packed using {packOne}.\n    /// Returns the empty string if `packed` is `bytes32(0)`.\n    /// If `packed` is not an output of {packOne}, the output behavior is undefined.\n    function unpackOne(bytes32 packed) internal pure returns (string memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := mload(0x40) // Grab the free memory pointer.\n            mstore(0x40, add(result, 0x40)) // Allocate 2 words (1 for the length, 1 for the bytes).\n            mstore(result, 0) // Zeroize the length slot.\n            mstore(add(result, 0x1f), packed) // Store the length and bytes.\n            mstore(add(add(result, 0x20), mload(result)), 0) // Right pad with zeroes.\n        }\n    }\n\n    /// @dev Packs two strings with their lengths into a single word.\n    /// Returns `bytes32(0)` if combined length is zero or greater than 30.\n    function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let aLength := mload(a)\n            // We don't need to zero right pad the strings,\n            // since this is our own custom non-standard packing scheme.\n            result :=\n                mul(\n                    or( // Load the length and the bytes of `a` and `b`.\n                        shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))),\n                        mload(sub(add(b, 0x1e), aLength))\n                    ),\n                    // `totalLength != 0 && totalLength < 31`. Abuses underflow.\n                    // Assumes that the lengths are valid and within the block gas limit.\n                    lt(sub(add(aLength, mload(b)), 1), 0x1e)\n                )\n        }\n    }\n\n    /// @dev Unpacks strings packed using {packTwo}.\n    /// Returns the empty strings if `packed` is `bytes32(0)`.\n    /// If `packed` is not an output of {packTwo}, the output behavior is undefined.\n    function unpackTwo(bytes32 packed)\n        internal\n        pure\n        returns (string memory resultA, string memory resultB)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            resultA := mload(0x40) // Grab the free memory pointer.\n            resultB := add(resultA, 0x40)\n            // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words.\n            mstore(0x40, add(resultB, 0x40))\n            // Zeroize the length slots.\n            mstore(resultA, 0)\n            mstore(resultB, 0)\n            // Store the lengths and bytes.\n            mstore(add(resultA, 0x1f), packed)\n            mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA))))\n            // Right pad with zeroes.\n            mstore(add(add(resultA, 0x20), mload(resultA)), 0)\n            mstore(add(add(resultB, 0x20), mload(resultB)), 0)\n        }\n    }\n\n    /// @dev Directly returns `a` without copying.\n    function directReturn(string memory a) internal pure {\n        assembly {\n            // Assumes that the string does not start from the scratch space.\n            let retStart := sub(a, 0x20)\n            let retUnpaddedSize := add(mload(a), 0x40)\n            // Right pad with zeroes. Just in case the string is produced\n            // by a method that doesn't zero right pad.\n            mstore(add(retStart, retUnpaddedSize), 0)\n            mstore(retStart, 0x20) // Store the return offset.\n            // End the transaction, returning the string.\n            return(retStart, and(not(0x1f), add(0x1f, retUnpaddedSize)))\n        }\n    }\n}\n"},"solady/src/utils/ReentrancyGuard.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Reentrancy guard mixin.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ReentrancyGuard.sol)\nabstract contract ReentrancyGuard {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Unauthorized reentrant call.\n    error Reentrancy();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                          STORAGE                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Equivalent to: `uint72(bytes9(keccak256(\"_REENTRANCY_GUARD_SLOT\")))`.\n    /// 9 bytes is large enough to avoid collisions with lower slots,\n    /// but not too large to result in excessive bytecode bloat.\n    uint256 private constant _REENTRANCY_GUARD_SLOT = 0x929eee149b4bd21268;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                      REENTRANCY GUARD                      */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Guards a function from reentrancy.\n    modifier nonReentrant() virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if eq(sload(_REENTRANCY_GUARD_SLOT), address()) {\n                mstore(0x00, 0xab143c06) // `Reentrancy()`.\n                revert(0x1c, 0x04)\n            }\n            sstore(_REENTRANCY_GUARD_SLOT, address())\n        }\n        _;\n        /// @solidity memory-safe-assembly\n        assembly {\n            sstore(_REENTRANCY_GUARD_SLOT, codesize())\n        }\n    }\n\n    /// @dev Guards a view function from read-only reentrancy.\n    modifier nonReadReentrant() virtual {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if eq(sload(_REENTRANCY_GUARD_SLOT), address()) {\n                mstore(0x00, 0xab143c06) // `Reentrancy()`.\n                revert(0x1c, 0x04)\n            }\n        }\n        _;\n    }\n}\n"},"solady/src/utils/SSTORE2.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Read and write to persistent storage at a fraction of the cost.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SSTORE2.sol)\n/// @author Saw-mon-and-Natalie (https://github.com/Saw-mon-and-Natalie)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol)\n/// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol)\n/// @author Modified from SSTORE3 (https://github.com/Philogy/sstore3)\nlibrary SSTORE2 {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         CONSTANTS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The proxy initialization code.\n    uint256 private constant _CREATE3_PROXY_INITCODE = 0x67363d3d37363d34f03d5260086018f3;\n\n    /// @dev Hash of the `_CREATE3_PROXY_INITCODE`.\n    /// Equivalent to `keccak256(abi.encodePacked(hex\"67363d3d37363d34f03d5260086018f3\"))`.\n    bytes32 internal constant CREATE3_PROXY_INITCODE_HASH =\n        0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                        CUSTOM ERRORS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Unable to deploy the storage contract.\n    error DeploymentFailed();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         WRITE LOGIC                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Writes `data` into the bytecode of a storage contract and returns its address.\n    function write(bytes memory data) internal returns (address pointer) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let n := mload(data) // Let `l` be `n + 1`. +1 as we prefix a STOP opcode.\n            /**\n             * ---------------------------------------------------+\n             * Opcode | Mnemonic       | Stack     | Memory       |\n             * ---------------------------------------------------|\n             * 61 l   | PUSH2 l        | l         |              |\n             * 80     | DUP1           | l l       |              |\n             * 60 0xa | PUSH1 0xa      | 0xa l l   |              |\n             * 3D     | RETURNDATASIZE | 0 0xa l l |              |\n             * 39     | CODECOPY       | l         | [0..l): code |\n             * 3D     | RETURNDATASIZE | 0 l       | [0..l): code |\n             * F3     | RETURN         |           | [0..l): code |\n             * 00     | STOP           |           |              |\n             * ---------------------------------------------------+\n             * @dev Prefix the bytecode with a STOP opcode to ensure it cannot be called.\n             * Also PUSH2 is used since max contract size cap is 24,576 bytes which is less than 2 ** 16.\n             */\n            // Do a out-of-gas revert if `n + 1` is more than 2 bytes.\n            mstore(add(data, gt(n, 0xfffe)), add(0xfe61000180600a3d393df300, shl(0x40, n)))\n            // Deploy a new contract with the generated creation code.\n            pointer := create(0, add(data, 0x15), add(n, 0xb))\n            if iszero(pointer) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(data, n) // Restore the length of `data`.\n        }\n    }\n\n    /// @dev Writes `data` into the bytecode of a storage contract with `salt`\n    /// and returns its normal CREATE2 deterministic address.\n    function writeCounterfactual(bytes memory data, bytes32 salt)\n        internal\n        returns (address pointer)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let n := mload(data)\n            // Do a out-of-gas revert if `n + 1` is more than 2 bytes.\n            mstore(add(data, gt(n, 0xfffe)), add(0xfe61000180600a3d393df300, shl(0x40, n)))\n            // Deploy a new contract with the generated creation code.\n            pointer := create2(0, add(data, 0x15), add(n, 0xb), salt)\n            if iszero(pointer) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(data, n) // Restore the length of `data`.\n        }\n    }\n\n    /// @dev Writes `data` into the bytecode of a storage contract and returns its address.\n    /// This uses the so-called \"CREATE3\" workflow,\n    /// which means that `pointer` is agnostic to `data, and only depends on `salt`.\n    function writeDeterministic(bytes memory data, bytes32 salt)\n        internal\n        returns (address pointer)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let n := mload(data)\n            mstore(0x00, _CREATE3_PROXY_INITCODE) // Store the `_PROXY_INITCODE`.\n            let proxy := create2(0, 0x10, 0x10, salt)\n            if iszero(proxy) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x14, proxy) // Store the proxy's address.\n            // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01).\n            // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex).\n            mstore(0x00, 0xd694)\n            mstore8(0x34, 0x01) // Nonce of the proxy contract (1).\n            pointer := keccak256(0x1e, 0x17)\n\n            // Do a out-of-gas revert if `n + 1` is more than 2 bytes.\n            mstore(add(data, gt(n, 0xfffe)), add(0xfe61000180600a3d393df300, shl(0x40, n)))\n            if iszero(\n                mul( // The arguments of `mul` are evaluated last to first.\n                    extcodesize(pointer),\n                    call(gas(), proxy, 0, add(data, 0x15), add(n, 0xb), codesize(), 0x00)\n                )\n            ) {\n                mstore(0x00, 0x30116425) // `DeploymentFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(data, n) // Restore the length of `data`.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                    ADDRESS CALCULATIONS                    */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the initialization code hash of the storage contract for `data`.\n    /// Used for mining vanity addresses with create2crunch.\n    function initCodeHash(bytes memory data) internal pure returns (bytes32 hash) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let n := mload(data)\n            // Do a out-of-gas revert if `n + 1` is more than 2 bytes.\n            returndatacopy(returndatasize(), returndatasize(), gt(n, 0xfffe))\n            mstore(data, add(0x61000180600a3d393df300, shl(0x40, n)))\n            hash := keccak256(add(data, 0x15), add(n, 0xb))\n            mstore(data, n) // Restore the length of `data`.\n        }\n    }\n\n    /// @dev Equivalent to `predictCounterfactualAddress(data, salt, address(this))`\n    function predictCounterfactualAddress(bytes memory data, bytes32 salt)\n        internal\n        view\n        returns (address pointer)\n    {\n        pointer = predictCounterfactualAddress(data, salt, address(this));\n    }\n\n    /// @dev Returns the CREATE2 address of the storage contract for `data`\n    /// deployed with `salt` by `deployer`.\n    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.\n    function predictCounterfactualAddress(bytes memory data, bytes32 salt, address deployer)\n        internal\n        pure\n        returns (address predicted)\n    {\n        bytes32 hash = initCodeHash(data);\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute and store the bytecode hash.\n            mstore8(0x00, 0xff) // Write the prefix.\n            mstore(0x35, hash)\n            mstore(0x01, shl(96, deployer))\n            mstore(0x15, salt)\n            predicted := keccak256(0x00, 0x55)\n            // Restore the part of the free memory pointer that has been overwritten.\n            mstore(0x35, 0)\n        }\n    }\n\n    /// @dev Equivalent to `predictDeterministicAddress(salt, address(this))`.\n    function predictDeterministicAddress(bytes32 salt) internal view returns (address pointer) {\n        pointer = predictDeterministicAddress(salt, address(this));\n    }\n\n    /// @dev Returns the \"CREATE3\" deterministic address for `salt` with `deployer`.\n    function predictDeterministicAddress(bytes32 salt, address deployer)\n        internal\n        pure\n        returns (address pointer)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, deployer) // Store `deployer`.\n            mstore8(0x0b, 0xff) // Store the prefix.\n            mstore(0x20, salt) // Store the salt.\n            mstore(0x40, CREATE3_PROXY_INITCODE_HASH) // Store the bytecode hash.\n\n            mstore(0x14, keccak256(0x0b, 0x55)) // Store the proxy's address.\n            mstore(0x40, m) // Restore the free memory pointer.\n            // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01).\n            // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex).\n            mstore(0x00, 0xd694)\n            mstore8(0x34, 0x01) // Nonce of the proxy contract (1).\n            pointer := keccak256(0x1e, 0x17)\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         READ LOGIC                         */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Equivalent to `read(pointer, 0, 2 ** 256 - 1)`.\n    function read(address pointer) internal view returns (bytes memory data) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            data := mload(0x40)\n            let n := and(sub(extcodesize(pointer), 0x01), 0xffffffffff)\n            extcodecopy(pointer, add(data, 0x1f), 0x00, add(n, 0x21))\n            mstore(data, n) // Store the length.\n            mstore(0x40, add(n, add(data, 0x40))) // Allocate memory.\n        }\n    }\n\n    /// @dev Equivalent to `read(pointer, start, 2 ** 256 - 1)`.\n    function read(address pointer, uint256 start) internal view returns (bytes memory data) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            data := mload(0x40)\n            let n := and(sub(extcodesize(pointer), 0x01), 0xffffffffff)\n            extcodecopy(pointer, add(data, 0x1f), start, add(n, 0x21))\n            mstore(data, mul(sub(n, start), lt(start, n))) // Store the length.\n            mstore(0x40, add(data, add(0x40, mload(data)))) // Allocate memory.\n        }\n    }\n\n    /// @dev Returns a slice of the data on `pointer` from `start` to `end`.\n    /// `start` and `end` will be clamped to the range `[0, args.length]`.\n    /// The `pointer` MUST be deployed via the SSTORE2 write functions.\n    /// Otherwise, the behavior is undefined.\n    /// Out-of-gas reverts if `pointer` does not have any code.\n    function read(address pointer, uint256 start, uint256 end)\n        internal\n        view\n        returns (bytes memory data)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            data := mload(0x40)\n            if iszero(lt(end, 0xffff)) { end := 0xffff }\n            let d := mul(sub(end, start), lt(start, end))\n            extcodecopy(pointer, add(data, 0x1f), start, add(d, 0x01))\n            if iszero(and(0xff, mload(add(data, d)))) {\n                let n := sub(extcodesize(pointer), 0x01)\n                returndatacopy(returndatasize(), returndatasize(), shr(64, n))\n                d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))\n            }\n            mstore(data, d) // Store the length.\n            mstore(add(add(data, 0x20), d), 0) // Zeroize the slot after the bytes.\n            mstore(0x40, add(add(data, 0x40), d)) // Allocate memory.\n        }\n    }\n}\n"}},"deployment":{"transactionHash":"0xfc62fdb44bbd7fd0d6bcff9be55d675dc1d24ca86a6bf09046d797be5b73d6e1","blockNumber":"26056965","transactionIndex":"3","deployer":"0xfFFffFb57D1266CEa6e5648418487083854fdDC9"},"matchId":"53294591","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-09-27T05:54:45Z","match":"exact_match","chainId":"1","address":"0xf5e65A785B62ad1ac616013482bB3C0793DFB601"}