{
  "language": "Solidity",
  "sources": {
    "contracts/Autoglyphs.sol": {
      "content": "pragma solidity ^0.4.24;\n\n/**\n *\n *      ***    **     ** ********  *******   ******   **     **    ** ********  **     **  ******\n *     ** **   **     **    **    **     ** **    **  **      **  **  **     ** **     ** **    **\n *    **   **  **     **    **    **     ** **        **       ****   **     ** **     ** **\n *   **     ** **     **    **    **     ** **   **** **        **    ********  *********  ******\n *   ********* **     **    **    **     ** **    **  **        **    **        **     **       **\n *   **     ** **     **    **    **     ** **    **  **        **    **        **     ** **    **\n *   **     **  *******     **     *******   ******   ********  **    **        **     **  ******\n *\n *\n *                                                                by Matt Hall and John Watkinson\n *\n *\n * The output of the 'tokenURI' function is a set of instructions to make a drawing.\n * Each symbol in the output corresponds to a cell, and there are 64x64 cells arranged in a square grid.\n * The drawing can be any size, and the pen's stroke width should be between 1/5th to 1/10th the size of a cell.\n * The drawing instructions for the nine different symbols are as follows:\n *\n *   .  Draw nothing in the cell.\n *   O  Draw a circle bounded by the cell.\n *   +  Draw centered lines vertically and horizontally the length of the cell.\n *   X  Draw diagonal lines connecting opposite corners of the cell.\n *   |  Draw a centered vertical line the length of the cell.\n *   -  Draw a centered horizontal line the length of the cell.\n *   \\  Draw a line connecting the top left corner of the cell to the bottom right corner.\n *   /  Draw a line connecting the bottom left corner of teh cell to the top right corner.\n *   #  Fill in the cell completely.\n *\n */\ninterface ERC721TokenReceiver\n{\n\n    function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);\n\n}\n\ncontract Autoglyphs {\n\n    event Generated(uint indexed index, address indexed a, string value);\n\n    /// @dev This emits when ownership of any NFT changes by any mechanism.\n    ///  This event emits when NFTs are created (`from` == 0) and destroyed\n    ///  (`to` == 0). Exception: during contract creation, any number of NFTs\n    ///  may be created and assigned without emitting Transfer. At the time of\n    ///  any transfer, the approved address for that NFT (if any) is reset to none.\n    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);\n\n    /// @dev This emits when the approved address for an NFT is changed or\n    ///  reaffirmed. The zero address indicates there is no approved address.\n    ///  When a Transfer event emits, this also indicates that the approved\n    ///  address for that NFT (if any) is reset to none.\n    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);\n\n    /// @dev This emits when an operator is enabled or disabled for an owner.\n    ///  The operator can manage all NFTs of the owner.\n    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);\n\n    bytes4 internal constant MAGIC_ON_ERC721_RECEIVED = 0x150b7a02;\n\n    uint public constant TOKEN_LIMIT = 512; // 8 for testing, 256 or 512 for prod;\n    uint public constant ARTIST_PRINTS = 128; // 2 for testing, 64 for prod;\n\n    uint public constant PRICE = 200 finney;\n\n    // The beneficiary is 350.org\n    address public constant BENEFICIARY = 0x50990F09d4f0cb864b8e046e7edC749dE410916b;\n\n    mapping (uint => address) private idToCreator;\n    mapping (uint => uint8) private idToSymbolScheme;\n\n    // ERC 165\n    mapping(bytes4 => bool) internal supportedInterfaces;\n\n    /**\n     * @dev A mapping from NFT ID to the address that owns it.\n     */\n    mapping (uint256 => address) internal idToOwner;\n\n    /**\n     * @dev A mapping from NFT ID to the seed used to make it.\n     */\n    mapping (uint256 => uint256) internal idToSeed;\n    mapping (uint256 => uint256) internal seedToId;\n\n    /**\n     * @dev Mapping from NFT ID to approved address.\n     */\n    mapping (uint256 => address) internal idToApproval;\n\n    /**\n     * @dev Mapping from owner address to mapping of operator addresses.\n     */\n    mapping (address => mapping (address => bool)) internal ownerToOperators;\n\n    /**\n     * @dev Mapping from owner to list of owned NFT IDs.\n     */\n    mapping(address => uint256[]) internal ownerToIds;\n\n    /**\n     * @dev Mapping from NFT ID to its index in the owner tokens list.\n     */\n    mapping(uint256 => uint256) internal idToOwnerIndex;\n\n    /**\n     * @dev Total number of tokens.\n     */\n    uint internal numTokens = 0;\n\n    /**\n     * @dev Guarantees that the msg.sender is an owner or operator of the given NFT.\n     * @param _tokenId ID of the NFT to validate.\n     */\n    modifier canOperate(uint256 _tokenId) {\n        address tokenOwner = idToOwner[_tokenId];\n        require(tokenOwner == msg.sender || ownerToOperators[tokenOwner][msg.sender]);\n        _;\n    }\n\n    /**\n     * @dev Guarantees that the msg.sender is allowed to transfer NFT.\n     * @param _tokenId ID of the NFT to transfer.\n     */\n    modifier canTransfer(uint256 _tokenId) {\n        address tokenOwner = idToOwner[_tokenId];\n        require(\n            tokenOwner == msg.sender\n            || idToApproval[_tokenId] == msg.sender\n            || ownerToOperators[tokenOwner][msg.sender]\n        );\n        _;\n    }\n\n    /**\n     * @dev Guarantees that _tokenId is a valid Token.\n     * @param _tokenId ID of the NFT to validate.\n     */\n    modifier validNFToken(uint256 _tokenId) {\n        require(idToOwner[_tokenId] != address(0));\n        _;\n    }\n\n    /**\n     * @dev Contract constructor.\n     */\n    constructor() public {\n        supportedInterfaces[0x01ffc9a7] = true; // ERC165\n        supportedInterfaces[0x80ac58cd] = true; // ERC721\n        supportedInterfaces[0x780e9d63] = true; // ERC721 Enumerable\n        supportedInterfaces[0x5b5e139f] = true; // ERC721 Metadata\n    }\n\n    ///////////////////\n    //// GENERATOR ////\n    ///////////////////\n\n    int constant ONE = int(0x100000000);\n    uint constant USIZE = 64;\n    int constant SIZE = int(USIZE);\n    int constant HALF_SIZE = SIZE / int(2);\n\n    int constant SCALE = int(0x1b81a81ab1a81a823);\n    int constant HALF_SCALE = SCALE / int(2);\n\n    bytes prefix = \"data:text/plain;charset=utf-8,\";\n\n    string internal nftName = \"Autoglyphs\";\n    string internal nftSymbol = \"☵\";\n\n    // 0x2E = .\n    // 0x4F = O\n    // 0x2B = +\n    // 0x58 = X\n    // 0x7C = |\n    // 0x2D = -\n    // 0x5C = \\\n    // 0x2F = /\n    // 0x23 = #\n\n    function abs(int n) internal pure returns (int) {\n        if (n >= 0) return n;\n        return -n;\n    }\n\n    function getScheme(uint a) internal pure returns (uint8) {\n        uint index = a % 83;\n        uint8 scheme;\n        if (index < 20) {\n            scheme = 1;\n        } else if (index < 35) {\n            scheme = 2;\n        } else if (index < 48) {\n            scheme = 3;\n        } else if (index < 59) {\n            scheme = 4;\n        } else if (index < 68) {\n            scheme = 5;\n        } else if (index < 73) {\n            scheme = 6;\n        } else if (index < 77) {\n            scheme = 7;\n        } else if (index < 80) {\n            scheme = 8;\n        } else if (index < 82) {\n            scheme = 9;\n        } else {\n            scheme = 10;\n        }\n        return scheme;\n    }\n\n    /* * ** *** ***** ******** ************* ******** ***** *** ** * */\n\n    // The following code generates art.\n\n    function draw(uint id) public view returns (string) {\n        uint a = uint(uint160(keccak256(abi.encodePacked(idToSeed[id]))));\n        bytes memory output = new bytes(USIZE * (USIZE + 3) + 30);\n        uint c;\n        for (c = 0; c < 30; c++) {\n            output[c] = prefix[c];\n        }\n        int x = 0;\n        int y = 0;\n        uint v = 0;\n        uint value = 0;\n        uint mod = (a % 11) + 5;\n        bytes5 symbols;\n        if (idToSymbolScheme[id] == 0) {\n            revert();\n        } else if (idToSymbolScheme[id] == 1) {\n            symbols = 0x2E582F5C2E; // X/\\\n        } else if (idToSymbolScheme[id] == 2) {\n            symbols = 0x2E2B2D7C2E; // +-|\n        } else if (idToSymbolScheme[id] == 3) {\n            symbols = 0x2E2F5C2E2E; // /\\\n        } else if (idToSymbolScheme[id] == 4) {\n            symbols = 0x2E5C7C2D2F; // \\|-/\n        } else if (idToSymbolScheme[id] == 5) {\n            symbols = 0x2E4F7C2D2E; // O|-\n        } else if (idToSymbolScheme[id] == 6) {\n            symbols = 0x2E5C5C2E2E; // \\\n        } else if (idToSymbolScheme[id] == 7) {\n            symbols = 0x2E237C2D2B; // #|-+\n        } else if (idToSymbolScheme[id] == 8) {\n            symbols = 0x2E4F4F2E2E; // OO\n        } else if (idToSymbolScheme[id] == 9) {\n            symbols = 0x2E232E2E2E; // #\n        } else {\n            symbols = 0x2E234F2E2E; // #O\n        }\n        for (int i = int(0); i < SIZE; i++) {\n            y = (2 * (i - HALF_SIZE) + 1);\n            if (a % 3 == 1) {\n                y = -y;\n            } else if (a % 3 == 2) {\n                y = abs(y);\n            }\n            y = y * int(a);\n            for (int j = int(0); j < SIZE; j++) {\n                x = (2 * (j - HALF_SIZE) + 1);\n                if (a % 2 == 1) {\n                    x = abs(x);\n                }\n                x = x * int(a);\n                v = uint(x * y / ONE) % mod;\n                if (v < 5) {\n                    value = uint(symbols[v]);\n                } else {\n                    value = 0x2E;\n                }\n                output[c] = byte(bytes32(value << 248));\n                c++;\n            }\n            output[c] = byte(0x25);\n            c++;\n            output[c] = byte(0x30);\n            c++;\n            output[c] = byte(0x41);\n            c++;\n        }\n        string memory result = string(output);\n        return result;\n    }\n\n    /* * ** *** ***** ******** ************* ******** ***** *** ** * */\n\n    function creator(uint _id) external view returns (address) {\n        return idToCreator[_id];\n    }\n\n    function symbolScheme(uint _id) external view returns (uint8) {\n        return idToSymbolScheme[_id];\n    }\n\n    function createGlyph(uint seed) external payable returns (string) {\n        return _mint(msg.sender, seed);\n    }\n\n    //////////////////////////\n    //// ERC 721 and 165  ////\n    //////////////////////////\n\n    /**\n     * @dev Returns whether the target address is a contract.\n     * @param _addr Address to check.\n     * @return True if _addr is a contract, false if not.\n     */\n    function isContract(address _addr) internal view returns (bool addressCheck) {\n        uint256 size;\n        assembly { size := extcodesize(_addr) } // solhint-disable-line\n        addressCheck = size > 0;\n    }\n\n    /**\n     * @dev Function to check which interfaces are suported by this contract.\n     * @param _interfaceID Id of the interface.\n     * @return True if _interfaceID is supported, false otherwise.\n     */\n    function supportsInterface(bytes4 _interfaceID) external view returns (bool) {\n        return supportedInterfaces[_interfaceID];\n    }\n\n    /**\n     * @dev Transfers the ownership of an NFT from one address to another address. This function can\n     * be changed to payable.\n     * @notice Throws unless `msg.sender` is the current owner, an authorized operator, or the\n     * approved address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is\n     * the zero address. Throws if `_tokenId` is not a valid NFT. When transfer is complete, this\n     * function checks if `_to` is a smart contract (code size > 0). If so, it calls\n     * `onERC721Received` on `_to` and throws if the return value is not\n     * `bytes4(keccak256(\"onERC721Received(address,uint256,bytes)\"))`.\n     * @param _from The current owner of the NFT.\n     * @param _to The new owner.\n     * @param _tokenId The NFT to transfer.\n     * @param _data Additional data with no specified format, sent in call to `_to`.\n     */\n    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes _data) external {\n        _safeTransferFrom(_from, _to, _tokenId, _data);\n    }\n\n    /**\n     * @dev Transfers the ownership of an NFT from one address to another address. This function can\n     * be changed to payable.\n     * @notice This works identically to the other function with an extra data parameter, except this\n     * function just sets data to \"\"\n     * @param _from The current owner of the NFT.\n     * @param _to The new owner.\n     * @param _tokenId The NFT to transfer.\n     */\n    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external {\n        _safeTransferFrom(_from, _to, _tokenId, \"\");\n    }\n\n    /**\n     * @dev Throws unless `msg.sender` is the current owner, an authorized operator, or the approved\n     * address for this NFT. Throws if `_from` is not the current owner. Throws if `_to` is the zero\n     * address. Throws if `_tokenId` is not a valid NFT. This function can be changed to payable.\n     * @notice The caller is responsible to confirm that `_to` is capable of receiving NFTs or else\n     * they maybe be permanently lost.\n     * @param _from The current owner of the NFT.\n     * @param _to The new owner.\n     * @param _tokenId The NFT to transfer.\n     */\n    function transferFrom(address _from, address _to, uint256 _tokenId) external canTransfer(_tokenId) validNFToken(_tokenId) {\n        address tokenOwner = idToOwner[_tokenId];\n        require(tokenOwner == _from);\n        require(_to != address(0));\n        _transfer(_to, _tokenId);\n    }\n\n    /**\n     * @dev Set or reaffirm the approved address for an NFT. This function can be changed to payable.\n     * @notice The zero address indicates there is no approved address. Throws unless `msg.sender` is\n     * the current NFT owner, or an authorized operator of the current owner.\n     * @param _approved Address to be approved for the given NFT ID.\n     * @param _tokenId ID of the token to be approved.\n     */\n    function approve(address _approved, uint256 _tokenId) external canOperate(_tokenId) validNFToken(_tokenId) {\n        address tokenOwner = idToOwner[_tokenId];\n        require(_approved != tokenOwner);\n        idToApproval[_tokenId] = _approved;\n        emit Approval(tokenOwner, _approved, _tokenId);\n    }\n\n    /**\n     * @dev Enables or disables approval for a third party (\"operator\") to manage all of\n     * `msg.sender`'s assets. It also emits the ApprovalForAll event.\n     * @notice This works even if sender doesn't own any tokens at the time.\n     * @param _operator Address to add to the set of authorized operators.\n     * @param _approved True if the operators is approved, false to revoke approval.\n     */\n    function setApprovalForAll(address _operator, bool _approved) external {\n        ownerToOperators[msg.sender][_operator] = _approved;\n        emit ApprovalForAll(msg.sender, _operator, _approved);\n    }\n\n    /**\n     * @dev Returns the number of NFTs owned by `_owner`. NFTs assigned to the zero address are\n     * considered invalid, and this function throws for queries about the zero address.\n     * @param _owner Address for whom to query the balance.\n     * @return Balance of _owner.\n     */\n    function balanceOf(address _owner) external view returns (uint256) {\n        require(_owner != address(0));\n        return _getOwnerNFTCount(_owner);\n    }\n\n    /**\n     * @dev Returns the address of the owner of the NFT. NFTs assigned to zero address are considered\n     * invalid, and queries about them do throw.\n     * @param _tokenId The identifier for an NFT.\n     * @return Address of _tokenId owner.\n     */\n    function ownerOf(uint256 _tokenId) external view returns (address _owner) {\n        _owner = idToOwner[_tokenId];\n        require(_owner != address(0));\n    }\n\n    /**\n     * @dev Get the approved address for a single NFT.\n     * @notice Throws if `_tokenId` is not a valid NFT.\n     * @param _tokenId ID of the NFT to query the approval of.\n     * @return Address that _tokenId is approved for.\n     */\n    function getApproved(uint256 _tokenId) external view validNFToken(_tokenId) returns (address) {\n        return idToApproval[_tokenId];\n    }\n\n    /**\n     * @dev Checks if `_operator` is an approved operator for `_owner`.\n     * @param _owner The address that owns the NFTs.\n     * @param _operator The address that acts on behalf of the owner.\n     * @return True if approved for all, false otherwise.\n     */\n    function isApprovedForAll(address _owner, address _operator) external view returns (bool) {\n        return ownerToOperators[_owner][_operator];\n    }\n\n    /**\n     * @dev Actually preforms the transfer.\n     * @notice Does NO checks.\n     * @param _to Address of a new owner.\n     * @param _tokenId The NFT that is being transferred.\n     */\n    function _transfer(address _to, uint256 _tokenId) internal {\n        address from = idToOwner[_tokenId];\n        _clearApproval(_tokenId);\n\n        _removeNFToken(from, _tokenId);\n        _addNFToken(_to, _tokenId);\n\n        emit Transfer(from, _to, _tokenId);\n}\n\n    /**\n     * @dev Mints a new NFT.\n     * @notice This is an internal function which should be called from user-implemented external\n     * mint function. Its purpose is to show and properly initialize data structures when using this\n     * implementation.\n     * @param _to The address that will own the minted NFT.\n     */\n    function _mint(address _to, uint seed) internal returns (string) {\n        require(_to != address(0));\n        require(numTokens < TOKEN_LIMIT);\n        uint amount = 0;\n        if (numTokens >= ARTIST_PRINTS) {\n            amount = PRICE;\n            require(msg.value >= amount);\n        }\n        require(seedToId[seed] == 0);\n        uint id = numTokens + 1;\n\n        idToCreator[id] = _to;\n        idToSeed[id] = seed;\n        seedToId[seed] = id;\n        uint a = uint(uint160(keccak256(abi.encodePacked(seed))));\n        idToSymbolScheme[id] = getScheme(a);\n        string memory uri = draw(id);\n        emit Generated(id, _to, uri);\n\n        numTokens = numTokens + 1;\n        _addNFToken(_to, id);\n\n        if (msg.value > amount) {\n            msg.sender.transfer(msg.value - amount);\n        }\n        if (amount > 0) {\n            BENEFICIARY.transfer(amount);\n        }\n\n        emit Transfer(address(0), _to, id);\n        return uri;\n    }\n\n    /**\n     * @dev Assigns a new NFT to an address.\n     * @notice Use and override this function with caution. Wrong usage can have serious consequences.\n     * @param _to Address to which we want to add the NFT.\n     * @param _tokenId Which NFT we want to add.\n     */\n    function _addNFToken(address _to, uint256 _tokenId) internal {\n        require(idToOwner[_tokenId] == address(0));\n        idToOwner[_tokenId] = _to;\n\n        uint256 length = ownerToIds[_to].push(_tokenId);\n        idToOwnerIndex[_tokenId] = length - 1;\n    }\n\n    /**\n     * @dev Removes a NFT from an address.\n     * @notice Use and override this function with caution. Wrong usage can have serious consequences.\n     * @param _from Address from wich we want to remove the NFT.\n     * @param _tokenId Which NFT we want to remove.\n     */\n    function _removeNFToken(address _from, uint256 _tokenId) internal {\n        require(idToOwner[_tokenId] == _from);\n        delete idToOwner[_tokenId];\n\n        uint256 tokenToRemoveIndex = idToOwnerIndex[_tokenId];\n        uint256 lastTokenIndex = ownerToIds[_from].length - 1;\n\n        if (lastTokenIndex != tokenToRemoveIndex) {\n            uint256 lastToken = ownerToIds[_from][lastTokenIndex];\n            ownerToIds[_from][tokenToRemoveIndex] = lastToken;\n            idToOwnerIndex[lastToken] = tokenToRemoveIndex;\n        }\n\n        ownerToIds[_from].length--;\n    }\n\n    /**\n     * @dev Helper function that gets NFT count of owner. This is needed for overriding in enumerable\n     * extension to remove double storage (gas optimization) of owner nft count.\n     * @param _owner Address for whom to query the count.\n     * @return Number of _owner NFTs.\n     */\n    function _getOwnerNFTCount(address _owner) internal view returns (uint256) {\n        return ownerToIds[_owner].length;\n    }\n\n    /**\n     * @dev Actually perform the safeTransferFrom.\n     * @param _from The current owner of the NFT.\n     * @param _to The new owner.\n     * @param _tokenId The NFT to transfer.\n     * @param _data Additional data with no specified format, sent in call to `_to`.\n     */\n    function _safeTransferFrom(address _from,  address _to,  uint256 _tokenId,  bytes memory _data) private canTransfer(_tokenId) validNFToken(_tokenId) {\n        address tokenOwner = idToOwner[_tokenId];\n        require(tokenOwner == _from);\n        require(_to != address(0));\n\n        _transfer(_to, _tokenId);\n\n        if (isContract(_to)) {\n            bytes4 retval = ERC721TokenReceiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data);\n            require(retval == MAGIC_ON_ERC721_RECEIVED);\n        }\n    }\n\n    /**\n     * @dev Clears the current approval of a given NFT ID.\n     * @param _tokenId ID of the NFT to be transferred.\n     */\n    function _clearApproval(uint256 _tokenId) private {\n        if (idToApproval[_tokenId] != address(0)) {\n            delete idToApproval[_tokenId];\n        }\n    }\n\n    //// Enumerable\n\n    function totalSupply() public view returns (uint256) {\n        return numTokens;\n    }\n\n    function tokenByIndex(uint256 index) public view returns (uint256) {\n        require(index < numTokens);\n        return index;\n    }\n\n    /**\n     * @dev returns the n-th NFT ID from a list of owner's tokens.\n     * @param _owner Token owner's address.\n     * @param _index Index number representing n-th token in owner's list of tokens.\n     * @return Token id.\n     */\n    function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256) {\n        require(_index < ownerToIds[_owner].length);\n        return ownerToIds[_owner][_index];\n    }\n\n    //// Metadata\n\n    /**\n      * @dev Returns a descriptive name for a collection of NFTokens.\n      * @return Representing name.\n      */\n    function name() external view returns (string memory _name) {\n        _name = nftName;\n    }\n\n    /**\n     * @dev Returns an abbreviated name for NFTokens.\n     * @return Representing symbol.\n     */\n    function symbol() external view returns (string memory _symbol) {\n        _symbol = nftSymbol;\n    }\n\n    /**\n     * @dev A distinct URI (RFC 3986) for a given NFT.\n     * @param _tokenId Id for which we want uri.\n     * @return URI of _tokenId.\n     */\n    function tokenURI(uint256 _tokenId) external view validNFToken(_tokenId) returns (string memory) {\n        return draw(_tokenId);\n    }\n\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode.object",
          "evm.deployedBytecode.object",
          "metadata"
        ]
      }
    }
  }
}
