{
  "address": "0xF5f1980e3144B3B30B51784A7F3148B1Aa8B7b0a",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "string",
          "name": "baseUriInput",
          "type": "string"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "operator",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "bool",
          "name": "approved",
          "type": "bool"
        }
      ],
      "name": "ApprovalForAll",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "string",
          "name": "newBaseURI",
          "type": "string"
        }
      ],
      "name": "BaseURISet",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "previousAdminRole",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "newAdminRole",
          "type": "bytes32"
        }
      ],
      "name": "RoleAdminChanged",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "sender",
          "type": "address"
        }
      ],
      "name": "RoleGranted",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "sender",
          "type": "address"
        }
      ],
      "name": "RoleRevoked",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "RoleSetup",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "ids",
          "type": "uint256[]"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "amounts",
          "type": "uint256[]"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "uuid",
          "type": "uint256[]"
        }
      ],
      "name": "TokenBatchMinted",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "uuid",
          "type": "uint256"
        }
      ],
      "name": "TokenMinted",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "string",
          "name": "name",
          "type": "string"
        }
      ],
      "name": "TokenNameSet",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "operator",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "ids",
          "type": "uint256[]"
        },
        {
          "indexed": false,
          "internalType": "uint256[]",
          "name": "values",
          "type": "uint256[]"
        }
      ],
      "name": "TransferBatch",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "operator",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        }
      ],
      "name": "TransferSingle",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "string",
          "name": "value",
          "type": "string"
        },
        {
          "indexed": true,
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        }
      ],
      "name": "URI",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "ADMIN_ROLE",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "DEFAULT_ADMIN_ROLE",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "MINTER_ROLE",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "UPDATER_ROLE",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "name": "accountTokenUUIDs",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        }
      ],
      "name": "balanceOf",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "accounts",
          "type": "address[]"
        },
        {
          "internalType": "uint256[]",
          "name": "ids",
          "type": "uint256[]"
        }
      ],
      "name": "balanceOfBatch",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "baseURI",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address[]",
          "name": "toAddresses",
          "type": "address[]"
        },
        {
          "internalType": "uint256[]",
          "name": "ids",
          "type": "uint256[]"
        },
        {
          "internalType": "uint256[]",
          "name": "uuids",
          "type": "uint256[]"
        }
      ],
      "name": "batchMint",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        }
      ],
      "name": "getAccountTokenUUIDs",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getAllTokenIdMetadata",
      "outputs": [
        {
          "components": [
            {
              "internalType": "uint256",
              "name": "tokenId",
              "type": "uint256"
            },
            {
              "components": [
                {
                  "internalType": "string",
                  "name": "name",
                  "type": "string"
                },
                {
                  "internalType": "string",
                  "name": "image",
                  "type": "string"
                },
                {
                  "internalType": "string",
                  "name": "description",
                  "type": "string"
                }
              ],
              "internalType": "struct DataPointsMulti.TokenMetadata",
              "name": "metadata",
              "type": "tuple"
            }
          ],
          "internalType": "struct DataPointsMulti.TokenIdMetadata[]",
          "name": "",
          "type": "tuple[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        }
      ],
      "name": "getRoleAdmin",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        }
      ],
      "name": "getTokenName",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "user",
          "type": "address"
        }
      ],
      "name": "getUserBalances",
      "outputs": [
        {
          "components": [
            {
              "internalType": "string",
              "name": "tokenName",
              "type": "string"
            },
            {
              "internalType": "uint256",
              "name": "balance",
              "type": "uint256"
            }
          ],
          "internalType": "struct DataPointsMulti.TokenBalance[]",
          "name": "",
          "type": "tuple[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "getValidTokenIds",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "grantRole",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "hasRole",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "operator",
          "type": "address"
        }
      ],
      "name": "isApprovedForAll",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "tokenId",
          "type": "uint256"
        }
      ],
      "name": "isTokenIdValid",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "renounceRole",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "revokeRole",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        },
        {
          "internalType": "uint256[]",
          "name": "",
          "type": "uint256[]"
        },
        {
          "internalType": "uint256[]",
          "name": "",
          "type": "uint256[]"
        },
        {
          "internalType": "bytes",
          "name": "",
          "type": "bytes"
        }
      ],
      "name": "safeBatchTransferFrom",
      "outputs": [],
      "stateMutability": "pure",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        },
        {
          "internalType": "bytes",
          "name": "",
          "type": "bytes"
        }
      ],
      "name": "safeTransferFrom",
      "outputs": [],
      "stateMutability": "pure",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "operator",
          "type": "address"
        },
        {
          "internalType": "bool",
          "name": "approved",
          "type": "bool"
        }
      ],
      "name": "setApprovalForAll",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "string",
          "name": "newBaseURI",
          "type": "string"
        }
      ],
      "name": "setBaseURI",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "tokenId",
          "type": "uint256"
        },
        {
          "internalType": "string",
          "name": "name",
          "type": "string"
        },
        {
          "internalType": "string",
          "name": "image",
          "type": "string"
        },
        {
          "internalType": "string",
          "name": "description",
          "type": "string"
        }
      ],
      "name": "setTokenMetadata",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "id",
          "type": "uint256"
        },
        {
          "internalType": "string",
          "name": "name",
          "type": "string"
        }
      ],
      "name": "setTokenName",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes32",
          "name": "role",
          "type": "bytes32"
        },
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "setupRole",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "bytes4",
          "name": "interfaceId",
          "type": "bytes4"
        }
      ],
      "name": "supportsInterface",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "name": "tokenMetadata",
      "outputs": [
        {
          "internalType": "string",
          "name": "name",
          "type": "string"
        },
        {
          "internalType": "string",
          "name": "image",
          "type": "string"
        },
        {
          "internalType": "string",
          "name": "description",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "tokenTypeCount",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "tokenId",
          "type": "uint256"
        }
      ],
      "name": "uri",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "name": "validTokenIds",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    }
  ],
  "transactionHash": "0x4935c16fb0e33aeeaa6f19bf81e3ec8f456fc54abc167b426ff4551642f374da",
  "receipt": {
    "to": null,
    "from": "0x55b474AD9f1139FdDA39fD89b0C3c1B74cEc01B2",
    "contractAddress": "0xF5f1980e3144B3B30B51784A7F3148B1Aa8B7b0a",
    "transactionIndex": 0,
    "gasUsed": "2960867",
    "logsBloom": "0x00000004000000000820000000000000080000100000000000000000000000000000000000004000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000020000400000000000040800000000000000000800000000001000000000000000000000000000080000004000000000000000000000000000000000000000000000000000000000010000000000000000000000001000000000000000000000000000000000000000000000001000000000400100020000000020000000000000000000000000000000400000000000000000000000000000000000",
    "blockHash": "0x3d019e01fdd4b3fe9804e8a7af464c2b5c4fbf8cab1a5beef84ed4baa20cacdf",
    "transactionHash": "0x4935c16fb0e33aeeaa6f19bf81e3ec8f456fc54abc167b426ff4551642f374da",
    "logs": [
      {
        "transactionIndex": 0,
        "blockNumber": 115496,
        "transactionHash": "0x4935c16fb0e33aeeaa6f19bf81e3ec8f456fc54abc167b426ff4551642f374da",
        "address": "0xF5f1980e3144B3B30B51784A7F3148B1Aa8B7b0a",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0x00000000000000000000000055b474ad9f1139fdda39fd89b0c3c1b74cec01b2",
          "0x00000000000000000000000055b474ad9f1139fdda39fd89b0c3c1b74cec01b2"
        ],
        "data": "0x",
        "logIndex": 0,
        "blockHash": "0x3d019e01fdd4b3fe9804e8a7af464c2b5c4fbf8cab1a5beef84ed4baa20cacdf"
      },
      {
        "transactionIndex": 0,
        "blockNumber": 115496,
        "transactionHash": "0x4935c16fb0e33aeeaa6f19bf81e3ec8f456fc54abc167b426ff4551642f374da",
        "address": "0xF5f1980e3144B3B30B51784A7F3148B1Aa8B7b0a",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0xa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775",
          "0x00000000000000000000000055b474ad9f1139fdda39fd89b0c3c1b74cec01b2",
          "0x00000000000000000000000055b474ad9f1139fdda39fd89b0c3c1b74cec01b2"
        ],
        "data": "0x",
        "logIndex": 1,
        "blockHash": "0x3d019e01fdd4b3fe9804e8a7af464c2b5c4fbf8cab1a5beef84ed4baa20cacdf"
      },
      {
        "transactionIndex": 0,
        "blockNumber": 115496,
        "transactionHash": "0x4935c16fb0e33aeeaa6f19bf81e3ec8f456fc54abc167b426ff4551642f374da",
        "address": "0xF5f1980e3144B3B30B51784A7F3148B1Aa8B7b0a",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6",
          "0x00000000000000000000000055b474ad9f1139fdda39fd89b0c3c1b74cec01b2",
          "0x00000000000000000000000055b474ad9f1139fdda39fd89b0c3c1b74cec01b2"
        ],
        "data": "0x",
        "logIndex": 2,
        "blockHash": "0x3d019e01fdd4b3fe9804e8a7af464c2b5c4fbf8cab1a5beef84ed4baa20cacdf"
      },
      {
        "transactionIndex": 0,
        "blockNumber": 115496,
        "transactionHash": "0x4935c16fb0e33aeeaa6f19bf81e3ec8f456fc54abc167b426ff4551642f374da",
        "address": "0xF5f1980e3144B3B30B51784A7F3148B1Aa8B7b0a",
        "topics": [
          "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
          "0x73e573f9566d61418a34d5de3ff49360f9c51fec37f7486551670290f6285dab",
          "0x00000000000000000000000055b474ad9f1139fdda39fd89b0c3c1b74cec01b2",
          "0x00000000000000000000000055b474ad9f1139fdda39fd89b0c3c1b74cec01b2"
        ],
        "data": "0x",
        "logIndex": 3,
        "blockHash": "0x3d019e01fdd4b3fe9804e8a7af464c2b5c4fbf8cab1a5beef84ed4baa20cacdf"
      },
      {
        "transactionIndex": 0,
        "blockNumber": 115496,
        "transactionHash": "0x4935c16fb0e33aeeaa6f19bf81e3ec8f456fc54abc167b426ff4551642f374da",
        "address": "0xF5f1980e3144B3B30B51784A7F3148B1Aa8B7b0a",
        "topics": [
          "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff",
          "0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0xa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775"
        ],
        "data": "0x",
        "logIndex": 4,
        "blockHash": "0x3d019e01fdd4b3fe9804e8a7af464c2b5c4fbf8cab1a5beef84ed4baa20cacdf"
      },
      {
        "transactionIndex": 0,
        "blockNumber": 115496,
        "transactionHash": "0x4935c16fb0e33aeeaa6f19bf81e3ec8f456fc54abc167b426ff4551642f374da",
        "address": "0xF5f1980e3144B3B30B51784A7F3148B1Aa8B7b0a",
        "topics": [
          "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff",
          "0x73e573f9566d61418a34d5de3ff49360f9c51fec37f7486551670290f6285dab",
          "0x0000000000000000000000000000000000000000000000000000000000000000",
          "0xa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775"
        ],
        "data": "0x",
        "logIndex": 5,
        "blockHash": "0x3d019e01fdd4b3fe9804e8a7af464c2b5c4fbf8cab1a5beef84ed4baa20cacdf"
      }
    ],
    "blockNumber": 115496,
    "cumulativeGasUsed": "2960867",
    "status": 1,
    "byzantium": true
  },
  "args": [
    ""
  ],
  "numDeployments": 1,
  "solcInputHash": "d4705c6a0c1f3fa16f3be15aa9651a72",
  "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"baseUriInput\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"newBaseURI\",\"type\":\"string\"}],\"name\":\"BaseURISet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"RoleSetup\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"uuid\",\"type\":\"uint256[]\"}],\"name\":\"TokenBatchMinted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"uuid\",\"type\":\"uint256\"}],\"name\":\"TokenMinted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"TokenNameSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPDATER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountTokenUUIDs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"toAddresses\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"uuids\",\"type\":\"uint256[]\"}],\"name\":\"batchMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getAccountTokenUUIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllTokenIdMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"image\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"internalType\":\"struct DataPointsMulti.TokenMetadata\",\"name\":\"metadata\",\"type\":\"tuple\"}],\"internalType\":\"struct DataPointsMulti.TokenIdMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getTokenName\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"getUserBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"tokenName\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"internalType\":\"struct DataPointsMulti.TokenBalance[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getValidTokenIds\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"isTokenIdValid\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"newBaseURI\",\"type\":\"string\"}],\"name\":\"setBaseURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"image\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"name\":\"setTokenMetadata\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"setTokenName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"setupRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"tokenMetadata\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"image\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenTypeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"validTokenIds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"This contract extends ERC1155 to create a multi-token contract, named DataPointsMulti, intended to represent accumulated data points within the Masa Network. Each token ID represents a different data type, and it features minting and burning capabilities, with distinct roles for each action, as well as an admin role for role management. The tokens are non-transferable, meaning they cannot be transferred between addresses once minted, making them purely a representation of earned points rather than a tradable asset. The contract utilizes OpenZeppelin's ERC1155 for the multi-token standard and AccessControl for role-based access control, respectively. It also implements the ERC1155 URI mechanism to provide on-chain metadata for each token type.\",\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call:   - if using `revokeRole`, it is the admin role bearer   - if using `renounceRole`, it is the role bearer (i.e. `account`)\"},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"}},\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"details\":\"See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address.\"},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length.\"},\"batchMint(address[],uint256[],uint256[])\":{\"details\":\"Mint batch of tokens of different types to specified addresses, each with a unique numeric UUID.\",\"params\":{\"ids\":\"An array of token types to mint.\",\"toAddresses\":\"An array of addresses to mint tokens to.\",\"uuids\":\"An array of numeric UUIDs for each token being minted.\"}},\"constructor\":{\"details\":\"Initializes the contract by setting a base URI and configuring roles.\",\"params\":{\"baseUriInput\":\"The initial base URI for token metadata.\"}},\"getAccountTokenUUIDs(address,uint256)\":{\"details\":\"Retrieves the UUIDs for a specific token ID associated with an account.\",\"params\":{\"account\":\"The address of the user to query UUIDs for.\",\"id\":\"The token ID to query UUIDs for.\"},\"returns\":{\"_0\":\"An array of UUIDs for the specified token ID associated with the account.\"}},\"getAllTokenIdMetadata()\":{\"details\":\"Returns an array of structs containing token IDs and their corresponding metadata.\",\"returns\":{\"_0\":\"An array of TokenIdMetadata structs.\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getTokenName(uint256)\":{\"details\":\"Retrieves the name of a given token ID.\",\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The name of the token ID.\"}},\"getUserBalances(address)\":{\"details\":\"Retrieves user balances for all token types.\",\"params\":{\"user\":\"The address of the user to query balances for.\"},\"returns\":{\"_0\":\"An array of TokenBalance structs containing token names and balances.\"}},\"getValidTokenIds()\":{\"details\":\"Public getter to access the array of valid token IDs.\",\"returns\":{\"_0\":\"An array of valid token IDs.\"}},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"Returns `true` if `account` has been granted `role`.\"},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC1155-isApprovedForAll}.\"},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"Prevents token transfers by overriding `safeTransferFrom` and `safeBatchTransferFrom`.\"},\"setApprovalForAll(address,bool)\":{\"details\":\"See {IERC1155-setApprovalForAll}.\"},\"setBaseURI(string)\":{\"details\":\"Updates the base URI used for token metadata. Can only be called by an admin.\",\"params\":{\"newBaseURI\":\"The new base URI to set.\"}},\"setTokenMetadata(uint256,string,string,string)\":{\"details\":\"Sets the metadata for a token ID. Can only be called by an admin.\",\"params\":{\"description\":\"The description for the token.\",\"image\":\"The image URL for the token.\",\"name\":\"The name for the token.\",\"tokenId\":\"The token ID to set metadata for.\"}},\"setTokenName(uint256,string)\":{\"details\":\"Sets the name for a given token ID.\",\"params\":{\"id\":\"The token ID.\",\"name\":\"The name to assign to the token ID. Requires that the caller has the UPDATER_ROLE.\"}},\"setupRole(bytes32,address)\":{\"details\":\"Grant or revoke role permissions dynamically.\",\"params\":{\"account\":\"The address to grant or revoke the role from.\",\"role\":\"The role identifier.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"uri(uint256)\":{\"details\":\"Generates a URI for a given token ID. The URI is a data URI with a JSON-formatted metadata blob. This includes the name, description, and image for the token.\",\"params\":{\"tokenId\":\"The token ID to generate a URI for.\"},\"returns\":{\"_0\":\"The URI string for the given token ID's metadata.\"}}},\"title\":\"DataPointsMulti\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DataPointsMulti.sol\":\"DataPointsMulti\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"details\":{\"constantOptimizer\":true,\"cse\":true,\"deduplicate\":true,\"inliner\":true,\"jumpdestRemover\":true,\"orderLiterals\":true,\"peephole\":true,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":false},\"runs\":1},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/access/AccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IAccessControl.sol\\\";\\nimport \\\"../utils/Context.sol\\\";\\nimport \\\"../utils/Strings.sol\\\";\\nimport \\\"../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Contract module that allows children to implement role-based access\\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\\n * members except through off-chain means by accessing the contract event logs. Some\\n * applications may benefit from on-chain enumerability, for those cases see\\n * {AccessControlEnumerable}.\\n *\\n * Roles are referred to by their `bytes32` identifier. These should be exposed\\n * in the external API and be unique. The best way to achieve this is by\\n * using `public constant` hash digests:\\n *\\n * ```solidity\\n * bytes32 public constant MY_ROLE = keccak256(\\\"MY_ROLE\\\");\\n * ```\\n *\\n * Roles can be used to represent a set of permissions. To restrict access to a\\n * function call, use {hasRole}:\\n *\\n * ```solidity\\n * function foo() public {\\n *     require(hasRole(MY_ROLE, msg.sender));\\n *     ...\\n * }\\n * ```\\n *\\n * Roles can be granted and revoked dynamically via the {grantRole} and\\n * {revokeRole} functions. Each role has an associated admin role, and only\\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\\n *\\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\\n * that only accounts with this role will be able to grant or revoke other\\n * roles. More complex role relationships can be created by using\\n * {_setRoleAdmin}.\\n *\\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\\n * grant and revoke this role. Extra precautions should be taken to secure\\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\\n * to enforce additional security measures for this role.\\n */\\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\\n    struct RoleData {\\n        mapping(address => bool) members;\\n        bytes32 adminRole;\\n    }\\n\\n    mapping(bytes32 => RoleData) private _roles;\\n\\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\\n\\n    /**\\n     * @dev Modifier that checks that an account has a specific role. Reverts\\n     * with a standardized message including the required role.\\n     *\\n     * The format of the revert reason is given by the following regular expression:\\n     *\\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n     *\\n     * _Available since v4.1._\\n     */\\n    modifier onlyRole(bytes32 role) {\\n        _checkRole(role);\\n        _;\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\\n    }\\n\\n    /**\\n     * @dev Returns `true` if `account` has been granted `role`.\\n     */\\n    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\\n        return _roles[role].members[account];\\n    }\\n\\n    /**\\n     * @dev Revert with a standard message if `_msgSender()` is missing `role`.\\n     * Overriding this function changes the behavior of the {onlyRole} modifier.\\n     *\\n     * Format of the revert message is described in {_checkRole}.\\n     *\\n     * _Available since v4.6._\\n     */\\n    function _checkRole(bytes32 role) internal view virtual {\\n        _checkRole(role, _msgSender());\\n    }\\n\\n    /**\\n     * @dev Revert with a standard message if `account` is missing `role`.\\n     *\\n     * The format of the revert reason is given by the following regular expression:\\n     *\\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\\n     */\\n    function _checkRole(bytes32 role, address account) internal view virtual {\\n        if (!hasRole(role, account)) {\\n            revert(\\n                string(\\n                    abi.encodePacked(\\n                        \\\"AccessControl: account \\\",\\n                        Strings.toHexString(account),\\n                        \\\" is missing role \\\",\\n                        Strings.toHexString(uint256(role), 32)\\n                    )\\n                )\\n            );\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\\n     * {revokeRole}.\\n     *\\n     * To change a role's admin, use {_setRoleAdmin}.\\n     */\\n    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\\n        return _roles[role].adminRole;\\n    }\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     *\\n     * May emit a {RoleGranted} event.\\n     */\\n    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n        _grantRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Revokes `role` from `account`.\\n     *\\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     *\\n     * May emit a {RoleRevoked} event.\\n     */\\n    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\\n        _revokeRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Revokes `role` from the calling account.\\n     *\\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n     * purpose is to provide a mechanism for accounts to lose their privileges\\n     * if they are compromised (such as when a trusted device is misplaced).\\n     *\\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must be `account`.\\n     *\\n     * May emit a {RoleRevoked} event.\\n     */\\n    function renounceRole(bytes32 role, address account) public virtual override {\\n        require(account == _msgSender(), \\\"AccessControl: can only renounce roles for self\\\");\\n\\n        _revokeRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\\n     * event. Note that unlike {grantRole}, this function doesn't perform any\\n     * checks on the calling account.\\n     *\\n     * May emit a {RoleGranted} event.\\n     *\\n     * [WARNING]\\n     * ====\\n     * This function should only be called from the constructor when setting\\n     * up the initial roles for the system.\\n     *\\n     * Using this function in any other way is effectively circumventing the admin\\n     * system imposed by {AccessControl}.\\n     * ====\\n     *\\n     * NOTE: This function is deprecated in favor of {_grantRole}.\\n     */\\n    function _setupRole(bytes32 role, address account) internal virtual {\\n        _grantRole(role, account);\\n    }\\n\\n    /**\\n     * @dev Sets `adminRole` as ``role``'s admin role.\\n     *\\n     * Emits a {RoleAdminChanged} event.\\n     */\\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\\n        bytes32 previousAdminRole = getRoleAdmin(role);\\n        _roles[role].adminRole = adminRole;\\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\\n    }\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * Internal function without access restriction.\\n     *\\n     * May emit a {RoleGranted} event.\\n     */\\n    function _grantRole(bytes32 role, address account) internal virtual {\\n        if (!hasRole(role, account)) {\\n            _roles[role].members[account] = true;\\n            emit RoleGranted(role, account, _msgSender());\\n        }\\n    }\\n\\n    /**\\n     * @dev Revokes `role` from `account`.\\n     *\\n     * Internal function without access restriction.\\n     *\\n     * May emit a {RoleRevoked} event.\\n     */\\n    function _revokeRole(bytes32 role, address account) internal virtual {\\n        if (hasRole(role, account)) {\\n            _roles[role].members[account] = false;\\n            emit RoleRevoked(role, account, _msgSender());\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x0dd6e52cb394d7f5abe5dca2d4908a6be40417914720932de757de34a99ab87f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n    /**\\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n     *\\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n     * {RoleAdminChanged} not being emitted signaling this.\\n     *\\n     * _Available since v3.1._\\n     */\\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n    /**\\n     * @dev Emitted when `account` is granted `role`.\\n     *\\n     * `sender` is the account that originated the contract call, an admin role\\n     * bearer except when using {AccessControl-_setupRole}.\\n     */\\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n    /**\\n     * @dev Emitted when `account` is revoked `role`.\\n     *\\n     * `sender` is the account that originated the contract call:\\n     *   - if using `revokeRole`, it is the admin role bearer\\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n     */\\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n    /**\\n     * @dev Returns `true` if `account` has been granted `role`.\\n     */\\n    function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n    /**\\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\\n     * {revokeRole}.\\n     *\\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n     */\\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n    /**\\n     * @dev Grants `role` to `account`.\\n     *\\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     */\\n    function grantRole(bytes32 role, address account) external;\\n\\n    /**\\n     * @dev Revokes `role` from `account`.\\n     *\\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must have ``role``'s admin role.\\n     */\\n    function revokeRole(bytes32 role, address account) external;\\n\\n    /**\\n     * @dev Revokes `role` from the calling account.\\n     *\\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n     * purpose is to provide a mechanism for accounts to lose their privileges\\n     * if they are compromised (such as when a trusted device is misplaced).\\n     *\\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\\n     * event.\\n     *\\n     * Requirements:\\n     *\\n     * - the caller must be `account`.\\n     */\\n    function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/ERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC1155.sol\\\";\\nimport \\\"./IERC1155Receiver.sol\\\";\\nimport \\\"./extensions/IERC1155MetadataURI.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the basic standard multi-token.\\n * See https://eips.ethereum.org/EIPS/eip-1155\\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\\n *\\n * _Available since v3.1._\\n */\\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\\n    using Address for address;\\n\\n    // Mapping from token ID to account balances\\n    mapping(uint256 => mapping(address => uint256)) private _balances;\\n\\n    // Mapping from account to operator approvals\\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n    // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\\n    string private _uri;\\n\\n    /**\\n     * @dev See {_setURI}.\\n     */\\n    constructor(string memory uri_) {\\n        _setURI(uri_);\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n        return\\n            interfaceId == type(IERC1155).interfaceId ||\\n            interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n            super.supportsInterface(interfaceId);\\n    }\\n\\n    /**\\n     * @dev See {IERC1155MetadataURI-uri}.\\n     *\\n     * This implementation returns the same URI for *all* token types. It relies\\n     * on the token type ID substitution mechanism\\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n     *\\n     * Clients calling this function must replace the `\\\\{id\\\\}` substring with the\\n     * actual token type ID.\\n     */\\n    function uri(uint256) public view virtual override returns (string memory) {\\n        return _uri;\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-balanceOf}.\\n     *\\n     * Requirements:\\n     *\\n     * - `account` cannot be the zero address.\\n     */\\n    function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\\n        require(account != address(0), \\\"ERC1155: address zero is not a valid owner\\\");\\n        return _balances[id][account];\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-balanceOfBatch}.\\n     *\\n     * Requirements:\\n     *\\n     * - `accounts` and `ids` must have the same length.\\n     */\\n    function balanceOfBatch(\\n        address[] memory accounts,\\n        uint256[] memory ids\\n    ) public view virtual override returns (uint256[] memory) {\\n        require(accounts.length == ids.length, \\\"ERC1155: accounts and ids length mismatch\\\");\\n\\n        uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n        for (uint256 i = 0; i < accounts.length; ++i) {\\n            batchBalances[i] = balanceOf(accounts[i], ids[i]);\\n        }\\n\\n        return batchBalances;\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-setApprovalForAll}.\\n     */\\n    function setApprovalForAll(address operator, bool approved) public virtual override {\\n        _setApprovalForAll(_msgSender(), operator, approved);\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-isApprovedForAll}.\\n     */\\n    function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\\n        return _operatorApprovals[account][operator];\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-safeTransferFrom}.\\n     */\\n    function safeTransferFrom(\\n        address from,\\n        address to,\\n        uint256 id,\\n        uint256 amount,\\n        bytes memory data\\n    ) public virtual override {\\n        require(\\n            from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n            \\\"ERC1155: caller is not token owner or approved\\\"\\n        );\\n        _safeTransferFrom(from, to, id, amount, data);\\n    }\\n\\n    /**\\n     * @dev See {IERC1155-safeBatchTransferFrom}.\\n     */\\n    function safeBatchTransferFrom(\\n        address from,\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) public virtual override {\\n        require(\\n            from == _msgSender() || isApprovedForAll(from, _msgSender()),\\n            \\\"ERC1155: caller is not token owner or approved\\\"\\n        );\\n        _safeBatchTransferFrom(from, to, ids, amounts, data);\\n    }\\n\\n    /**\\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n     *\\n     * Emits a {TransferSingle} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n     * acceptance magic value.\\n     */\\n    function _safeTransferFrom(\\n        address from,\\n        address to,\\n        uint256 id,\\n        uint256 amount,\\n        bytes memory data\\n    ) internal virtual {\\n        require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n        address operator = _msgSender();\\n        uint256[] memory ids = _asSingletonArray(id);\\n        uint256[] memory amounts = _asSingletonArray(amount);\\n\\n        _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n        uint256 fromBalance = _balances[id][from];\\n        require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n        unchecked {\\n            _balances[id][from] = fromBalance - amount;\\n        }\\n        _balances[id][to] += amount;\\n\\n        emit TransferSingle(operator, from, to, id, amount);\\n\\n        _afterTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\\n    }\\n\\n    /**\\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\\n     *\\n     * Emits a {TransferBatch} event.\\n     *\\n     * Requirements:\\n     *\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n     * acceptance magic value.\\n     */\\n    function _safeBatchTransferFrom(\\n        address from,\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) internal virtual {\\n        require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n        require(to != address(0), \\\"ERC1155: transfer to the zero address\\\");\\n\\n        address operator = _msgSender();\\n\\n        _beforeTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n        for (uint256 i = 0; i < ids.length; ++i) {\\n            uint256 id = ids[i];\\n            uint256 amount = amounts[i];\\n\\n            uint256 fromBalance = _balances[id][from];\\n            require(fromBalance >= amount, \\\"ERC1155: insufficient balance for transfer\\\");\\n            unchecked {\\n                _balances[id][from] = fromBalance - amount;\\n            }\\n            _balances[id][to] += amount;\\n        }\\n\\n        emit TransferBatch(operator, from, to, ids, amounts);\\n\\n        _afterTokenTransfer(operator, from, to, ids, amounts, data);\\n\\n        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\\n    }\\n\\n    /**\\n     * @dev Sets a new URI for all token types, by relying on the token type ID\\n     * substitution mechanism\\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\\n     *\\n     * By this mechanism, any occurrence of the `\\\\{id\\\\}` substring in either the\\n     * URI or any of the amounts in the JSON file at said URI will be replaced by\\n     * clients with the token type ID.\\n     *\\n     * For example, the `https://token-cdn-domain/\\\\{id\\\\}.json` URI would be\\n     * interpreted by clients as\\n     * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\\n     * for token type ID 0x4cce0.\\n     *\\n     * See {uri}.\\n     *\\n     * Because these URIs cannot be meaningfully represented by the {URI} event,\\n     * this function emits no events.\\n     */\\n    function _setURI(string memory newuri) internal virtual {\\n        _uri = newuri;\\n    }\\n\\n    /**\\n     * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\\n     *\\n     * Emits a {TransferSingle} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n     * acceptance magic value.\\n     */\\n    function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual {\\n        require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n\\n        address operator = _msgSender();\\n        uint256[] memory ids = _asSingletonArray(id);\\n        uint256[] memory amounts = _asSingletonArray(amount);\\n\\n        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n        _balances[id][to] += amount;\\n        emit TransferSingle(operator, address(0), to, id, amount);\\n\\n        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n        _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\\n    }\\n\\n    /**\\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\\n     *\\n     * Emits a {TransferBatch} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `ids` and `amounts` must have the same length.\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n     * acceptance magic value.\\n     */\\n    function _mintBatch(\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) internal virtual {\\n        require(to != address(0), \\\"ERC1155: mint to the zero address\\\");\\n        require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n        address operator = _msgSender();\\n\\n        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n        for (uint256 i = 0; i < ids.length; i++) {\\n            _balances[ids[i]][to] += amounts[i];\\n        }\\n\\n        emit TransferBatch(operator, address(0), to, ids, amounts);\\n\\n        _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\\n\\n        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\\n    }\\n\\n    /**\\n     * @dev Destroys `amount` tokens of token type `id` from `from`\\n     *\\n     * Emits a {TransferSingle} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `from` cannot be the zero address.\\n     * - `from` must have at least `amount` tokens of token type `id`.\\n     */\\n    function _burn(address from, uint256 id, uint256 amount) internal virtual {\\n        require(from != address(0), \\\"ERC1155: burn from the zero address\\\");\\n\\n        address operator = _msgSender();\\n        uint256[] memory ids = _asSingletonArray(id);\\n        uint256[] memory amounts = _asSingletonArray(amount);\\n\\n        _beforeTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n\\n        uint256 fromBalance = _balances[id][from];\\n        require(fromBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n        unchecked {\\n            _balances[id][from] = fromBalance - amount;\\n        }\\n\\n        emit TransferSingle(operator, from, address(0), id, amount);\\n\\n        _afterTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\\n     *\\n     * Emits a {TransferBatch} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `ids` and `amounts` must have the same length.\\n     */\\n    function _burnBatch(address from, uint256[] memory ids, uint256[] memory amounts) internal virtual {\\n        require(from != address(0), \\\"ERC1155: burn from the zero address\\\");\\n        require(ids.length == amounts.length, \\\"ERC1155: ids and amounts length mismatch\\\");\\n\\n        address operator = _msgSender();\\n\\n        _beforeTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n\\n        for (uint256 i = 0; i < ids.length; i++) {\\n            uint256 id = ids[i];\\n            uint256 amount = amounts[i];\\n\\n            uint256 fromBalance = _balances[id][from];\\n            require(fromBalance >= amount, \\\"ERC1155: burn amount exceeds balance\\\");\\n            unchecked {\\n                _balances[id][from] = fromBalance - amount;\\n            }\\n        }\\n\\n        emit TransferBatch(operator, from, address(0), ids, amounts);\\n\\n        _afterTokenTransfer(operator, from, address(0), ids, amounts, \\\"\\\");\\n    }\\n\\n    /**\\n     * @dev Approve `operator` to operate on all of `owner` tokens\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     */\\n    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n        require(owner != operator, \\\"ERC1155: setting approval status for self\\\");\\n        _operatorApprovals[owner][operator] = approved;\\n        emit ApprovalForAll(owner, operator, approved);\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any token transfer. This includes minting\\n     * and burning, as well as batched variants.\\n     *\\n     * The same hook is called on both single and batched variants. For single\\n     * transfers, the length of the `ids` and `amounts` arrays will be 1.\\n     *\\n     * Calling conditions (for each `id` and `amount` pair):\\n     *\\n     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n     * of token type `id` will be  transferred to `to`.\\n     * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n     * for `to`.\\n     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n     * will be burned.\\n     * - `from` and `to` are never both zero.\\n     * - `ids` and `amounts` have the same, non-zero length.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(\\n        address operator,\\n        address from,\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) internal virtual {}\\n\\n    /**\\n     * @dev Hook that is called after any token transfer. This includes minting\\n     * and burning, as well as batched variants.\\n     *\\n     * The same hook is called on both single and batched variants. For single\\n     * transfers, the length of the `id` and `amount` arrays will be 1.\\n     *\\n     * Calling conditions (for each `id` and `amount` pair):\\n     *\\n     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n     * of token type `id` will be  transferred to `to`.\\n     * - When `from` is zero, `amount` tokens of token type `id` will be minted\\n     * for `to`.\\n     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\\n     * will be burned.\\n     * - `from` and `to` are never both zero.\\n     * - `ids` and `amounts` have the same, non-zero length.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _afterTokenTransfer(\\n        address operator,\\n        address from,\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) internal virtual {}\\n\\n    function _doSafeTransferAcceptanceCheck(\\n        address operator,\\n        address from,\\n        address to,\\n        uint256 id,\\n        uint256 amount,\\n        bytes memory data\\n    ) private {\\n        if (to.isContract()) {\\n            try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\\n                if (response != IERC1155Receiver.onERC1155Received.selector) {\\n                    revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n                }\\n            } catch Error(string memory reason) {\\n                revert(reason);\\n            } catch {\\n                revert(\\\"ERC1155: transfer to non-ERC1155Receiver implementer\\\");\\n            }\\n        }\\n    }\\n\\n    function _doSafeBatchTransferAcceptanceCheck(\\n        address operator,\\n        address from,\\n        address to,\\n        uint256[] memory ids,\\n        uint256[] memory amounts,\\n        bytes memory data\\n    ) private {\\n        if (to.isContract()) {\\n            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\\n                bytes4 response\\n            ) {\\n                if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\\n                    revert(\\\"ERC1155: ERC1155Receiver rejected tokens\\\");\\n                }\\n            } catch Error(string memory reason) {\\n                revert(reason);\\n            } catch {\\n                revert(\\\"ERC1155: transfer to non-ERC1155Receiver implementer\\\");\\n            }\\n        }\\n    }\\n\\n    function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\\n        uint256[] memory array = new uint256[](1);\\n        array[0] = element;\\n\\n        return array;\\n    }\\n}\\n\",\"keccak256\":\"0x81149353c99ccf8ff18af7701bc3f38665c7a97e344cdc0d27f927f03d22af0e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n    /**\\n     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n     */\\n    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n    /**\\n     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n     * transfers.\\n     */\\n    event TransferBatch(\\n        address indexed operator,\\n        address indexed from,\\n        address indexed to,\\n        uint256[] ids,\\n        uint256[] values\\n    );\\n\\n    /**\\n     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n     * `approved`.\\n     */\\n    event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n    /**\\n     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n     *\\n     * If an {URI} event was emitted for `id`, the standard\\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n     * returned by {IERC1155MetadataURI-uri}.\\n     */\\n    event URI(string value, uint256 indexed id);\\n\\n    /**\\n     * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n     *\\n     * Requirements:\\n     *\\n     * - `account` cannot be the zero address.\\n     */\\n    function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n    /**\\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n     *\\n     * Requirements:\\n     *\\n     * - `accounts` and `ids` must have the same length.\\n     */\\n    function balanceOfBatch(\\n        address[] calldata accounts,\\n        uint256[] calldata ids\\n    ) external view returns (uint256[] memory);\\n\\n    /**\\n     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n     *\\n     * Emits an {ApprovalForAll} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `operator` cannot be the caller.\\n     */\\n    function setApprovalForAll(address operator, bool approved) external;\\n\\n    /**\\n     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n     *\\n     * See {setApprovalForAll}.\\n     */\\n    function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n    /**\\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n     *\\n     * Emits a {TransferSingle} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `to` cannot be the zero address.\\n     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n     * acceptance magic value.\\n     */\\n    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n    /**\\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n     *\\n     * Emits a {TransferBatch} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `ids` and `amounts` must have the same length.\\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n     * acceptance magic value.\\n     */\\n    function safeBatchTransferFrom(\\n        address from,\\n        address to,\\n        uint256[] calldata ids,\\n        uint256[] calldata amounts,\\n        bytes calldata data\\n    ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n    /**\\n     * @dev Handles the receipt of a single ERC1155 token type. This function is\\n     * called at the end of a `safeTransferFrom` after the balance has been updated.\\n     *\\n     * NOTE: To accept the transfer, this must return\\n     * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n     * (i.e. 0xf23a6e61, or its own function selector).\\n     *\\n     * @param operator The address which initiated the transfer (i.e. msg.sender)\\n     * @param from The address which previously owned the token\\n     * @param id The ID of the token being transferred\\n     * @param value The amount of tokens being transferred\\n     * @param data Additional data with no specified format\\n     * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n     */\\n    function onERC1155Received(\\n        address operator,\\n        address from,\\n        uint256 id,\\n        uint256 value,\\n        bytes calldata data\\n    ) external returns (bytes4);\\n\\n    /**\\n     * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n     * is called at the end of a `safeBatchTransferFrom` after the balances have\\n     * been updated.\\n     *\\n     * NOTE: To accept the transfer(s), this must return\\n     * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n     * (i.e. 0xbc197c81, or its own function selector).\\n     *\\n     * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n     * @param from The address which previously owned the token\\n     * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n     * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n     * @param data Additional data with no specified format\\n     * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n     */\\n    function onERC1155BatchReceived(\\n        address operator,\\n        address from,\\n        uint256[] calldata ids,\\n        uint256[] calldata values,\\n        bytes calldata data\\n    ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n    /**\\n     * @dev Returns the URI for token type `id`.\\n     *\\n     * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n     * clients with the actual token type ID.\\n     */\\n    function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xa66d18b9a85458d28fc3304717964502ae36f7f8a2ff35bc83f6f85d74b03574\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n    /**\\n     * @dev Returns true if `account` is a contract.\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * It is unsafe to assume that an address for which this function returns\\n     * false is an externally-owned account (EOA) and not a contract.\\n     *\\n     * Among others, `isContract` will return false for the following\\n     * types of addresses:\\n     *\\n     *  - an externally-owned account\\n     *  - a contract in construction\\n     *  - an address where a contract will be created\\n     *  - an address where a contract lived, but was destroyed\\n     *\\n     * Furthermore, `isContract` will also return true if the target contract within\\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n     * which only has an effect at the end of a transaction.\\n     * ====\\n     *\\n     * [IMPORTANT]\\n     * ====\\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n     *\\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n     * constructor.\\n     * ====\\n     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize/address.code.length, which returns 0\\n        // for contracts in construction, since the code is only stored at the end\\n        // of the constructor execution.\\n\\n        return account.code.length > 0;\\n    }\\n\\n    /**\\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n     * `recipient`, forwarding all available gas and reverting on errors.\\n     *\\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n     * imposed by `transfer`, making them unable to receive funds via\\n     * `transfer`. {sendValue} removes this limitation.\\n     *\\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n     *\\n     * IMPORTANT: because control is transferred to `recipient`, care must be\\n     * taken to not create reentrancy vulnerabilities. Consider using\\n     * {ReentrancyGuard} or the\\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n     */\\n    function sendValue(address payable recipient, uint256 amount) internal {\\n        require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n        (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n        require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n    }\\n\\n    /**\\n     * @dev Performs a Solidity function call using a low level `call`. A\\n     * plain `call` is an unsafe replacement for a function call: use this\\n     * function instead.\\n     *\\n     * If `target` reverts with a revert reason, it is bubbled up by this\\n     * function (like regular Solidity function calls).\\n     *\\n     * Returns the raw returned data. To convert to the expected return value,\\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n     *\\n     * Requirements:\\n     *\\n     * - `target` must be a contract.\\n     * - calling `target` with `data` must not revert.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n     * `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, 0, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but also transferring `value` wei to `target`.\\n     *\\n     * Requirements:\\n     *\\n     * - the calling contract must have an ETH balance of at least `value`.\\n     * - the called Solidity function must be `payable`.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n        return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function functionCallWithValue(\\n        address target,\\n        bytes memory data,\\n        uint256 value,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n        return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a static call.\\n     *\\n     * _Available since v3.3._\\n     */\\n    function functionStaticCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal view returns (bytes memory) {\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n        return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n    }\\n\\n    /**\\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n     * but performing a delegate call.\\n     *\\n     * _Available since v3.4._\\n     */\\n    function functionDelegateCall(\\n        address target,\\n        bytes memory data,\\n        string memory errorMessage\\n    ) internal returns (bytes memory) {\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n     *\\n     * _Available since v4.8._\\n     */\\n    function verifyCallResultFromTarget(\\n        address target,\\n        bool success,\\n        bytes memory returndata,\\n        string memory errorMessage\\n    ) internal view returns (bytes memory) {\\n        if (success) {\\n            if (returndata.length == 0) {\\n                // only check isContract if the call was successful and the return data is empty\\n                // otherwise we already know that it was a contract\\n                require(isContract(target), \\\"Address: call to non-contract\\\");\\n            }\\n            return returndata;\\n        } else {\\n            _revert(returndata, errorMessage);\\n        }\\n    }\\n\\n    /**\\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n     * revert reason or using the provided one.\\n     *\\n     * _Available since v4.3._\\n     */\\n    function verifyCallResult(\\n        bool success,\\n        bytes memory returndata,\\n        string memory errorMessage\\n    ) internal pure returns (bytes memory) {\\n        if (success) {\\n            return returndata;\\n        } else {\\n            _revert(returndata, errorMessage);\\n        }\\n    }\\n\\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n        // Look for revert reason and bubble it up if present\\n        if (returndata.length > 0) {\\n            // The easiest way to bubble the revert reason is using memory via assembly\\n            /// @solidity memory-safe-assembly\\n            assembly {\\n                let returndata_size := mload(returndata)\\n                revert(add(32, returndata), returndata_size)\\n            }\\n        } else {\\n            revert(errorMessage);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n    function _msgSender() internal view virtual returns (address) {\\n        return msg.sender;\\n    }\\n\\n    function _msgData() internal view virtual returns (bytes calldata) {\\n        return msg.data;\\n    }\\n\\n    function _contextSuffixLength() internal view virtual returns (uint256) {\\n        return 0;\\n    }\\n}\\n\",\"keccak256\":\"0xa92e4fa126feb6907daa0513ddd816b2eb91f30a808de54f63c17d0e162c3439\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n    bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n    uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n     */\\n    function toString(uint256 value) internal pure returns (string memory) {\\n        unchecked {\\n            uint256 length = Math.log10(value) + 1;\\n            string memory buffer = new string(length);\\n            uint256 ptr;\\n            /// @solidity memory-safe-assembly\\n            assembly {\\n                ptr := add(buffer, add(32, length))\\n            }\\n            while (true) {\\n                ptr--;\\n                /// @solidity memory-safe-assembly\\n                assembly {\\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n                }\\n                value /= 10;\\n                if (value == 0) break;\\n            }\\n            return buffer;\\n        }\\n    }\\n\\n    /**\\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n     */\\n    function toString(int256 value) internal pure returns (string memory) {\\n        return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\n    }\\n\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n     */\\n    function toHexString(uint256 value) internal pure returns (string memory) {\\n        unchecked {\\n            return toHexString(value, Math.log256(value) + 1);\\n        }\\n    }\\n\\n    /**\\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n     */\\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n        bytes memory buffer = new bytes(2 * length + 2);\\n        buffer[0] = \\\"0\\\";\\n        buffer[1] = \\\"x\\\";\\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\\n            buffer[i] = _SYMBOLS[value & 0xf];\\n            value >>= 4;\\n        }\\n        require(value == 0, \\\"Strings: hex length insufficient\\\");\\n        return string(buffer);\\n    }\\n\\n    /**\\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n     */\\n    function toHexString(address addr) internal pure returns (string memory) {\\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n    }\\n\\n    /**\\n     * @dev Returns true if the two strings are equal.\\n     */\\n    function equal(string memory a, string memory b) internal pure returns (bool) {\\n        return keccak256(bytes(a)) == keccak256(bytes(b));\\n    }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n        return interfaceId == type(IERC165).interfaceId;\\n    }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n    /**\\n     * @dev Returns true if this contract implements the interface defined by\\n     * `interfaceId`. See the corresponding\\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n     * to learn more about how these ids are created.\\n     *\\n     * This function call must use less than 30 000 gas.\\n     */\\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n    enum Rounding {\\n        Down, // Toward negative infinity\\n        Up, // Toward infinity\\n        Zero // Toward zero\\n    }\\n\\n    /**\\n     * @dev Returns the largest of two numbers.\\n     */\\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a > b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the smallest of two numbers.\\n     */\\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return a < b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the average of two numbers. The result is rounded towards\\n     * zero.\\n     */\\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // (a + b) / 2 can overflow.\\n        return (a & b) + (a ^ b) / 2;\\n    }\\n\\n    /**\\n     * @dev Returns the ceiling of the division of two numbers.\\n     *\\n     * This differs from standard division with `/` in that it rounds up instead\\n     * of rounding down.\\n     */\\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n        // (a + b - 1) / b can overflow on addition, so we distribute.\\n        return a == 0 ? 0 : (a - 1) / b + 1;\\n    }\\n\\n    /**\\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n     * with further edits by Uniswap Labs also under MIT license.\\n     */\\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n        unchecked {\\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n            // variables such that product = prod1 * 2^256 + prod0.\\n            uint256 prod0; // Least significant 256 bits of the product\\n            uint256 prod1; // Most significant 256 bits of the product\\n            assembly {\\n                let mm := mulmod(x, y, not(0))\\n                prod0 := mul(x, y)\\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n            }\\n\\n            // Handle non-overflow cases, 256 by 256 division.\\n            if (prod1 == 0) {\\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n                // The surrounding unchecked block does not change this fact.\\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n                return prod0 / denominator;\\n            }\\n\\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n            require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\n\\n            ///////////////////////////////////////////////\\n            // 512 by 256 division.\\n            ///////////////////////////////////////////////\\n\\n            // Make division exact by subtracting the remainder from [prod1 prod0].\\n            uint256 remainder;\\n            assembly {\\n                // Compute remainder using mulmod.\\n                remainder := mulmod(x, y, denominator)\\n\\n                // Subtract 256 bit number from 512 bit number.\\n                prod1 := sub(prod1, gt(remainder, prod0))\\n                prod0 := sub(prod0, remainder)\\n            }\\n\\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n            // See https://cs.stackexchange.com/q/138556/92363.\\n\\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\\n            uint256 twos = denominator & (~denominator + 1);\\n            assembly {\\n                // Divide denominator by twos.\\n                denominator := div(denominator, twos)\\n\\n                // Divide [prod1 prod0] by twos.\\n                prod0 := div(prod0, twos)\\n\\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n                twos := add(div(sub(0, twos), twos), 1)\\n            }\\n\\n            // Shift in bits from prod1 into prod0.\\n            prod0 |= prod1 * twos;\\n\\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n            // four bits. That is, denominator * inv = 1 mod 2^4.\\n            uint256 inverse = (3 * denominator) ^ 2;\\n\\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n            // in modular arithmetic, doubling the correct bits in each step.\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n            // is no longer required.\\n            result = prod0 * inverse;\\n            return result;\\n        }\\n    }\\n\\n    /**\\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n     */\\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n        uint256 result = mulDiv(x, y, denominator);\\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n            result += 1;\\n        }\\n        return result;\\n    }\\n\\n    /**\\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n     *\\n     * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n     */\\n    function sqrt(uint256 a) internal pure returns (uint256) {\\n        if (a == 0) {\\n            return 0;\\n        }\\n\\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n        //\\n        // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n        //\\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n        // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n        // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n        //\\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n        uint256 result = 1 << (log2(a) >> 1);\\n\\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n        // into the expected uint128 result.\\n        unchecked {\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            result = (result + a / result) >> 1;\\n            return min(result, a / result);\\n        }\\n    }\\n\\n    /**\\n     * @notice Calculates sqrt(a), following the selected rounding direction.\\n     */\\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n        unchecked {\\n            uint256 result = sqrt(a);\\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev Return the log in base 2, rounded down, of a positive value.\\n     * Returns 0 if given 0.\\n     */\\n    function log2(uint256 value) internal pure returns (uint256) {\\n        uint256 result = 0;\\n        unchecked {\\n            if (value >> 128 > 0) {\\n                value >>= 128;\\n                result += 128;\\n            }\\n            if (value >> 64 > 0) {\\n                value >>= 64;\\n                result += 64;\\n            }\\n            if (value >> 32 > 0) {\\n                value >>= 32;\\n                result += 32;\\n            }\\n            if (value >> 16 > 0) {\\n                value >>= 16;\\n                result += 16;\\n            }\\n            if (value >> 8 > 0) {\\n                value >>= 8;\\n                result += 8;\\n            }\\n            if (value >> 4 > 0) {\\n                value >>= 4;\\n                result += 4;\\n            }\\n            if (value >> 2 > 0) {\\n                value >>= 2;\\n                result += 2;\\n            }\\n            if (value >> 1 > 0) {\\n                result += 1;\\n            }\\n        }\\n        return result;\\n    }\\n\\n    /**\\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n     * Returns 0 if given 0.\\n     */\\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n        unchecked {\\n            uint256 result = log2(value);\\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev Return the log in base 10, rounded down, of a positive value.\\n     * Returns 0 if given 0.\\n     */\\n    function log10(uint256 value) internal pure returns (uint256) {\\n        uint256 result = 0;\\n        unchecked {\\n            if (value >= 10 ** 64) {\\n                value /= 10 ** 64;\\n                result += 64;\\n            }\\n            if (value >= 10 ** 32) {\\n                value /= 10 ** 32;\\n                result += 32;\\n            }\\n            if (value >= 10 ** 16) {\\n                value /= 10 ** 16;\\n                result += 16;\\n            }\\n            if (value >= 10 ** 8) {\\n                value /= 10 ** 8;\\n                result += 8;\\n            }\\n            if (value >= 10 ** 4) {\\n                value /= 10 ** 4;\\n                result += 4;\\n            }\\n            if (value >= 10 ** 2) {\\n                value /= 10 ** 2;\\n                result += 2;\\n            }\\n            if (value >= 10 ** 1) {\\n                result += 1;\\n            }\\n        }\\n        return result;\\n    }\\n\\n    /**\\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n     * Returns 0 if given 0.\\n     */\\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n        unchecked {\\n            uint256 result = log10(value);\\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev Return the log in base 256, rounded down, of a positive value.\\n     * Returns 0 if given 0.\\n     *\\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n     */\\n    function log256(uint256 value) internal pure returns (uint256) {\\n        uint256 result = 0;\\n        unchecked {\\n            if (value >> 128 > 0) {\\n                value >>= 128;\\n                result += 16;\\n            }\\n            if (value >> 64 > 0) {\\n                value >>= 64;\\n                result += 8;\\n            }\\n            if (value >> 32 > 0) {\\n                value >>= 32;\\n                result += 4;\\n            }\\n            if (value >> 16 > 0) {\\n                value >>= 16;\\n                result += 2;\\n            }\\n            if (value >> 8 > 0) {\\n                result += 1;\\n            }\\n        }\\n        return result;\\n    }\\n\\n    /**\\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\\n     * Returns 0 if given 0.\\n     */\\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n        unchecked {\\n            uint256 result = log256(value);\\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n    /**\\n     * @dev Returns the largest of two signed numbers.\\n     */\\n    function max(int256 a, int256 b) internal pure returns (int256) {\\n        return a > b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the smallest of two signed numbers.\\n     */\\n    function min(int256 a, int256 b) internal pure returns (int256) {\\n        return a < b ? a : b;\\n    }\\n\\n    /**\\n     * @dev Returns the average of two signed numbers without overflow.\\n     * The result is rounded towards zero.\\n     */\\n    function average(int256 a, int256 b) internal pure returns (int256) {\\n        // Formula from the book \\\"Hacker's Delight\\\"\\n        int256 x = (a & b) + ((a ^ b) >> 1);\\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\\n    }\\n\\n    /**\\n     * @dev Returns the absolute unsigned value of a signed value.\\n     */\\n    function abs(int256 n) internal pure returns (uint256) {\\n        unchecked {\\n            // must be unchecked in order to support `n = type(int256).min`\\n            return uint256(n >= 0 ? n : -n);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"contracts/DataPointsMulti.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/AccessControl.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport \\\"./lib/base64.sol\\\";\\n\\n/**\\n * @title DataPointsMulti\\n * @dev This contract extends ERC1155 to create a multi-token contract, named DataPointsMulti, intended to represent accumulated data points\\n * within the Masa Network. Each token ID represents a different data type, and it features minting and burning capabilities, with distinct roles\\n * for each action, as well as an admin role for role management. The tokens are non-transferable, meaning they cannot be transferred between\\n * addresses once minted, making them purely a representation of earned points rather than a tradable asset.\\n *\\n * The contract utilizes OpenZeppelin's ERC1155 for the multi-token standard and AccessControl for role-based access control, respectively.\\n * It also implements the ERC1155 URI mechanism to provide on-chain metadata for each token type.\\n */\\ncontract DataPointsMulti is ERC1155, AccessControl {\\n    using Strings for uint256;\\n\\n    // Role definitions for role-based access control\\n    bytes32 public constant MINTER_ROLE = keccak256(\\\"MINTER_ROLE\\\");\\n    bytes32 public constant ADMIN_ROLE = keccak256(\\\"ADMIN_ROLE\\\");\\n    bytes32 public constant UPDATER_ROLE = keccak256(\\\"UPDATER_ROLE\\\");\\n\\n    // Struct for storing token metadata.\\n    struct TokenMetadata {\\n        string name;\\n        string image;\\n        string description;\\n    }\\n\\n    // Define a new struct that includes the token ID and its metadata\\n    struct TokenIdMetadata {\\n        uint256 tokenId;\\n        TokenMetadata metadata;\\n    }\\n\\n    // Struct to hold token balance information.\\n    struct TokenBalance {\\n        string tokenName;\\n        uint256 balance;\\n    }\\n\\n    // Mapping from token ID to its metadata.\\n    mapping(uint256 => TokenMetadata) public tokenMetadata;\\n\\n    // Mapping from address and token ID to an array of UUIDs.\\n    mapping(address => mapping(uint256 => uint256[])) public accountTokenUUIDs;\\n\\n    // Counter for the total number of token types.\\n    uint256 public tokenTypeCount;\\n\\n    // Array of valid token IDs.\\n    uint256[] public validTokenIds;\\n\\n    // Base URI for constructing token URIs.\\n    string public baseURI;\\n\\n    // Events for logging actions on the contract.\\n    event BaseURISet(string newBaseURI);\\n    event TokenMinted(\\n        address account,\\n        uint256 id,\\n        uint256 amount,\\n        uint256 uuid\\n    );\\n    event TokenBatchMinted(\\n        address account,\\n        uint256[] ids,\\n        uint256[] amounts,\\n        uint256[] uuid\\n    );\\n\\n    event TokenNameSet(uint256 id, string name);\\n    event RoleSetup(bytes32 role, address account);\\n\\n    /**\\n     * @dev Initializes the contract by setting a base URI and configuring roles.\\n     * @param baseUriInput The initial base URI for token metadata.\\n     */\\n    constructor(string memory baseUriInput) ERC1155(\\\"\\\") {\\n        baseURI = baseUriInput;\\n\\n        // Grant roles to the contract deployer\\n        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\\n        _setupRole(ADMIN_ROLE, msg.sender);\\n        _setupRole(MINTER_ROLE, msg.sender);\\n        _setupRole(UPDATER_ROLE, msg.sender);\\n\\n        // Configure role hierarchies\\n        _setRoleAdmin(MINTER_ROLE, ADMIN_ROLE);\\n        _setRoleAdmin(UPDATER_ROLE, ADMIN_ROLE);\\n    }\\n\\n    /**\\n     * @dev Updates the base URI used for token metadata. Can only be called by an admin.\\n     * @param newBaseURI The new base URI to set.\\n     */\\n    function setBaseURI(string memory newBaseURI) public onlyRole(ADMIN_ROLE) {\\n        require(\\n            bytes(newBaseURI).length > 0,\\n            \\\"DataPointsMulti: Base URI cannot be empty\\\"\\n        );\\n        baseURI = newBaseURI;\\n        emit BaseURISet(newBaseURI);\\n    }\\n\\n    /**\\n     * @dev Sets the metadata for a token ID. Can only be called by an admin.\\n     * @param tokenId The token ID to set metadata for.\\n     * @param name The name for the token.\\n     * @param image The image URL for the token.\\n     * @param description The description for the token.\\n     */\\n    function setTokenMetadata(\\n        uint256 tokenId,\\n        string memory name,\\n        string memory image,\\n        string memory description\\n    ) public onlyRole(ADMIN_ROLE) {\\n        require(\\n            bytes(name).length > 0,\\n            \\\"DataPointsMulti: Token name cannot be empty\\\"\\n        );\\n        require(\\n            bytes(image).length > 0,\\n            \\\"DataPointsMulti: Token image cannot be empty\\\"\\n        );\\n        require(\\n            bytes(description).length > 0,\\n            \\\"DataPointsMulti: Token description cannot be empty\\\"\\n        );\\n\\n        tokenMetadata[tokenId] = TokenMetadata(name, image, description);\\n    }\\n\\n    /**\\n     * @dev Generates a URI for a given token ID. The URI is a data URI with a JSON-formatted metadata blob.\\n     * This includes the name, description, and image for the token.\\n     * @param tokenId The token ID to generate a URI for.\\n     * @return The URI string for the given token ID's metadata.\\n     */\\n    function uri(uint256 tokenId) public view override returns (string memory) {\\n        require(\\n            bytes(tokenMetadata[tokenId].name).length > 0,\\n            \\\"DataPointsMulti: Token ID does not exist\\\"\\n        );\\n\\n        // Create a JSON blob with the metadata\\n        string memory json = string(\\n            abi.encodePacked(\\n                '{\\\"name\\\": \\\"',\\n                tokenMetadata[tokenId].name,\\n                '\\\", \\\"description\\\": \\\"',\\n                tokenMetadata[tokenId].description,\\n                '\\\", \\\"image\\\": \\\"',\\n                tokenMetadata[tokenId].image,\\n                '\\\"}'\\n            )\\n        );\\n\\n        // Encode the JSON blob as Base64\\n        string memory encodedJson = Base64.encode(bytes(json));\\n\\n        // Return the encoded data as the URI\\n        return\\n            string(\\n                abi.encodePacked(\\\"data:application/json;base64,\\\", encodedJson)\\n            );\\n    }\\n\\n    /**\\n     * @dev Mint batch of tokens of different types to specified addresses, each with a unique numeric UUID.\\n     * @param toAddresses An array of addresses to mint tokens to.\\n     * @param ids An array of token types to mint.\\n     * @param uuids An array of numeric UUIDs for each token being minted.\\n     */\\n\\n    function batchMint(\\n        address[] memory toAddresses,\\n        uint256[] memory ids,\\n        uint256[] memory uuids\\n    ) public onlyRole(MINTER_ROLE) {\\n        require(\\n            toAddresses.length == ids.length && ids.length == uuids.length,\\n            \\\"Must provide equal numbers of addresses, ids, and UUIDs\\\"\\n        );\\n\\n        for (uint256 i = 0; i < toAddresses.length; i++) {\\n            require(isTokenIdValid(ids[i]), \\\"Invalid token ID\\\");\\n            require(uuids[i] != 0, \\\"UUID cannot be zero\\\");\\n            require(\\n                toAddresses[i] != address(0),\\n                \\\"Cannot mint to the zero address\\\"\\n            );\\n\\n            // Update the state variable before the external call\\n            accountTokenUUIDs[toAddresses[i]][ids[i]].push(uuids[i]);\\n\\n            // External call to mint the token\\n            _mint(toAddresses[i], ids[i], 1, \\\"0x00\\\");\\n\\n            emit TokenMinted(toAddresses[i], ids[i], 1, uuids[i]);\\n        }\\n    }\\n\\n    function isTokenIdValid(uint256 tokenId) public view returns (bool) {\\n        // Example validation logic to check if the token ID has been initialized\\n        // This could be checking against a list of validTokenIds or other criteria\\n        // indicating the token ID has been properly set up.\\n        for (uint256 i = 0; i < validTokenIds.length; i++) {\\n            if (validTokenIds[i] == tokenId) {\\n                return true;\\n            }\\n        }\\n        return false;\\n    }\\n\\n    /**\\n     * @dev Sets the name for a given token ID.\\n     * @param id The token ID.\\n     * @param name The name to assign to the token ID.\\n     * Requires that the caller has the UPDATER_ROLE.\\n     */\\n    function setTokenName(\\n        uint256 id,\\n        string memory name\\n    ) public onlyRole(UPDATER_ROLE) {\\n        require(\\n            bytes(name).length > 0,\\n            \\\"DataPointsMulti: Token name cannot be empty\\\"\\n        );\\n\\n        // Check if the token already has metadata set\\n        bool isNewToken = bytes(tokenMetadata[id].name).length == 0;\\n\\n        // Update the token name within the token metadata\\n        tokenMetadata[id].name = name;\\n\\n        // If this is a new token type, add the token ID to the list and increment the token type counter\\n        if (isNewToken) {\\n            validTokenIds.push(id);\\n            tokenTypeCount++;\\n        }\\n\\n        emit TokenNameSet(id, name);\\n    }\\n\\n    /**\\n     * @dev Retrieves the name of a given token ID.\\n     * @param id The token ID.\\n     * @return The name of the token ID.\\n     */\\n    function getTokenName(uint256 id) public view returns (string memory) {\\n        require(\\n            bytes(tokenMetadata[id].name).length != 0,\\n            \\\"DataPointsMulti: Token ID does not exist\\\"\\n        );\\n        return tokenMetadata[id].name;\\n    }\\n\\n    /**\\n     * @dev Grant or revoke role permissions dynamically.\\n     * @param role The role identifier.\\n     * @param account The address to grant or revoke the role from.\\n     */\\n    function setupRole(bytes32 role, address account) public {\\n        require(\\n            hasRole(DEFAULT_ADMIN_ROLE, msg.sender),\\n            \\\"Caller is not an admin\\\"\\n        );\\n        _setupRole(role, account);\\n        emit RoleSetup(role, account);\\n    }\\n\\n    /**\\n     * @dev Prevents token transfers by overriding `safeTransferFrom` and `safeBatchTransferFrom`.\\n     */\\n    function safeTransferFrom(\\n        address,\\n        address,\\n        uint256,\\n        uint256,\\n        bytes memory\\n    ) public pure override {\\n        require(false, \\\"DataPointsMulti: transfer not allowed\\\");\\n    }\\n\\n    function safeBatchTransferFrom(\\n        address,\\n        address,\\n        uint256[] memory,\\n        uint256[] memory,\\n        bytes memory\\n    ) public pure override {\\n        require(false, \\\"DataPointsMulti: batch transfer not allowed\\\");\\n    }\\n\\n    /**\\n     * @dev See {IERC165-supportsInterface}.\\n     */\\n    function supportsInterface(\\n        bytes4 interfaceId\\n    ) public view virtual override(ERC1155, AccessControl) returns (bool) {\\n        return super.supportsInterface(interfaceId);\\n    }\\n\\n    /**\\n     * @dev Retrieves user balances for all token types.\\n     * @param user The address of the user to query balances for.\\n     * @return An array of TokenBalance structs containing token names and balances.\\n     */\\n    function getUserBalances(\\n        address user\\n    ) public view returns (TokenBalance[] memory) {\\n        uint256 length = validTokenIds.length; // Cache the length of the array\\n        TokenBalance[] memory balances = new TokenBalance[](length);\\n\\n        for (uint256 i = 0; i < validTokenIds.length; i++) {\\n            uint256 tokenId = validTokenIds[i];\\n            balances[i].tokenName = tokenMetadata[tokenId].name;\\n            balances[i].balance = balanceOf(user, tokenId);\\n        }\\n\\n        return balances;\\n    }\\n\\n    /**\\n     * @dev Retrieves the UUIDs for a specific token ID associated with an account.\\n     * @param account The address of the user to query UUIDs for.\\n     * @param id The token ID to query UUIDs for.\\n     * @return An array of UUIDs for the specified token ID associated with the account.\\n     */\\n    function getAccountTokenUUIDs(\\n        address account,\\n        uint256 id\\n    ) public view returns (uint256[] memory) {\\n        return accountTokenUUIDs[account][id];\\n    }\\n\\n    /**\\n     * @dev Public getter to access the array of valid token IDs.\\n     * @return An array of valid token IDs.\\n     */\\n    function getValidTokenIds() public view returns (uint256[] memory) {\\n        return validTokenIds;\\n    }\\n\\n    /**\\n     * @dev Returns an array of structs containing token IDs and their corresponding metadata.\\n     * @return An array of TokenIdMetadata structs.\\n     */\\n    function getAllTokenIdMetadata()\\n        public\\n        view\\n        returns (TokenIdMetadata[] memory)\\n    {\\n        TokenIdMetadata[] memory allTokenIdMetadata = new TokenIdMetadata[](\\n            validTokenIds.length\\n        );\\n        for (uint256 i = 0; i < validTokenIds.length; i++) {\\n            allTokenIdMetadata[i].tokenId = validTokenIds[i];\\n            allTokenIdMetadata[i].metadata = tokenMetadata[validTokenIds[i]];\\n        }\\n        return allTokenIdMetadata;\\n    }\\n}\\n\",\"keccak256\":\"0xcb67c0d9dd5580cc1d1630deb3532b25ce62514152542f3485036e7bff6487a3\",\"license\":\"MIT\"},\"contracts/lib/base64.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Base64.sol)\\n\\npragma solidity ^0.8.19;\\n\\n/**\\n * @dev Provides a set of functions to operate with Base64 strings.\\n */\\nlibrary Base64 {\\n    /**\\n     * @dev Base64 Encoding/Decoding Table\\n     * See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648\\n     */\\n    string internal constant _TABLE =\\n        \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n    string internal constant _TABLE_URL =\\n        \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\\\";\\n\\n    /**\\n     * @dev Converts a `bytes` to its Bytes64 `string` representation.\\n     */\\n    function encode(bytes memory data) internal pure returns (string memory) {\\n        return _encode(data, _TABLE, true);\\n    }\\n\\n    /**\\n     * @dev Converts a `bytes` to its Bytes64Url `string` representation.\\n     */\\n    function encodeURL(\\n        bytes memory data\\n    ) internal pure returns (string memory) {\\n        return _encode(data, _TABLE_URL, false);\\n    }\\n\\n    /**\\n     * @dev Internal table-agnostic conversion\\n     */\\n    function _encode(\\n        bytes memory data,\\n        string memory table,\\n        bool withPadding\\n    ) private pure returns (string memory) {\\n        /**\\n         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\\n         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\\n         */\\n        if (data.length == 0) return \\\"\\\";\\n\\n        // If padding is enabled, the final length should be `bytes` data length divided by 3 rounded up and then\\n        // multiplied by 4 so that it leaves room for padding the last chunk\\n        // - `data.length + 2`  -> Round up\\n        // - `/ 3`              -> Number of 3-bytes chunks\\n        // - `4 *`              -> 4 characters for each chunk\\n        // If padding is disabled, the final length should be `bytes` data length multiplied by 4/3 rounded up as\\n        // opposed to when padding is required to fill the last chunk.\\n        // - `4 *`              -> 4 characters for each chunk\\n        // - `data.length + 2`  -> Round up\\n        // - `/ 3`              -> Number of 3-bytes chunks\\n        uint256 resultLength = withPadding\\n            ? 4 * ((data.length + 2) / 3)\\n            : (4 * data.length + 2) / 3;\\n\\n        string memory result = new string(resultLength);\\n\\n        /// @solidity memory-safe-assembly\\n        assembly {\\n            // Prepare the lookup table (skip the first \\\"length\\\" byte)\\n            let tablePtr := add(table, 1)\\n\\n            // Prepare result pointer, jump over length\\n            let resultPtr := add(result, 32)\\n\\n            // Run over the input, 3 bytes at a time\\n            for {\\n                let dataPtr := data\\n                let endPtr := add(data, mload(data))\\n            } lt(dataPtr, endPtr) {\\n\\n            } {\\n                // Advance 3 bytes\\n                dataPtr := add(dataPtr, 3)\\n                let input := mload(dataPtr)\\n\\n                // To write each character, shift the 3 bytes (18 bits) chunk\\n                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\\n                // and apply logical AND with 0x3F which is the number of\\n                // the previous character in the ASCII table prior to the Base64 Table\\n                // The result is then added to the table to get the character to write,\\n                // and finally write it in the result pointer but with a left shift\\n                // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits\\n\\n                mstore8(\\n                    resultPtr,\\n                    mload(add(tablePtr, and(shr(18, input), 0x3F)))\\n                )\\n                resultPtr := add(resultPtr, 1) // Advance\\n\\n                mstore8(\\n                    resultPtr,\\n                    mload(add(tablePtr, and(shr(12, input), 0x3F)))\\n                )\\n                resultPtr := add(resultPtr, 1) // Advance\\n\\n                mstore8(\\n                    resultPtr,\\n                    mload(add(tablePtr, and(shr(6, input), 0x3F)))\\n                )\\n                resultPtr := add(resultPtr, 1) // Advance\\n\\n                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\\n                resultPtr := add(resultPtr, 1) // Advance\\n            }\\n\\n            if withPadding {\\n                // When data `bytes` is not exactly 3 bytes long\\n                // it is padded with `=` characters at the end\\n                switch mod(mload(data), 3)\\n                case 1 {\\n                    mstore8(sub(resultPtr, 1), 0x3d)\\n                    mstore8(sub(resultPtr, 2), 0x3d)\\n                }\\n                case 2 {\\n                    mstore8(sub(resultPtr, 1), 0x3d)\\n                }\\n            }\\n        }\\n\\n        return result;\\n    }\\n}\\n\",\"keccak256\":\"0x1c4ca91af9cdd16b63cd65dafb05e9788b12d261d549e5d9650d424b2be129f4\",\"license\":\"MIT\"}},\"version\":1}",
  "bytecode": "0x60806040523462000030576200001e620000186200014d565b6200042e565b60405161313a620006d7823961313a90f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b038211176200006d57604052565b62000035565b906200008a6200008260405190565b92836200004b565b565b6001600160401b0381116200006d57602090601f01601f19160190565b60005b838110620000bd5750506000910152565b8181015183820152602001620000ac565b90929192620000e7620000e1826200008c565b62000073565b9381855260208501908284011162000030576200008a92620000a9565b9080601f83011215620000305781516200012192602001620000ce565b90565b90602082820312620000305781516001600160401b038111620000305762000121920162000104565b620001216200381180380380620001648162000073565b92833981019062000124565b9062000180620000e1836200008c565b918252565b62000121600062000170565b6200012162000185565b634e487b7160e01b600052602260045260246000fd5b9060016002830492168015620001d4575b6020831014620001ce57565b6200019b565b91607f1691620001c2565b9160001960089290920291821b911b5b9181191691161790565b6200012162000121620001219290565b91906200021e620001216200022793620001f9565b908354620001df565b9055565b6200008a9160009162000209565b81811062000245575050565b806200025560006001936200022b565b0162000239565b9190601f81116200026c57505050565b620002806200008a93600052602060002090565b906020601f840181900483019310620002a4575b6020601f90910104019062000239565b909150819062000294565b9060001960089091021c191690565b81620002ca91620002af565b906002021790565b90620002dc815190565b906001600160401b0382116200006d576200030482620002fd8554620001b1565b856200025c565b602090601f83116001146200033757620002279291600091836200032b575b5050620002be565b01519050388062000323565b601f198316916200034d85600052602060002090565b9260005b818110620003915750916002939185600196941062000374575b50505002019055565b62000386910151601f841690620002af565b90553880806200036b565b9193602060018192878701518155019501920162000351565b906200008a91620002d2565b620001216000620001f9565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177590565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a690565b7f73e573f9566d61418a34d5de3ff49360f9c51fec37f7486551670290f6285dab90565b6200044f90620004476200044162000191565b620004bc565b6008620003aa565b620004656200045d620003b6565b3390620004cc565b620004736200045d620003c2565b620004816200045d620003e6565b6200048f6200045d6200040a565b620004ae6200049d620003e6565b620004a7620003c2565b906200050c565b6200008a6200049d6200040a565b6200008a906200008a906200057b565b906200008a91620005f1565b905b600052602052604060002090565b9060001990620001ef565b906200050462000121620002279290565b8254620004e8565b90620005188262000685565b91620005348260016200052d846003620004d8565b01620004f3565b916200056a62000566620005667fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9590565b9290565b926200057560405190565b600090a4565b6200008a906002620003aa565b62000121906200059e906001600160a01b031682565b6001600160a01b031690565b620001219062000588565b6200012190620005aa565b90620004da90620005b5565b9060ff90620001ef565b90620005e9620001216200022792151590565b8254620005cc565b62000605620006018383620006b0565b1590565b6200060e575050565b62000636600162000630600062000627856003620004d8565b018590620005c0565b620005d6565b9033906200056a6200066a6200066a7f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b92620005b5565b620001219081565b62000121905462000671565b6001620006a2620001219262000699600090565b506003620004d8565b0162000679565b5460ff1690565b62000121916000620006c9620006d09362000699600090565b01620005c0565b620006a956fe6080604052600436101561001257600080fd5b60003560e01c8062749d6514610220578062fdd58e1461021b57806301ffc9a71461021657806307b5f95b146102115780630e89341c1461020c578063108d00d414610207578063248a9ca3146102025780632eb2c2d6146101fd5780632f2ff15d146101f857806336568abe146101f35780633e7dcc9d146101ee57806347e63380146101e95780634e1273f4146101e457806355f804b3146101df5780635a783c00146101da578063682953ed146101d55780636914db60146101d05780636c0360eb146101cb57806371185897146101c657806375b238fc146101c157806391d14854146101bc578063a217fddf146101b7578063a22cb465146101b2578063abd3f612146101ad578063cdb0e89e146101a8578063d5391393146101a3578063d547741f1461019e578063d559f05b14610199578063d56f4d0114610194578063dbe16c071461018f578063e985e9c51461018a578063f242432a146101855763fa82ac7603610230576110bb565b61109f565b611042565b61100d565b610ff1565b610f65565b610ee7565b610ecc565b610e87565b610e2b565b610d5f565b610d0c565b610cde565b610cc3565b610c7c565b610c55565b610bf3565b610a80565b610a65565b610a4d565b610a0c565b610942565b6108ef565b6107ee565b6107d5565b610791565b6105b2565b610596565b6104ce565b61044b565b610396565b610333565b6102a7565b600091031261023057565b600080fd5b9052565b0190565b9061025d61025661024c845190565b8084529260200190565b9260200190565b9060005b81811061026e5750505090565b90919261028b6102846001928651815260200190565b9460200190565b929101610261565b60208082526102a49291019061023d565b90565b34610230576102b7366004610225565b6102ce6102c261116a565b60405191829182610293565b0390f35b6001600160a01b031690565b6102e7816102d2565b0361023057565b905035906102fb826102de565b565b806102e7565b905035906102fb826102fd565b9190604083820312610230576102a49061032a81856102ee565b93602001610303565b34610230576102ce61034f610349366004610310565b906111ed565b6040519182918290815260200190565b6001600160e01b03191690565b6102e78161035f565b905035906102fb8261036c565b90602082820312610230576102a491610375565b34610230576102ce6103b16103ac366004610382565b611238565b6040515b91829182901515815260200190565b90602082820312610230576102a491610303565b634e487b7160e01b600052603260045260246000fd5b805482101561041157610408600191600052602060002090565b91020190600090565b6103d8565b6102a4916008021c81565b906102a49154610416565b600780545b821015610230576102a491610445916103ee565b90610421565b34610230576102ce61034f6104613660046103c4565b61042c565b60005b8381106104795750506000910152565b8181015183820152602001610469565b6104aa6104b36020936102399361049e815190565b80835293849260200190565b95869101610466565b601f01601f191690565b60208082526102a492910190610489565b34610230576102ce6104e96104e43660046103c4565b6113f1565b6040515b918291826104bd565b9091606082840312610230576102a461050f84846102ee565b9361051d8160208601610303565b93604001610303565b6102a4906102d2906001600160a01b031682565b6102a490610526565b6102a49061053a565b9061055690610543565b600052602052604060002090565b6102a46102a46102a49290565b9061055690610564565b9061058a61058f92600561054c565b610571565b8054610431565b34610230576102ce61034f6105ac3660046104f6565b9161057b565b34610230576102ce61034f6105c83660046103c4565b6114ad565b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b0382111761060457604052565b6105cd565b906102fb61061660405190565b92836105e3565b6001600160401b0381116106045760208091020190565b909291926106496106448261061d565b610609565b938185526020808601920283019281841161023057915b83831061066d5750505050565b6020809161067b8486610303565b815201920191610660565b9080601f83011215610230578160206102a493359101610634565b6001600160401b03811161060457602090601f01601f19160190565b90826000939282370152565b909291926106d9610644826106a1565b93818552602085019082840111610230576102fb926106bd565b9080601f83011215610230578160206102a4933591016106c9565b91909160a0818403126102305761072583826102ee565b9261073381602084016102ee565b9260408301356001600160401b0381116102305782610753918501610686565b9260608101356001600160401b0381116102305783610773918301610686565b9260808201356001600160401b038111610230576102a492016106f3565b34610230576107ad6107a436600461070e565b9392909261152c565b604051005b9190604083820312610230576102a4906107cc8185610303565b936020016102ee565b34610230576107ad6107e83660046107b2565b9061155b565b34610230576107ad6108013660046107b2565b906115c9565b805160608084526102a493916040916108389161082691850190610489565b60208501518482036020860152610489565b920151906040818403910152610489565b805182526102a491604081019160200151906020818403910152610807565b906102a491610849565b9061088861087e835190565b8083529160200190565b908161089a6020830284019460200190565b926000915b8383106108ae57505050505090565b909192939460206108d16108ca83856001950387528951610868565b9760200190565b930193019193929061089f565b60208082526102a492910190610872565b34610230576108ff366004610225565b6102ce61090a61170b565b604051918291826108de565b7f73e573f9566d61418a34d5de3ff49360f9c51fec37f7486551670290f6285dab90565b6102a4610916565b3461023057610952366004610225565b6102ce61034f61093a565b9092919261096d6106448261061d565b938185526020808601920283019281841161023057915b8383106109915750505050565b6020809161099f84866102ee565b815201920191610984565b9080601f83011215610230578160206102a49335910161095d565b9190916040818403126102305780356001600160401b03811161023057836109ee9183016109aa565b9260208201356001600160401b038111610230576102a49201610686565b34610230576102ce6102c2610a223660046109c5565b90611839565b906020828203126102305781356001600160401b038111610230576102a492016106f3565b34610230576107ad610a60366004610a28565b611b3e565b34610230576102ce6103b1610a7b3660046103c4565b611b47565b34610230576102ce6102c2610a96366004610310565b90611b91565b634e487b7160e01b600052602260045260246000fd5b9060016002830492168015610ad2575b6020831014610acd57565b610a9c565b91607f1691610ac2565b80546000939291610af9610aef83610ab2565b8085529360200190565b9160018116908115610b4b5750600114610b1257505050565b610b259192939450600052602060002090565b916000925b818410610b375750500190565b805484840152602090930192600101610b2a565b92949550505060ff1916825215156020020190565b906102a491610adc565b906102fb610b8492610b7b60405190565b93848092610b60565b03836105e3565b610b96906004610571565b610b9f81610b6a565b916102a46002610bb160018501610b6a565b9301610b6a565b91610be590610bd76102a4959360608601908682036000880152610489565b908482036020860152610489565b916040818403910152610489565b34610230576102ce610c0e610c093660046103c4565b610b8b565b60405191939193849384610bb8565b634e487b7160e01b600052600060045260246000fd5b90600010610c44576102a490610b6a565b610c1d565b6102a460006008610c33565b3461023057610c65366004610225565b6102ce6104e9610c49565b6102a460006006610421565b3461023057610c8c366004610225565b6102ce61034f610c70565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177590565b6102a4610c97565b3461023057610cd3366004610225565b6102ce61034f610cbb565b34610230576102ce6103b1610cf43660046107b2565b90611bc6565b6102a46000610564565b6102a4610cfa565b3461023057610d1c366004610225565b6102ce61034f610d04565b8015156102e7565b905035906102fb82610d27565b9190604083820312610230576102a490610d5681856102ee565b93602001610d2f565b34610230576107ad610d72366004610d3c565b90611be6565b90602082820312610230576102a4916102ee565b906102a490602080610dad6040840160008701518582036000870152610489565b940151910152565b906102a491610d8c565b90610dcb61087e835190565b9081610ddd6020830284019460200190565b926000915b838310610df157505050505090565b90919293946020610e0d6108ca83856001950387528951610db5565b9301930191939290610de2565b60208082526102a492910190610dbf565b34610230576102ce610e46610e41366004610d78565b611c61565b60405191829182610e1a565b91909160408184031261023057610e698382610303565b9260208201356001600160401b038111610230576102a492016106f3565b34610230576107ad610e9a366004610e52565b90611eae565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a690565b6102a4610ea0565b3461023057610edc366004610225565b6102ce61034f610ec4565b34610230576107ad610efa3660046107b2565b90611ed3565b916060838303126102305782356001600160401b0381116102305782610f279185016109aa565b9260208101356001600160401b0381116102305783610f47918301610686565b9260408201356001600160401b038111610230576102a49201610686565b34610230576107ad610f78366004610f00565b91612262565b9060808282031261023057610f938183610303565b9260208301356001600160401b0381116102305782610fb39185016106f3565b9260408101356001600160401b0381116102305783610fd39183016106f3565b9260608201356001600160401b038111610230576102a492016106f3565b34610230576107ad611004366004610f7e565b92919091612415565b34610230576102ce6104e96110233660046103c4565b612421565b9190604083820312610230576102a4906107cc81856102ee565b34610230576102ce6103b1611058366004611028565b90612461565b91909160a0818403126102305761107583826102ee565b9261108381602084016102ee565b926110918260408501610303565b926107738360608301610303565b34610230576107ad6110b236600461105e565b939290926124d6565b34610230576107ad6110ce3660046107b2565b90612540565b6102a49081565b6102a490546110d4565b906111006110f461024c845490565b92600052602060002090565b9060005b8181106111115750505090565b90919261113561112e600192611126876110db565b815260200190565b9460010190565b929101611104565b906102a4916110e5565b906102fb610b849261115860405190565b9384809261113d565b6102a490611147565b6102a46007611161565b6102d26102a46102a49290565b6102a490611174565b1561119157565b60405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b6064820152608490fd5b0390fd5b6112339061122e6102a493611200600090565b506112278361122061121a6112156000611181565b6102d2565b916102d2565b141561118a565b6000610571565b61054c565b6110db565b6102a49061259c565b6102a49054610ab2565b1561125257565b60405162461bcd60e51b815260206004820152602860248201527f44617461506f696e74734d756c74693a20546f6b656e20494420646f6573206e6044820152671bdd08195e1a5cdd60c21b6064820152608490fd5b805460009392916112bf6112bb83610ab2565b9390565b916001811690811561131057506001146112d857505050565b6112eb9192939450600052602060002090565b6000905b8382106112fc5750500190565b6001816020925484860152019101906112ef565b60ff191683525050811515909102019150565b611377611390936113526113586102a4979561135261135296693d913730b6b2911d101160b11b8152600a0190565b906112a8565b72111610113232b9b1b934b83a34b7b7111d101160691b815260130190565b6c1116101134b6b0b3b2911d101160991b8152600d0190565b61227d60f01b815260020190565b6102396113b6926020926113b0815190565b94859290565b93849101610466565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526102a49190601d015b9061139e565b6114846102a46114986114936102a46102a49561140c606090565b5061143f6114286114236000610239856004610571565b611241565b6114396114356000610564565b9190565b1161124b565b6102a4600061144f836004610571565b01611484600161146e6002611465876004610571565b01956004610571565b0161147860405190565b94859360208501611323565b602082018103825203826105e3565b612635565b604051928391602083016113bf565b90610556565b60016114c66102a4926114be600090565b5060036114a7565b016110db565b156114d357565b60405162461bcd60e51b815260206004820152602b60248201527f44617461506f696e74734d756c74693a206261746368207472616e736665722060448201526a1b9bdd08185b1b1bddd95960aa1b6064820152608490fd5b50505050506102fb60006114cc565b906102fb9161155161154c826114ad565b612649565b906102fb91612674565b906102fb9161153b565b1561156c57565b60405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608490fd5b6102fb91906115e4826115de61121a336102d2565b14611565565b6126f6565b906115f66106448361061d565b918252565b6102a46040610609565b6102a46060610609565b611617611605565b606080825260208201819052604082015290565b905250565b6102a461160f565b6116406115fb565b9060208083600081520161162b611630565b6102a4611638565b60005b82811061166957505050565b602090611674611652565b818401520161165d565b906102fb61168b836115e9565b92602080611699869361061d565b920191039061165a565b906116ac825190565b811015610411576020809102010190565b906102fb6116fb60026116ce611605565b946116df6116db82610b6a565b8752565b6116f56116ee60018301610b6a565b6020880152565b01610b6a565b6040840152565b6102a4906116bd565b61171c61171760075490565b61167e565b6117266000610564565b806117366114356102a460075490565b101561179f5761179a906117626117516104458360076103ee565b600061175d84876116a3565b510152565b61177b60046117756104458460076103ee565b90610571565b611792602061178a84876116a3565b510191611702565b905260010190565b611726565b5090565b156117aa57565b60405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608490fd5b369037565b906102fb611813836115e9565b92602080611821869361061d565b9201910390611801565b6102a490516102d2565b5190565b90611859611845835190565b6118536114356102a4855190565b146117a3565b611869611864835190565b611806565b916118746000610564565b806118836114356102a4855190565b10156118ca576118c5906118bf6118b26118a56118a084876116a3565b61182b565b61034961183585896116a3565b6118bc83886116a3565b52565b60010190565b611874565b50505090565b6102fb906118df61154c610c97565b611ae2565b156118eb57565b60405162461bcd60e51b815260206004820152602960248201527f44617461506f696e74734d756c74693a2042617365205552492063616e6e6f7460448201526820626520656d70747960b81b6064820152608490fd5b9160001960089290920291821b911b5b9181191691161790565b919061196d6102a461197593610564565b908354611942565b9055565b6102fb9160009161195c565b818110611990575050565b8061199e6000600193611979565b01611985565b9190601f81116119b357505050565b6119c56102fb93600052602060002090565b906020601f8401819004830193106119e7575b6020601f909101040190611985565b90915081906119d8565b9060001960089091021c191690565b81611a0a916119f1565b906002021790565b90611a1b815190565b906001600160401b03821161060457611a3e82611a388554610ab2565b856119a4565b602090601f8311600114611a6c57611975929160009183611a61575b5050611a00565b015190503880611a5a565b601f19831691611a8185600052602060002090565b9260005b818110611ac057509160029391856001969410611aa6575b50505002019055565b611ab6910151601f8416906119f1565b9055388080611a9d565b91936020600181928787015181550195019201611a85565b906102fb91611a12565b611b00611aed825190565b611afa6114356000610564565b116118e4565b611b0b816008611ad8565b611b397ff9c7803e94e0d3c02900d8a90893a6d5e90dd04d32a4cfe825520f82bf9f32f6916104ed60405190565b0390a1565b6102fb906118d0565b611b516000610564565b80611b616114356102a460075490565b1015611b8a57611b756104458260076103ee565b8214611b8357600101611b51565b5050600190565b5050600090565b6102a49161058a611bac92611ba4606090565b50600561054c565b611161565b6102a4905b60ff1690565b6102a49054611bb1565b6102a4916000611bdb611be1936114be600090565b0161054c565b611bbc565b6102fb9190336127ab565b611bf96115fb565b606081526000602082015290565b6102a4611bf1565b60005b828110611c1e57505050565b602090611c29611c07565b8184015201611c12565b906102fb611c40836115e9565b92602080611c4e869361061d565b9201910390611c0f565b6102a490610b6a565b611c72611c6d60075490565b611c33565b90611c7d6000610564565b80611c8d6114356102a460075490565b1015611ce957611ce4906118bf611cd8611cab6104458460076103ee565b6000611cb8826004610571565b01611cd06000611cc8878b6116a3565b510191611c58565b9052856111ed565b602061175d84886116a3565b611c7d565b505090565b906102fb91611cfe61154c610916565b611def565b15611d0a57565b60405162461bcd60e51b815260206004820152602b60248201527f44617461506f696e74734d756c74693a20546f6b656e206e616d652063616e6e60448201526a6f7420626520656d70747960a81b6064820152608490fd5b80549190600160401b8310156106045782611d869160016102fb950181556103ee565b9061195c565b634e487b7160e01b600052601160045260246000fd5b6000198114611db15760010190565b611d8c565b9060001990611952565b90611dd06102a461197592610564565b8254611db6565b9081526040602082018190526102a492910190610489565b611e0d611dfa835190565b611e076114356000610564565b11611d03565b611e206114236000610239846004610571565b611e2d6114356000610564565b14611e45836000611e3f856004610571565b01611ad8565b611e82575b907f12eaf3f3916d89f3c309726b8ae46295fd61d13f086e7c92fe4745c70bd523d491611b39611e7960405190565b92839283611dd7565b611e8d816007611d63565b611ea9611ea2611e9d60066110db565b611da2565b6006611dc0565b611e4a565b906102fb91611cee565b906102fb91611ec961154c826114ad565b906102fb916126f6565b906102fb91611eb8565b906102fb9291611eee61154c610ea0565b6120a4565b15611efa57565b60405162461bcd60e51b815260206004820152603760248201527f4d7573742070726f7669646520657175616c206e756d62657273206f66206164604482015276647265737365732c206964732c20616e6420555549447360481b6064820152608490fd5b15611f6657565b60405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081d1bdad95b88125160821b6044820152606490fd5b15611fa557565b60405162461bcd60e51b8152602060048201526013602482015272555549442063616e6e6f74206265207a65726f60681b6044820152606490fd5b15611fe757565b60405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f74206d696e7420746f20746865207a65726f2061646472657373006044820152606490fd5b906115f6610644836106a1565b612043600461202c565b630307830360e41b602082015290565b6102a4612039565b610235906102d2565b61023590610564565b6120a06102fb9461209660609498979561208f608086019a600087019061205b565b6020850152565b6040830190612064565b0152565b9291906120af845190565b6120bd6114356102a4845190565b1480612240575b6120cd90611ef3565b6120d76000610564565b806120e66114356102a4885190565b10156122395761223490612108612103610a7b61183584876116a3565b611f5f565b61212c61211861183583876116a3565b6121256114356000610564565b1415611f9e565b61215361213c6118a083896116a3565b61214c61121a6112156000611181565b1415611fe0565b6121946121816102a4612174600561216e6118a0878d6116a3565b9061054c565b61177561183586896116a3565b61218e61183584886116a3565b90611d63565b6121ca6121a46118a083896116a3565b6121b161183584876116a3565b6121bb6001610564565b906121c4612053565b9261289c565b6121d76118a082886116a3565b6121e461183583866116a3565b60019161222b6121f7611835868a6116a3565b7f10546b1a6f5245ff0ffa18c256b9e46859c585cbb473b453fcd4c2dc39ae08db9461222260405190565b9485948561206d565b0390a160010190565b6120d7565b5050509050565b506120cd61224c825190565b61225a6114356102a4865190565b1490506120c4565b906102fb9291611edd565b906102fb93929161227f61154c610c97565b612393565b1561228b57565b60405162461bcd60e51b815260206004820152602c60248201527f44617461506f696e74734d756c74693a20546f6b656e20696d6167652063616e60448201526b6e6f7420626520656d70747960a01b6064820152608490fd5b156122ec57565b60405162461bcd60e51b815260206004820152603260248201527f44617461506f696e74734d756c74693a20546f6b656e206465736372697074696044820152716f6e2063616e6e6f7420626520656d70747960701b6064820152608490fd5b9061236a604060026102fb946123706000820161236a600088015190565b90611ad8565b6123826001820161236a602088015190565b0192015190565b906102fb9161234c565b6124096102fb94612402612410946123ae611dfa6118358390565b6123cc6123b9885190565b6123c66114356000610564565b11612284565b6123ea6123d7845190565b6123e46114356000610564565b116122e5565b956123fb6123f6611605565b978852565b6020870152565b6040850152565b6004610571565b612389565b906102fb93929161226d565b600061245b6102a492612432606090565b5061240961244861142385610239856004610571565b61245461143586610564565b141561124b565b01611c58565b6102a49161122e611be192612474600090565b50600161054c565b1561248357565b60405162461bcd60e51b815260206004820152602560248201527f44617461506f696e74734d756c74693a207472616e73666572206e6f7420616c6044820152641b1bddd95960da1b6064820152608490fd5b50505050506102fb600061247c565b156124ec57565b60405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1030b71030b236b4b760511b6044820152606490fd5b9081526040810192916102fb916020019061205b565b61255a61255561254e610cfa565b3390611bc6565b6124e5565b6125648282611551565b907f16194562807df720d4a84cf9af794c83e0d73a47c9b37a146b142d4b5c08c2cd91611b3961259360405190565b9283928361252a565b806125b66125b0637965db0b60e01b61035f565b9161035f565b149081156125c2575090565b6102a49150612977565b6125d6604061202c565b7f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f604082015290565b6102a46125cc565b6102a4612625565b6102a49061264161262d565b600191612a28565b6102fb903390612bab565b9060ff90611952565b9061266d6102a461197592151590565b8254612654565b6126856126818383611bc6565b1590565b61268d575050565b6126af60016126aa60006126a28560036114a7565b01859061054c565b61265d565b9033906126e66126e06126e07f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b92610543565b926126f060405190565b600090a4565b6127008282611bc6565b612708575050565b61271c60006126aa816126a28560036114a7565b9033906126e66126e06126e07ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9590565b1561275457565b60405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608490fd5b9190916127c5816127be61121a866102d2565b141561274d565b6127de826126aa6127d784600161054c565b869061054c565b9190916128216128176128117f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3193610543565b93610543565b936103b560405190565b0390a3565b1561282d57565b60405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608490fd5b91908201809211611db157565b9081526040810192916102fb9160200152565b916102fb93916128bd846128b661121a6112156000611181565b1415612826565b336128c782612c22565b506128d183612c22565b50612903836128fd6128ee6128e7866000610571565b899061054c565b916128f8836110db565b61287c565b90611dc0565b8061290e6000611181565b86908492866129496129436129437fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6294610543565b94610543565b9461295f61295660405190565b92839283612889565b0390a49361296d6000611181565b9091929394612d38565b8061298b6125b0636cdb3d1360e11b61035f565b1480156129a8575b90811561299e575090565b6102a49150612ef6565b50806129bd6125b06303a24d0760e21b61035f565b14612993565b6102a4600061202c565b6102a46129c3565b81810292918115918404141715611db157565b634e487b7160e01b600052601260045260246000fd5b8115612a08570490565b6129e8565b906102fb612a1a8361202c565b9260208061182186936106a1565b9091908051612a3a6114356000610564565b14612b48578115612b2d576001612a90612a8b6004612a86612a80612a70612a60885190565b612a6a6002610564565b9061287c565b612a7a6003610564565b906129fe565b91610564565b6129d5565b612a0d565b9301916020840192829083518401915b828110612ae657505050612ab357505090565b600390510680600114612ad557600214612acb575090565b6001603d91035390565b50600281603d600181940353035390565b6003600191969293960191603f828080865194848660121c168901518153018385600c1c16880151815301828460061c168701518153019116840151815301949190612aa0565b6001612a90612a8b612a70612a606004612a86612a80885190565b5050506102a46129cd565b6102a490610564565b612b8e6102a493926113eb6113eb9376020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b815260170190565b7001034b99036b4b9b9b4b733903937b6329607d1b815260110190565b90612bb96126818284611bc6565b612bc1575050565b6111e9916102a4612bf0612be0612bda612c0995612f46565b93612b53565b612bea6020610564565b90613000565b91611484612bfd60405190565b93849260208401612b5c565b6040515b62461bcd60e51b8152918291600483016104bd565b6102a4612c326118646001610564565b916118bc83612c416000610564565b906116a3565b905051906102fb8261036c565b90602082820312610230576102a491612c47565b9193612c966102a49694612402612c9d9497612c8c60a0880199600089019061205b565b602087019061205b565b6060830152565b6080818403910152610489565b60009060033d11612cb757565b905060046000803e60005160e01c90565b60009060443d106102fb5760405160043d036004823e8051906001600160401b0382113d602484011117612d345780820180519092906001600160401b038111612d2e5780602085010160043d03840110612d2e576102a49394955060200101906105e3565b50505050565b5050565b939491909294612d47826130f2565b612d54575b505050505050565b602094612d9e600092612d71612d6c612d9396610543565b610543565b9563f23a6e61939799919091612d8660405190565b9a8b998a98899760e01b90565b875260048701612c68565b03925af160009181612ec6575b50612e5857506001612dbb612caa565b6308c379a014612e38575b612dd6575b388080808080612d4c565b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608490fd5b612e40612cc8565b80612e4b5750612dc6565b6111e990612c0d60405190565b612e6b6125b063f23a6e6160e01b61035f565b14612dcb5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b6064820152608490fd5b612ee891925060203d8111612eef575b612ee081836105e3565b810190612c54565b9038612dab565b503d612ed6565b612f096125b06301ffc9a760e01b61035f565b1490565b6102a49081906001600160a01b031681565b611bb66102a46102a49290565b6102a46014612f1f565b6102a46102a46102a49260ff1690565b612f63612f5e6102a492612f58606090565b5061053a565b612f0d565b612bea612f6e612f2c565b612f36565b90612f7c825190565b811015610411570160200190565b8015611db1576000190190565b6102a490612fab6114356102a49460ff1690565b901c90565b15612fb757565b60405162461bcd60e51b8152806111e9600482016020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b919061305961304f61301c612a8b612a6085612a866002610564565b9260306130338561302d6000610564565b90612f73565b5360786130448561302d6001610564565b53612a866002610564565b612a6a6001610564565b925b836130696114356001610564565b11156130d5576f181899199a1a9b1b9c1cb0b131b232b360811b8161308e600f610564565b16916010831015610411576130ab6130c9926130cf941a60f81b90565b60001a6130b88786612f73565b536130c36004612f1f565b90612f97565b93612f8a565b9261305b565b6102a49293506102a4906130ec6114356000610564565b14612fb0565b3b6131006114356000610564565b119056fea264697066735822122048b64a70cf7789f40e045cf7a9634483d111fbdb4595c68481e2e5b84609e12364736f6c63430008180033",
  "deployedBytecode": "0x6080604052600436101561001257600080fd5b60003560e01c8062749d6514610220578062fdd58e1461021b57806301ffc9a71461021657806307b5f95b146102115780630e89341c1461020c578063108d00d414610207578063248a9ca3146102025780632eb2c2d6146101fd5780632f2ff15d146101f857806336568abe146101f35780633e7dcc9d146101ee57806347e63380146101e95780634e1273f4146101e457806355f804b3146101df5780635a783c00146101da578063682953ed146101d55780636914db60146101d05780636c0360eb146101cb57806371185897146101c657806375b238fc146101c157806391d14854146101bc578063a217fddf146101b7578063a22cb465146101b2578063abd3f612146101ad578063cdb0e89e146101a8578063d5391393146101a3578063d547741f1461019e578063d559f05b14610199578063d56f4d0114610194578063dbe16c071461018f578063e985e9c51461018a578063f242432a146101855763fa82ac7603610230576110bb565b61109f565b611042565b61100d565b610ff1565b610f65565b610ee7565b610ecc565b610e87565b610e2b565b610d5f565b610d0c565b610cde565b610cc3565b610c7c565b610c55565b610bf3565b610a80565b610a65565b610a4d565b610a0c565b610942565b6108ef565b6107ee565b6107d5565b610791565b6105b2565b610596565b6104ce565b61044b565b610396565b610333565b6102a7565b600091031261023057565b600080fd5b9052565b0190565b9061025d61025661024c845190565b8084529260200190565b9260200190565b9060005b81811061026e5750505090565b90919261028b6102846001928651815260200190565b9460200190565b929101610261565b60208082526102a49291019061023d565b90565b34610230576102b7366004610225565b6102ce6102c261116a565b60405191829182610293565b0390f35b6001600160a01b031690565b6102e7816102d2565b0361023057565b905035906102fb826102de565b565b806102e7565b905035906102fb826102fd565b9190604083820312610230576102a49061032a81856102ee565b93602001610303565b34610230576102ce61034f610349366004610310565b906111ed565b6040519182918290815260200190565b6001600160e01b03191690565b6102e78161035f565b905035906102fb8261036c565b90602082820312610230576102a491610375565b34610230576102ce6103b16103ac366004610382565b611238565b6040515b91829182901515815260200190565b90602082820312610230576102a491610303565b634e487b7160e01b600052603260045260246000fd5b805482101561041157610408600191600052602060002090565b91020190600090565b6103d8565b6102a4916008021c81565b906102a49154610416565b600780545b821015610230576102a491610445916103ee565b90610421565b34610230576102ce61034f6104613660046103c4565b61042c565b60005b8381106104795750506000910152565b8181015183820152602001610469565b6104aa6104b36020936102399361049e815190565b80835293849260200190565b95869101610466565b601f01601f191690565b60208082526102a492910190610489565b34610230576102ce6104e96104e43660046103c4565b6113f1565b6040515b918291826104bd565b9091606082840312610230576102a461050f84846102ee565b9361051d8160208601610303565b93604001610303565b6102a4906102d2906001600160a01b031682565b6102a490610526565b6102a49061053a565b9061055690610543565b600052602052604060002090565b6102a46102a46102a49290565b9061055690610564565b9061058a61058f92600561054c565b610571565b8054610431565b34610230576102ce61034f6105ac3660046104f6565b9161057b565b34610230576102ce61034f6105c83660046103c4565b6114ad565b634e487b7160e01b600052604160045260246000fd5b90601f01601f191681019081106001600160401b0382111761060457604052565b6105cd565b906102fb61061660405190565b92836105e3565b6001600160401b0381116106045760208091020190565b909291926106496106448261061d565b610609565b938185526020808601920283019281841161023057915b83831061066d5750505050565b6020809161067b8486610303565b815201920191610660565b9080601f83011215610230578160206102a493359101610634565b6001600160401b03811161060457602090601f01601f19160190565b90826000939282370152565b909291926106d9610644826106a1565b93818552602085019082840111610230576102fb926106bd565b9080601f83011215610230578160206102a4933591016106c9565b91909160a0818403126102305761072583826102ee565b9261073381602084016102ee565b9260408301356001600160401b0381116102305782610753918501610686565b9260608101356001600160401b0381116102305783610773918301610686565b9260808201356001600160401b038111610230576102a492016106f3565b34610230576107ad6107a436600461070e565b9392909261152c565b604051005b9190604083820312610230576102a4906107cc8185610303565b936020016102ee565b34610230576107ad6107e83660046107b2565b9061155b565b34610230576107ad6108013660046107b2565b906115c9565b805160608084526102a493916040916108389161082691850190610489565b60208501518482036020860152610489565b920151906040818403910152610489565b805182526102a491604081019160200151906020818403910152610807565b906102a491610849565b9061088861087e835190565b8083529160200190565b908161089a6020830284019460200190565b926000915b8383106108ae57505050505090565b909192939460206108d16108ca83856001950387528951610868565b9760200190565b930193019193929061089f565b60208082526102a492910190610872565b34610230576108ff366004610225565b6102ce61090a61170b565b604051918291826108de565b7f73e573f9566d61418a34d5de3ff49360f9c51fec37f7486551670290f6285dab90565b6102a4610916565b3461023057610952366004610225565b6102ce61034f61093a565b9092919261096d6106448261061d565b938185526020808601920283019281841161023057915b8383106109915750505050565b6020809161099f84866102ee565b815201920191610984565b9080601f83011215610230578160206102a49335910161095d565b9190916040818403126102305780356001600160401b03811161023057836109ee9183016109aa565b9260208201356001600160401b038111610230576102a49201610686565b34610230576102ce6102c2610a223660046109c5565b90611839565b906020828203126102305781356001600160401b038111610230576102a492016106f3565b34610230576107ad610a60366004610a28565b611b3e565b34610230576102ce6103b1610a7b3660046103c4565b611b47565b34610230576102ce6102c2610a96366004610310565b90611b91565b634e487b7160e01b600052602260045260246000fd5b9060016002830492168015610ad2575b6020831014610acd57565b610a9c565b91607f1691610ac2565b80546000939291610af9610aef83610ab2565b8085529360200190565b9160018116908115610b4b5750600114610b1257505050565b610b259192939450600052602060002090565b916000925b818410610b375750500190565b805484840152602090930192600101610b2a565b92949550505060ff1916825215156020020190565b906102a491610adc565b906102fb610b8492610b7b60405190565b93848092610b60565b03836105e3565b610b96906004610571565b610b9f81610b6a565b916102a46002610bb160018501610b6a565b9301610b6a565b91610be590610bd76102a4959360608601908682036000880152610489565b908482036020860152610489565b916040818403910152610489565b34610230576102ce610c0e610c093660046103c4565b610b8b565b60405191939193849384610bb8565b634e487b7160e01b600052600060045260246000fd5b90600010610c44576102a490610b6a565b610c1d565b6102a460006008610c33565b3461023057610c65366004610225565b6102ce6104e9610c49565b6102a460006006610421565b3461023057610c8c366004610225565b6102ce61034f610c70565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177590565b6102a4610c97565b3461023057610cd3366004610225565b6102ce61034f610cbb565b34610230576102ce6103b1610cf43660046107b2565b90611bc6565b6102a46000610564565b6102a4610cfa565b3461023057610d1c366004610225565b6102ce61034f610d04565b8015156102e7565b905035906102fb82610d27565b9190604083820312610230576102a490610d5681856102ee565b93602001610d2f565b34610230576107ad610d72366004610d3c565b90611be6565b90602082820312610230576102a4916102ee565b906102a490602080610dad6040840160008701518582036000870152610489565b940151910152565b906102a491610d8c565b90610dcb61087e835190565b9081610ddd6020830284019460200190565b926000915b838310610df157505050505090565b90919293946020610e0d6108ca83856001950387528951610db5565b9301930191939290610de2565b60208082526102a492910190610dbf565b34610230576102ce610e46610e41366004610d78565b611c61565b60405191829182610e1a565b91909160408184031261023057610e698382610303565b9260208201356001600160401b038111610230576102a492016106f3565b34610230576107ad610e9a366004610e52565b90611eae565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a690565b6102a4610ea0565b3461023057610edc366004610225565b6102ce61034f610ec4565b34610230576107ad610efa3660046107b2565b90611ed3565b916060838303126102305782356001600160401b0381116102305782610f279185016109aa565b9260208101356001600160401b0381116102305783610f47918301610686565b9260408201356001600160401b038111610230576102a49201610686565b34610230576107ad610f78366004610f00565b91612262565b9060808282031261023057610f938183610303565b9260208301356001600160401b0381116102305782610fb39185016106f3565b9260408101356001600160401b0381116102305783610fd39183016106f3565b9260608201356001600160401b038111610230576102a492016106f3565b34610230576107ad611004366004610f7e565b92919091612415565b34610230576102ce6104e96110233660046103c4565b612421565b9190604083820312610230576102a4906107cc81856102ee565b34610230576102ce6103b1611058366004611028565b90612461565b91909160a0818403126102305761107583826102ee565b9261108381602084016102ee565b926110918260408501610303565b926107738360608301610303565b34610230576107ad6110b236600461105e565b939290926124d6565b34610230576107ad6110ce3660046107b2565b90612540565b6102a49081565b6102a490546110d4565b906111006110f461024c845490565b92600052602060002090565b9060005b8181106111115750505090565b90919261113561112e600192611126876110db565b815260200190565b9460010190565b929101611104565b906102a4916110e5565b906102fb610b849261115860405190565b9384809261113d565b6102a490611147565b6102a46007611161565b6102d26102a46102a49290565b6102a490611174565b1561119157565b60405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b6064820152608490fd5b0390fd5b6112339061122e6102a493611200600090565b506112278361122061121a6112156000611181565b6102d2565b916102d2565b141561118a565b6000610571565b61054c565b6110db565b6102a49061259c565b6102a49054610ab2565b1561125257565b60405162461bcd60e51b815260206004820152602860248201527f44617461506f696e74734d756c74693a20546f6b656e20494420646f6573206e6044820152671bdd08195e1a5cdd60c21b6064820152608490fd5b805460009392916112bf6112bb83610ab2565b9390565b916001811690811561131057506001146112d857505050565b6112eb9192939450600052602060002090565b6000905b8382106112fc5750500190565b6001816020925484860152019101906112ef565b60ff191683525050811515909102019150565b611377611390936113526113586102a4979561135261135296693d913730b6b2911d101160b11b8152600a0190565b906112a8565b72111610113232b9b1b934b83a34b7b7111d101160691b815260130190565b6c1116101134b6b0b3b2911d101160991b8152600d0190565b61227d60f01b815260020190565b6102396113b6926020926113b0815190565b94859290565b93849101610466565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526102a49190601d015b9061139e565b6114846102a46114986114936102a46102a49561140c606090565b5061143f6114286114236000610239856004610571565b611241565b6114396114356000610564565b9190565b1161124b565b6102a4600061144f836004610571565b01611484600161146e6002611465876004610571565b01956004610571565b0161147860405190565b94859360208501611323565b602082018103825203826105e3565b612635565b604051928391602083016113bf565b90610556565b60016114c66102a4926114be600090565b5060036114a7565b016110db565b156114d357565b60405162461bcd60e51b815260206004820152602b60248201527f44617461506f696e74734d756c74693a206261746368207472616e736665722060448201526a1b9bdd08185b1b1bddd95960aa1b6064820152608490fd5b50505050506102fb60006114cc565b906102fb9161155161154c826114ad565b612649565b906102fb91612674565b906102fb9161153b565b1561156c57565b60405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608490fd5b6102fb91906115e4826115de61121a336102d2565b14611565565b6126f6565b906115f66106448361061d565b918252565b6102a46040610609565b6102a46060610609565b611617611605565b606080825260208201819052604082015290565b905250565b6102a461160f565b6116406115fb565b9060208083600081520161162b611630565b6102a4611638565b60005b82811061166957505050565b602090611674611652565b818401520161165d565b906102fb61168b836115e9565b92602080611699869361061d565b920191039061165a565b906116ac825190565b811015610411576020809102010190565b906102fb6116fb60026116ce611605565b946116df6116db82610b6a565b8752565b6116f56116ee60018301610b6a565b6020880152565b01610b6a565b6040840152565b6102a4906116bd565b61171c61171760075490565b61167e565b6117266000610564565b806117366114356102a460075490565b101561179f5761179a906117626117516104458360076103ee565b600061175d84876116a3565b510152565b61177b60046117756104458460076103ee565b90610571565b611792602061178a84876116a3565b510191611702565b905260010190565b611726565b5090565b156117aa57565b60405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608490fd5b369037565b906102fb611813836115e9565b92602080611821869361061d565b9201910390611801565b6102a490516102d2565b5190565b90611859611845835190565b6118536114356102a4855190565b146117a3565b611869611864835190565b611806565b916118746000610564565b806118836114356102a4855190565b10156118ca576118c5906118bf6118b26118a56118a084876116a3565b61182b565b61034961183585896116a3565b6118bc83886116a3565b52565b60010190565b611874565b50505090565b6102fb906118df61154c610c97565b611ae2565b156118eb57565b60405162461bcd60e51b815260206004820152602960248201527f44617461506f696e74734d756c74693a2042617365205552492063616e6e6f7460448201526820626520656d70747960b81b6064820152608490fd5b9160001960089290920291821b911b5b9181191691161790565b919061196d6102a461197593610564565b908354611942565b9055565b6102fb9160009161195c565b818110611990575050565b8061199e6000600193611979565b01611985565b9190601f81116119b357505050565b6119c56102fb93600052602060002090565b906020601f8401819004830193106119e7575b6020601f909101040190611985565b90915081906119d8565b9060001960089091021c191690565b81611a0a916119f1565b906002021790565b90611a1b815190565b906001600160401b03821161060457611a3e82611a388554610ab2565b856119a4565b602090601f8311600114611a6c57611975929160009183611a61575b5050611a00565b015190503880611a5a565b601f19831691611a8185600052602060002090565b9260005b818110611ac057509160029391856001969410611aa6575b50505002019055565b611ab6910151601f8416906119f1565b9055388080611a9d565b91936020600181928787015181550195019201611a85565b906102fb91611a12565b611b00611aed825190565b611afa6114356000610564565b116118e4565b611b0b816008611ad8565b611b397ff9c7803e94e0d3c02900d8a90893a6d5e90dd04d32a4cfe825520f82bf9f32f6916104ed60405190565b0390a1565b6102fb906118d0565b611b516000610564565b80611b616114356102a460075490565b1015611b8a57611b756104458260076103ee565b8214611b8357600101611b51565b5050600190565b5050600090565b6102a49161058a611bac92611ba4606090565b50600561054c565b611161565b6102a4905b60ff1690565b6102a49054611bb1565b6102a4916000611bdb611be1936114be600090565b0161054c565b611bbc565b6102fb9190336127ab565b611bf96115fb565b606081526000602082015290565b6102a4611bf1565b60005b828110611c1e57505050565b602090611c29611c07565b8184015201611c12565b906102fb611c40836115e9565b92602080611c4e869361061d565b9201910390611c0f565b6102a490610b6a565b611c72611c6d60075490565b611c33565b90611c7d6000610564565b80611c8d6114356102a460075490565b1015611ce957611ce4906118bf611cd8611cab6104458460076103ee565b6000611cb8826004610571565b01611cd06000611cc8878b6116a3565b510191611c58565b9052856111ed565b602061175d84886116a3565b611c7d565b505090565b906102fb91611cfe61154c610916565b611def565b15611d0a57565b60405162461bcd60e51b815260206004820152602b60248201527f44617461506f696e74734d756c74693a20546f6b656e206e616d652063616e6e60448201526a6f7420626520656d70747960a81b6064820152608490fd5b80549190600160401b8310156106045782611d869160016102fb950181556103ee565b9061195c565b634e487b7160e01b600052601160045260246000fd5b6000198114611db15760010190565b611d8c565b9060001990611952565b90611dd06102a461197592610564565b8254611db6565b9081526040602082018190526102a492910190610489565b611e0d611dfa835190565b611e076114356000610564565b11611d03565b611e206114236000610239846004610571565b611e2d6114356000610564565b14611e45836000611e3f856004610571565b01611ad8565b611e82575b907f12eaf3f3916d89f3c309726b8ae46295fd61d13f086e7c92fe4745c70bd523d491611b39611e7960405190565b92839283611dd7565b611e8d816007611d63565b611ea9611ea2611e9d60066110db565b611da2565b6006611dc0565b611e4a565b906102fb91611cee565b906102fb91611ec961154c826114ad565b906102fb916126f6565b906102fb91611eb8565b906102fb9291611eee61154c610ea0565b6120a4565b15611efa57565b60405162461bcd60e51b815260206004820152603760248201527f4d7573742070726f7669646520657175616c206e756d62657273206f66206164604482015276647265737365732c206964732c20616e6420555549447360481b6064820152608490fd5b15611f6657565b60405162461bcd60e51b815260206004820152601060248201526f125b9d985b1a59081d1bdad95b88125160821b6044820152606490fd5b15611fa557565b60405162461bcd60e51b8152602060048201526013602482015272555549442063616e6e6f74206265207a65726f60681b6044820152606490fd5b15611fe757565b60405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f74206d696e7420746f20746865207a65726f2061646472657373006044820152606490fd5b906115f6610644836106a1565b612043600461202c565b630307830360e41b602082015290565b6102a4612039565b610235906102d2565b61023590610564565b6120a06102fb9461209660609498979561208f608086019a600087019061205b565b6020850152565b6040830190612064565b0152565b9291906120af845190565b6120bd6114356102a4845190565b1480612240575b6120cd90611ef3565b6120d76000610564565b806120e66114356102a4885190565b10156122395761223490612108612103610a7b61183584876116a3565b611f5f565b61212c61211861183583876116a3565b6121256114356000610564565b1415611f9e565b61215361213c6118a083896116a3565b61214c61121a6112156000611181565b1415611fe0565b6121946121816102a4612174600561216e6118a0878d6116a3565b9061054c565b61177561183586896116a3565b61218e61183584886116a3565b90611d63565b6121ca6121a46118a083896116a3565b6121b161183584876116a3565b6121bb6001610564565b906121c4612053565b9261289c565b6121d76118a082886116a3565b6121e461183583866116a3565b60019161222b6121f7611835868a6116a3565b7f10546b1a6f5245ff0ffa18c256b9e46859c585cbb473b453fcd4c2dc39ae08db9461222260405190565b9485948561206d565b0390a160010190565b6120d7565b5050509050565b506120cd61224c825190565b61225a6114356102a4865190565b1490506120c4565b906102fb9291611edd565b906102fb93929161227f61154c610c97565b612393565b1561228b57565b60405162461bcd60e51b815260206004820152602c60248201527f44617461506f696e74734d756c74693a20546f6b656e20696d6167652063616e60448201526b6e6f7420626520656d70747960a01b6064820152608490fd5b156122ec57565b60405162461bcd60e51b815260206004820152603260248201527f44617461506f696e74734d756c74693a20546f6b656e206465736372697074696044820152716f6e2063616e6e6f7420626520656d70747960701b6064820152608490fd5b9061236a604060026102fb946123706000820161236a600088015190565b90611ad8565b6123826001820161236a602088015190565b0192015190565b906102fb9161234c565b6124096102fb94612402612410946123ae611dfa6118358390565b6123cc6123b9885190565b6123c66114356000610564565b11612284565b6123ea6123d7845190565b6123e46114356000610564565b116122e5565b956123fb6123f6611605565b978852565b6020870152565b6040850152565b6004610571565b612389565b906102fb93929161226d565b600061245b6102a492612432606090565b5061240961244861142385610239856004610571565b61245461143586610564565b141561124b565b01611c58565b6102a49161122e611be192612474600090565b50600161054c565b1561248357565b60405162461bcd60e51b815260206004820152602560248201527f44617461506f696e74734d756c74693a207472616e73666572206e6f7420616c6044820152641b1bddd95960da1b6064820152608490fd5b50505050506102fb600061247c565b156124ec57565b60405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1030b71030b236b4b760511b6044820152606490fd5b9081526040810192916102fb916020019061205b565b61255a61255561254e610cfa565b3390611bc6565b6124e5565b6125648282611551565b907f16194562807df720d4a84cf9af794c83e0d73a47c9b37a146b142d4b5c08c2cd91611b3961259360405190565b9283928361252a565b806125b66125b0637965db0b60e01b61035f565b9161035f565b149081156125c2575090565b6102a49150612977565b6125d6604061202c565b7f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208201527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f604082015290565b6102a46125cc565b6102a4612625565b6102a49061264161262d565b600191612a28565b6102fb903390612bab565b9060ff90611952565b9061266d6102a461197592151590565b8254612654565b6126856126818383611bc6565b1590565b61268d575050565b6126af60016126aa60006126a28560036114a7565b01859061054c565b61265d565b9033906126e66126e06126e07f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b92610543565b926126f060405190565b600090a4565b6127008282611bc6565b612708575050565b61271c60006126aa816126a28560036114a7565b9033906126e66126e06126e07ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9590565b1561275457565b60405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608490fd5b9190916127c5816127be61121a866102d2565b141561274d565b6127de826126aa6127d784600161054c565b869061054c565b9190916128216128176128117f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3193610543565b93610543565b936103b560405190565b0390a3565b1561282d57565b60405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608490fd5b91908201809211611db157565b9081526040810192916102fb9160200152565b916102fb93916128bd846128b661121a6112156000611181565b1415612826565b336128c782612c22565b506128d183612c22565b50612903836128fd6128ee6128e7866000610571565b899061054c565b916128f8836110db565b61287c565b90611dc0565b8061290e6000611181565b86908492866129496129436129437fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6294610543565b94610543565b9461295f61295660405190565b92839283612889565b0390a49361296d6000611181565b9091929394612d38565b8061298b6125b0636cdb3d1360e11b61035f565b1480156129a8575b90811561299e575090565b6102a49150612ef6565b50806129bd6125b06303a24d0760e21b61035f565b14612993565b6102a4600061202c565b6102a46129c3565b81810292918115918404141715611db157565b634e487b7160e01b600052601260045260246000fd5b8115612a08570490565b6129e8565b906102fb612a1a8361202c565b9260208061182186936106a1565b9091908051612a3a6114356000610564565b14612b48578115612b2d576001612a90612a8b6004612a86612a80612a70612a60885190565b612a6a6002610564565b9061287c565b612a7a6003610564565b906129fe565b91610564565b6129d5565b612a0d565b9301916020840192829083518401915b828110612ae657505050612ab357505090565b600390510680600114612ad557600214612acb575090565b6001603d91035390565b50600281603d600181940353035390565b6003600191969293960191603f828080865194848660121c168901518153018385600c1c16880151815301828460061c168701518153019116840151815301949190612aa0565b6001612a90612a8b612a70612a606004612a86612a80885190565b5050506102a46129cd565b6102a490610564565b612b8e6102a493926113eb6113eb9376020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b815260170190565b7001034b99036b4b9b9b4b733903937b6329607d1b815260110190565b90612bb96126818284611bc6565b612bc1575050565b6111e9916102a4612bf0612be0612bda612c0995612f46565b93612b53565b612bea6020610564565b90613000565b91611484612bfd60405190565b93849260208401612b5c565b6040515b62461bcd60e51b8152918291600483016104bd565b6102a4612c326118646001610564565b916118bc83612c416000610564565b906116a3565b905051906102fb8261036c565b90602082820312610230576102a491612c47565b9193612c966102a49694612402612c9d9497612c8c60a0880199600089019061205b565b602087019061205b565b6060830152565b6080818403910152610489565b60009060033d11612cb757565b905060046000803e60005160e01c90565b60009060443d106102fb5760405160043d036004823e8051906001600160401b0382113d602484011117612d345780820180519092906001600160401b038111612d2e5780602085010160043d03840110612d2e576102a49394955060200101906105e3565b50505050565b5050565b939491909294612d47826130f2565b612d54575b505050505050565b602094612d9e600092612d71612d6c612d9396610543565b610543565b9563f23a6e61939799919091612d8660405190565b9a8b998a98899760e01b90565b875260048701612c68565b03925af160009181612ec6575b50612e5857506001612dbb612caa565b6308c379a014612e38575b612dd6575b388080808080612d4c565b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608490fd5b612e40612cc8565b80612e4b5750612dc6565b6111e990612c0d60405190565b612e6b6125b063f23a6e6160e01b61035f565b14612dcb5760405162461bcd60e51b815260206004820152602860248201527f455243313135353a204552433131353552656365697665722072656a656374656044820152676420746f6b656e7360c01b6064820152608490fd5b612ee891925060203d8111612eef575b612ee081836105e3565b810190612c54565b9038612dab565b503d612ed6565b612f096125b06301ffc9a760e01b61035f565b1490565b6102a49081906001600160a01b031681565b611bb66102a46102a49290565b6102a46014612f1f565b6102a46102a46102a49260ff1690565b612f63612f5e6102a492612f58606090565b5061053a565b612f0d565b612bea612f6e612f2c565b612f36565b90612f7c825190565b811015610411570160200190565b8015611db1576000190190565b6102a490612fab6114356102a49460ff1690565b901c90565b15612fb757565b60405162461bcd60e51b8152806111e9600482016020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b919061305961304f61301c612a8b612a6085612a866002610564565b9260306130338561302d6000610564565b90612f73565b5360786130448561302d6001610564565b53612a866002610564565b612a6a6001610564565b925b836130696114356001610564565b11156130d5576f181899199a1a9b1b9c1cb0b131b232b360811b8161308e600f610564565b16916010831015610411576130ab6130c9926130cf941a60f81b90565b60001a6130b88786612f73565b536130c36004612f1f565b90612f97565b93612f8a565b9261305b565b6102a49293506102a4906130ec6114356000610564565b14612fb0565b3b6131006114356000610564565b119056fea264697066735822122048b64a70cf7789f40e045cf7a9634483d111fbdb4595c68481e2e5b84609e12364736f6c63430008180033",
  "devdoc": {
    "details": "This contract extends ERC1155 to create a multi-token contract, named DataPointsMulti, intended to represent accumulated data points within the Masa Network. Each token ID represents a different data type, and it features minting and burning capabilities, with distinct roles for each action, as well as an admin role for role management. The tokens are non-transferable, meaning they cannot be transferred between addresses once minted, making them purely a representation of earned points rather than a tradable asset. The contract utilizes OpenZeppelin's ERC1155 for the multi-token standard and AccessControl for role-based access control, respectively. It also implements the ERC1155 URI mechanism to provide on-chain metadata for each token type.",
    "events": {
      "ApprovalForAll(address,address,bool)": {
        "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`."
      },
      "RoleAdminChanged(bytes32,bytes32,bytes32)": {
        "details": "Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted signaling this. _Available since v3.1._"
      },
      "RoleGranted(bytes32,address,address)": {
        "details": "Emitted when `account` is granted `role`. `sender` is the account that originated the contract call, an admin role bearer except when using {AccessControl-_setupRole}."
      },
      "RoleRevoked(bytes32,address,address)": {
        "details": "Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call:   - if using `revokeRole`, it is the admin role bearer   - if using `renounceRole`, it is the role bearer (i.e. `account`)"
      },
      "TransferBatch(address,address,address,uint256[],uint256[])": {
        "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers."
      },
      "TransferSingle(address,address,address,uint256,uint256)": {
        "details": "Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`."
      },
      "URI(string,uint256)": {
        "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}."
      }
    },
    "kind": "dev",
    "methods": {
      "balanceOf(address,uint256)": {
        "details": "See {IERC1155-balanceOf}. Requirements: - `account` cannot be the zero address."
      },
      "balanceOfBatch(address[],uint256[])": {
        "details": "See {IERC1155-balanceOfBatch}. Requirements: - `accounts` and `ids` must have the same length."
      },
      "batchMint(address[],uint256[],uint256[])": {
        "details": "Mint batch of tokens of different types to specified addresses, each with a unique numeric UUID.",
        "params": {
          "ids": "An array of token types to mint.",
          "toAddresses": "An array of addresses to mint tokens to.",
          "uuids": "An array of numeric UUIDs for each token being minted."
        }
      },
      "constructor": {
        "details": "Initializes the contract by setting a base URI and configuring roles.",
        "params": {
          "baseUriInput": "The initial base URI for token metadata."
        }
      },
      "getAccountTokenUUIDs(address,uint256)": {
        "details": "Retrieves the UUIDs for a specific token ID associated with an account.",
        "params": {
          "account": "The address of the user to query UUIDs for.",
          "id": "The token ID to query UUIDs for."
        },
        "returns": {
          "_0": "An array of UUIDs for the specified token ID associated with the account."
        }
      },
      "getAllTokenIdMetadata()": {
        "details": "Returns an array of structs containing token IDs and their corresponding metadata.",
        "returns": {
          "_0": "An array of TokenIdMetadata structs."
        }
      },
      "getRoleAdmin(bytes32)": {
        "details": "Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."
      },
      "getTokenName(uint256)": {
        "details": "Retrieves the name of a given token ID.",
        "params": {
          "id": "The token ID."
        },
        "returns": {
          "_0": "The name of the token ID."
        }
      },
      "getUserBalances(address)": {
        "details": "Retrieves user balances for all token types.",
        "params": {
          "user": "The address of the user to query balances for."
        },
        "returns": {
          "_0": "An array of TokenBalance structs containing token names and balances."
        }
      },
      "getValidTokenIds()": {
        "details": "Public getter to access the array of valid token IDs.",
        "returns": {
          "_0": "An array of valid token IDs."
        }
      },
      "grantRole(bytes32,address)": {
        "details": "Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."
      },
      "hasRole(bytes32,address)": {
        "details": "Returns `true` if `account` has been granted `role`."
      },
      "isApprovedForAll(address,address)": {
        "details": "See {IERC1155-isApprovedForAll}."
      },
      "renounceRole(bytes32,address)": {
        "details": "Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`. May emit a {RoleRevoked} event."
      },
      "revokeRole(bytes32,address)": {
        "details": "Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."
      },
      "safeTransferFrom(address,address,uint256,uint256,bytes)": {
        "details": "Prevents token transfers by overriding `safeTransferFrom` and `safeBatchTransferFrom`."
      },
      "setApprovalForAll(address,bool)": {
        "details": "See {IERC1155-setApprovalForAll}."
      },
      "setBaseURI(string)": {
        "details": "Updates the base URI used for token metadata. Can only be called by an admin.",
        "params": {
          "newBaseURI": "The new base URI to set."
        }
      },
      "setTokenMetadata(uint256,string,string,string)": {
        "details": "Sets the metadata for a token ID. Can only be called by an admin.",
        "params": {
          "description": "The description for the token.",
          "image": "The image URL for the token.",
          "name": "The name for the token.",
          "tokenId": "The token ID to set metadata for."
        }
      },
      "setTokenName(uint256,string)": {
        "details": "Sets the name for a given token ID.",
        "params": {
          "id": "The token ID.",
          "name": "The name to assign to the token ID. Requires that the caller has the UPDATER_ROLE."
        }
      },
      "setupRole(bytes32,address)": {
        "details": "Grant or revoke role permissions dynamically.",
        "params": {
          "account": "The address to grant or revoke the role from.",
          "role": "The role identifier."
        }
      },
      "supportsInterface(bytes4)": {
        "details": "See {IERC165-supportsInterface}."
      },
      "uri(uint256)": {
        "details": "Generates a URI for a given token ID. The URI is a data URI with a JSON-formatted metadata blob. This includes the name, description, and image for the token.",
        "params": {
          "tokenId": "The token ID to generate a URI for."
        },
        "returns": {
          "_0": "The URI string for the given token ID's metadata."
        }
      }
    },
    "title": "DataPointsMulti",
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 527,
        "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
        "label": "_balances",
        "offset": 0,
        "slot": "0",
        "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))"
      },
      {
        "astId": 533,
        "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
        "label": "_operatorApprovals",
        "offset": 0,
        "slot": "1",
        "type": "t_mapping(t_address,t_mapping(t_address,t_bool))"
      },
      {
        "astId": 535,
        "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
        "label": "_uri",
        "offset": 0,
        "slot": "2",
        "type": "t_string_storage"
      },
      {
        "astId": 24,
        "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
        "label": "_roles",
        "offset": 0,
        "slot": "3",
        "type": "t_mapping(t_bytes32,t_struct(RoleData)19_storage)"
      },
      {
        "astId": 4846,
        "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
        "label": "tokenMetadata",
        "offset": 0,
        "slot": "4",
        "type": "t_mapping(t_uint256,t_struct(TokenMetadata)4830_storage)"
      },
      {
        "astId": 4853,
        "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
        "label": "accountTokenUUIDs",
        "offset": 0,
        "slot": "5",
        "type": "t_mapping(t_address,t_mapping(t_uint256,t_array(t_uint256)dyn_storage))"
      },
      {
        "astId": 4855,
        "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
        "label": "tokenTypeCount",
        "offset": 0,
        "slot": "6",
        "type": "t_uint256"
      },
      {
        "astId": 4858,
        "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
        "label": "validTokenIds",
        "offset": 0,
        "slot": "7",
        "type": "t_array(t_uint256)dyn_storage"
      },
      {
        "astId": 4860,
        "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
        "label": "baseURI",
        "offset": 0,
        "slot": "8",
        "type": "t_string_storage"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_array(t_uint256)dyn_storage": {
        "base": "t_uint256",
        "encoding": "dynamic_array",
        "label": "uint256[]",
        "numberOfBytes": "32"
      },
      "t_bool": {
        "encoding": "inplace",
        "label": "bool",
        "numberOfBytes": "1"
      },
      "t_bytes32": {
        "encoding": "inplace",
        "label": "bytes32",
        "numberOfBytes": "32"
      },
      "t_mapping(t_address,t_bool)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => bool)",
        "numberOfBytes": "32",
        "value": "t_bool"
      },
      "t_mapping(t_address,t_mapping(t_address,t_bool))": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => mapping(address => bool))",
        "numberOfBytes": "32",
        "value": "t_mapping(t_address,t_bool)"
      },
      "t_mapping(t_address,t_mapping(t_uint256,t_array(t_uint256)dyn_storage))": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => mapping(uint256 => uint256[]))",
        "numberOfBytes": "32",
        "value": "t_mapping(t_uint256,t_array(t_uint256)dyn_storage)"
      },
      "t_mapping(t_address,t_uint256)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_mapping(t_bytes32,t_struct(RoleData)19_storage)": {
        "encoding": "mapping",
        "key": "t_bytes32",
        "label": "mapping(bytes32 => struct AccessControl.RoleData)",
        "numberOfBytes": "32",
        "value": "t_struct(RoleData)19_storage"
      },
      "t_mapping(t_uint256,t_array(t_uint256)dyn_storage)": {
        "encoding": "mapping",
        "key": "t_uint256",
        "label": "mapping(uint256 => uint256[])",
        "numberOfBytes": "32",
        "value": "t_array(t_uint256)dyn_storage"
      },
      "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": {
        "encoding": "mapping",
        "key": "t_uint256",
        "label": "mapping(uint256 => mapping(address => uint256))",
        "numberOfBytes": "32",
        "value": "t_mapping(t_address,t_uint256)"
      },
      "t_mapping(t_uint256,t_struct(TokenMetadata)4830_storage)": {
        "encoding": "mapping",
        "key": "t_uint256",
        "label": "mapping(uint256 => struct DataPointsMulti.TokenMetadata)",
        "numberOfBytes": "32",
        "value": "t_struct(TokenMetadata)4830_storage"
      },
      "t_string_storage": {
        "encoding": "bytes",
        "label": "string",
        "numberOfBytes": "32"
      },
      "t_struct(RoleData)19_storage": {
        "encoding": "inplace",
        "label": "struct AccessControl.RoleData",
        "members": [
          {
            "astId": 16,
            "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
            "label": "members",
            "offset": 0,
            "slot": "0",
            "type": "t_mapping(t_address,t_bool)"
          },
          {
            "astId": 18,
            "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
            "label": "adminRole",
            "offset": 0,
            "slot": "1",
            "type": "t_bytes32"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_struct(TokenMetadata)4830_storage": {
        "encoding": "inplace",
        "label": "struct DataPointsMulti.TokenMetadata",
        "members": [
          {
            "astId": 4825,
            "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
            "label": "name",
            "offset": 0,
            "slot": "0",
            "type": "t_string_storage"
          },
          {
            "astId": 4827,
            "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
            "label": "image",
            "offset": 0,
            "slot": "1",
            "type": "t_string_storage"
          },
          {
            "astId": 4829,
            "contract": "contracts/DataPointsMulti.sol:DataPointsMulti",
            "label": "description",
            "offset": 0,
            "slot": "2",
            "type": "t_string_storage"
          }
        ],
        "numberOfBytes": "96"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      }
    }
  }
}