contract ERC721 is IERC165, IERC721, IERC721Metadata {
    // Token name
    string public constant override name = 'Doom Cult Society';

    // Token symbol
    string public constant override symbol = 'DCS';

    uint256 internal constant ERROR_SIG = 0x08c379a000000000000000000000000000000000000000000000000000000000;
    // event signatures
    uint256 private constant APPROVAL_FOR_ALL_SIG = 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31;
    bytes32 internal constant TRANSFER_SIG = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
    bytes32 internal constant APPROVAL_SIG = 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;

    // Mapping from token ID to owner address
    mapping(uint256 => address) internal _owners;

    // Mapping owner address to token count
    mapping(address => uint256) internal _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor() {}

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            interfaceId == type(IERC165).interfaceId;
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256 res) {
        assembly {
            if iszero(owner) {
                mstore(0x00, ERROR_SIG)
                mstore(0x04, 0x20)
                mstore(0x24, 42)
                mstore(0x44, 'ERC721: balance query for the ze')
                mstore(0x64, 'ro address')
                revert(0x00, 0x84)
            }

            mstore(0x00, owner)
            mstore(0x20, _balances.slot)
            res := sload(keccak256(0x00, 0x40))
        }
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address owner) {
        assembly {
            mstore(0x00, tokenId)
            mstore(0x20, _owners.slot)
            // no need to mask address if we ensure everything written into _owners is an address
            owner := sload(keccak256(0x00, 0x40))

            if iszero(owner) {
                mstore(0x00, ERROR_SIG)
                mstore(0x04, 0x20)
                mstore(0x24, 41)
                mstore(0x44, 'ERC721: owner query for nonexist')
                mstore(0x64, 'ent token')
                revert(0x00, 0x84)
            }
        }
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256) public view virtual override returns (string memory) {
        return '';
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ownerOf(tokenId);

        bool approvedForAll = isApprovedForAll(owner, msg.sender);
        /**
         * Failure cases
         * 1. to == owner (if ya wanna approve yourself go stare in a mirror!)
         * 2. !(msg.sender == owner OR approvedForAll == 1)
         */
        assembly {
            if or(eq(to, owner), iszero(or(eq(caller(), owner), approvedForAll))) {
                mstore(0x00, ERROR_SIG)
                mstore(0x04, 0x20)
                mstore(0x24, 19)
                mstore(0x44, 'ERC721: bad approve')
                revert(0x00, 0x64)
            }

            mstore(0x00, tokenId)
            mstore(0x20, _tokenApprovals.slot)
            sstore(keccak256(0x00, 0x40), to)
            log3(0x00, 0x20, APPROVAL_SIG, owner, to)
        }
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address res) {
        assembly {
            mstore(0x00, tokenId)
            mstore(0x20, _owners.slot)
            if iszero(sload(keccak256(0x00, 0x40))) {
                mstore(0x00, ERROR_SIG)
                mstore(0x04, 0x20)
                mstore(0x24, 19)
                mstore(0x44, 'ERC721: bad approve')
                revert(0x00, 0x64)
            }

            mstore(0x00, tokenId)
            mstore(0x20, _tokenApprovals.slot)
            res := sload(keccak256(0x00, 0x40))
        }
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        assembly {
            if eq(operator, caller()) {
                mstore(0x00, ERROR_SIG)
                mstore(0x04, 0x20)
                mstore(0x24, 25)
                mstore(0x44, 'ERC721: approve to caller')
                revert(0x00, 0x64)
            }

            // _operatorApprovals[_msgSender()][operator] = approved
            mstore(0x00, caller())
            mstore(0x20, _operatorApprovals.slot)
            mstore(0x20, keccak256(0x00, 0x40))
            mstore(0x00, operator)
            sstore(keccak256(0x00, 0x40), approved)

            log4(0, 0, APPROVAL_FOR_ALL_SIG, caller(), operator, approved)
        }
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool res) {
        assembly {
            mstore(0x00, owner)
            mstore(0x20, _operatorApprovals.slot)
            mstore(0x20, keccak256(0x00, 0x40))
            mstore(0x00, operator)
            res := sload(keccak256(0x00, 0x40))
        }
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        _isApprovedOrOwner(msg.sender, tokenId);
        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, '');
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public virtual override {
        _isApprovedOrOwner(msg.sender, tokenId);
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal virtual {
        _transfer(from, to, tokenId);
        bool isContract;
        assembly {
            isContract := gt(extcodesize(to), 0)
        }
        if (isContract) {
            _checkOnERC721ReceivedContract(from, to, tokenId, _data);
        }
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual {
        address owner;
        bool approvedForAll = isApprovedForAll(owner, spender);
        assembly {
            mstore(0x00, tokenId)
            mstore(0x20, _owners.slot)
            owner := sload(keccak256(0x00, 0x40))

            mstore(0x20, _tokenApprovals.slot)
            let approved := sload(keccak256(0x00, 0x40))

            /**
             * Success Conditions
             * 1. spender = owner
             * 2. spender = approved
             * 3. approvedForAll = true
             * Also owner must NOT be 0
             */
            if or(iszero(or(or(eq(spender, owner), eq(approved, spender)), approvedForAll)), iszero(owner)) {
                mstore(0x00, ERROR_SIG)
                mstore(0x04, 0x20)
                mstore(0x24, 44)
                mstore(0x44, 'ERC721: operator query for nonex')
                mstore(0x64, 'istent token')
                revert(0x00, 0x84)
            }
        }
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        // address owner = ownerOf(tokenId);
        assembly {
            mstore(0x00, tokenId)
            mstore(0x20, _owners.slot)
            let owner := sload(keccak256(0x00, 0x40))

            // Clear approvals from the previous owner
            mstore(0x00, tokenId)
            mstore(0x20, _tokenApprovals.slot)
            sstore(keccak256(0x00, 0x40), 0)
            log3(0x00, 0x20, APPROVAL_SIG, owner, 0)
            log3(0x00, 0x20, TRANSFER_SIG, from, to)

            // _owners[tokenId] = to
            mstore(0x20, _owners.slot)
            sstore(keccak256(0x00, 0x40), to)

            // _balances[from] -= 1
            mstore(0x00, from)
            mstore(0x20, _balances.slot)
            let slot := keccak256(0x00, 0x40)
            let fromBalance := sload(slot)
            sstore(slot, sub(fromBalance, 0x01))

            // _balances[to] += 1
            mstore(0x00, to)
            slot := keccak256(0x00, 0x40)
            sstore(slot, add(sload(slot), 1))

            /**
             * Failure cases...
             * 1. owner != from
             * 2. to == 0
             * 3. owner == 0
             * 4. balances[from] == 0
             */
            if or(or(iszero(owner), iszero(fromBalance)), or(iszero(to), sub(owner, from))) {
                mstore(0x00, ERROR_SIG)
                mstore(0x04, 0x20)
                mstore(0x24, 20)
                mstore(0x44, 'ERC721: bad transfer')
                revert(0x00, 0x64)
            }
        }
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     */
    function _checkOnERC721ReceivedContract(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal {
        try IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data) returns (bytes4 retval) {
            require(
                retval == IERC721Receiver(to).onERC721Received.selector,
                'ERC721: transfer to non ERC721Receiver implementer'
            );
        } catch (bytes memory reason) {
            if (reason.length == 0) {
                revert('ERC721: transfer to non ERC721Receiver implementer');
            } else {
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
    }
}
/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension but not the Enumerable extension
 */
function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId,
    bytes memory _data
) public virtual override {
    _isApprovedOrOwner(msg.sender, tokenId);
    _safeTransfer(from, to, tokenId, _data);
}

/**
 * @dev See {IERC721-safeTransferFrom}.
 */