{
  "address": "0xB27f379C050f6eD0973A01667458af6eCeBc1d90",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "string",
          "name": "_name",
          "type": "string"
        },
        {
          "internalType": "string",
          "name": "_symbol",
          "type": "string"
        },
        {
          "internalType": "uint8",
          "name": "decimals_",
          "type": "uint8"
        },
        {
          "internalType": "address",
          "name": "_controller",
          "type": "address"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        }
      ],
      "name": "Approval",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "delegator",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "delegate",
          "type": "address"
        }
      ],
      "name": "Delegated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "string",
          "name": "name",
          "type": "string"
        },
        {
          "indexed": false,
          "internalType": "string",
          "name": "symbol",
          "type": "string"
        },
        {
          "indexed": false,
          "internalType": "uint8",
          "name": "decimals",
          "type": "uint8"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "controller",
          "type": "address"
        }
      ],
      "name": "Deployed",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "components": [
            {
              "internalType": "uint224",
              "name": "amount",
              "type": "uint224"
            },
            {
              "internalType": "uint32",
              "name": "timestamp",
              "type": "uint32"
            }
          ],
          "indexed": false,
          "internalType": "struct ObservationLib.Observation",
          "name": "newTotalSupplyTwab",
          "type": "tuple"
        }
      ],
      "name": "NewTotalSupplyTwab",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "delegate",
          "type": "address"
        },
        {
          "components": [
            {
              "internalType": "uint224",
              "name": "amount",
              "type": "uint224"
            },
            {
              "internalType": "uint32",
              "name": "timestamp",
              "type": "uint32"
            }
          ],
          "indexed": false,
          "internalType": "struct ObservationLib.Observation",
          "name": "newTwab",
          "type": "tuple"
        }
      ],
      "name": "NewUserTwab",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "string",
          "name": "name",
          "type": "string"
        },
        {
          "indexed": false,
          "internalType": "string",
          "name": "symbol",
          "type": "string"
        },
        {
          "indexed": false,
          "internalType": "uint8",
          "name": "decimals",
          "type": "uint8"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "controller",
          "type": "address"
        }
      ],
      "name": "TicketInitialized",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "from",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "to",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        }
      ],
      "name": "Transfer",
      "type": "event"
    },
    {
      "inputs": [],
      "name": "DOMAIN_SEPARATOR",
      "outputs": [
        {
          "internalType": "bytes32",
          "name": "",
          "type": "bytes32"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        }
      ],
      "name": "allowance",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "approve",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "balanceOf",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "controller",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_amount",
          "type": "uint256"
        }
      ],
      "name": "controllerBurn",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_operator",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_amount",
          "type": "uint256"
        }
      ],
      "name": "controllerBurnFrom",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_to",
          "type": "address"
        }
      ],
      "name": "controllerDelegateFor",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_amount",
          "type": "uint256"
        }
      ],
      "name": "controllerMint",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "decimals",
      "outputs": [
        {
          "internalType": "uint8",
          "name": "",
          "type": "uint8"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "subtractedValue",
          "type": "uint256"
        }
      ],
      "name": "decreaseAllowance",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_to",
          "type": "address"
        }
      ],
      "name": "delegate",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        }
      ],
      "name": "delegateOf",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "_newDelegate",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "_deadline",
          "type": "uint256"
        },
        {
          "internalType": "uint8",
          "name": "_v",
          "type": "uint8"
        },
        {
          "internalType": "bytes32",
          "name": "_r",
          "type": "bytes32"
        },
        {
          "internalType": "bytes32",
          "name": "_s",
          "type": "bytes32"
        }
      ],
      "name": "delegateWithSignature",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        }
      ],
      "name": "getAccountDetails",
      "outputs": [
        {
          "components": [
            {
              "internalType": "uint208",
              "name": "balance",
              "type": "uint208"
            },
            {
              "internalType": "uint24",
              "name": "nextTwabIndex",
              "type": "uint24"
            },
            {
              "internalType": "uint24",
              "name": "cardinality",
              "type": "uint24"
            }
          ],
          "internalType": "struct TwabLib.AccountDetails",
          "name": "",
          "type": "tuple"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "uint64",
          "name": "_startTime",
          "type": "uint64"
        },
        {
          "internalType": "uint64",
          "name": "_endTime",
          "type": "uint64"
        }
      ],
      "name": "getAverageBalanceBetween",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "uint64[]",
          "name": "_startTimes",
          "type": "uint64[]"
        },
        {
          "internalType": "uint64[]",
          "name": "_endTimes",
          "type": "uint64[]"
        }
      ],
      "name": "getAverageBalancesBetween",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint64[]",
          "name": "_startTimes",
          "type": "uint64[]"
        },
        {
          "internalType": "uint64[]",
          "name": "_endTimes",
          "type": "uint64[]"
        }
      ],
      "name": "getAverageTotalSuppliesBetween",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "uint64",
          "name": "_target",
          "type": "uint64"
        }
      ],
      "name": "getBalanceAt",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "uint64[]",
          "name": "_targets",
          "type": "uint64[]"
        }
      ],
      "name": "getBalancesAt",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint64[]",
          "name": "_targets",
          "type": "uint64[]"
        }
      ],
      "name": "getTotalSuppliesAt",
      "outputs": [
        {
          "internalType": "uint256[]",
          "name": "",
          "type": "uint256[]"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint64",
          "name": "_target",
          "type": "uint64"
        }
      ],
      "name": "getTotalSupplyAt",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "_user",
          "type": "address"
        },
        {
          "internalType": "uint16",
          "name": "_index",
          "type": "uint16"
        }
      ],
      "name": "getTwab",
      "outputs": [
        {
          "components": [
            {
              "internalType": "uint224",
              "name": "amount",
              "type": "uint224"
            },
            {
              "internalType": "uint32",
              "name": "timestamp",
              "type": "uint32"
            }
          ],
          "internalType": "struct ObservationLib.Observation",
          "name": "",
          "type": "tuple"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "addedValue",
          "type": "uint256"
        }
      ],
      "name": "increaseAllowance",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "name",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        }
      ],
      "name": "nonces",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "value",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "deadline",
          "type": "uint256"
        },
        {
          "internalType": "uint8",
          "name": "v",
          "type": "uint8"
        },
        {
          "internalType": "bytes32",
          "name": "r",
          "type": "bytes32"
        },
        {
          "internalType": "bytes32",
          "name": "s",
          "type": "bytes32"
        }
      ],
      "name": "permit",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "symbol",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "totalSupply",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "recipient",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "transfer",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "sender",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "recipient",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "transferFrom",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0x37bc7fda3c28fffe20e50cc4cc6f796d91f3dd00f29923914ff08a87d8cec727",
  "receipt": {
    "to": null,
    "from": "0x21E8fFC0108B0cbA465E26cA0a0EA3955475e9b2",
    "contractAddress": "0xB27f379C050f6eD0973A01667458af6eCeBc1d90",
    "transactionIndex": 2,
    "gasUsed": "3129824",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000020000000000080000000000000020000002000000000000000000000000000000000000000",
    "blockHash": "0x93f8733cda9a17e4941f7d7315dc7c4e0397f5ba180e2ba74ee5525604fe0838",
    "transactionHash": "0x37bc7fda3c28fffe20e50cc4cc6f796d91f3dd00f29923914ff08a87d8cec727",
    "logs": [
      {
        "transactionIndex": 2,
        "blockNumber": 8501295,
        "transactionHash": "0x37bc7fda3c28fffe20e50cc4cc6f796d91f3dd00f29923914ff08a87d8cec727",
        "address": "0xB27f379C050f6eD0973A01667458af6eCeBc1d90",
        "topics": [
          "0xde72fc29218361f33503847e6f32be813f9ec92fc7c772bb59e46675c890fd0e",
          "0x000000000000000000000000f830f5cb2422d555ec34178e27094a816c8f95ec"
        ],
        "data": "0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001b506f6f6c546f6765746865722061765553444365205469636b6574000000000000000000000000000000000000000000000000000000000000000000000000095054617655534443650000000000000000000000000000000000000000000000",
        "logIndex": 5,
        "blockHash": "0x93f8733cda9a17e4941f7d7315dc7c4e0397f5ba180e2ba74ee5525604fe0838"
      }
    ],
    "blockNumber": 8501295,
    "cumulativeGasUsed": "3319051",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "PoolTogether avUSDCe Ticket",
    "PTavUSDCe",
    6,
    "0xF830F5Cb2422d555EC34178E27094a816c8F95EC"
  ],
  "solcInputHash": "8de2730cf5e263103c2ac52c02e7eaa7",
  "metadata": "{\"compiler\":{\"version\":\"0.8.6+commit.11564f7e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"_controller\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"}],\"name\":\"Delegated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"controller\",\"type\":\"address\"}],\"name\":\"Deployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"amount\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"struct ObservationLib.Observation\",\"name\":\"newTotalSupplyTwab\",\"type\":\"tuple\"}],\"name\":\"NewTotalSupplyTwab\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint224\",\"name\":\"amount\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"struct ObservationLib.Observation\",\"name\":\"newTwab\",\"type\":\"tuple\"}],\"name\":\"NewUserTwab\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"controller\",\"type\":\"address\"}],\"name\":\"TicketInitialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"controller\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"controllerBurn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"controllerBurnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"controllerDelegateFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"controllerMint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"}],\"name\":\"delegateOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_newDelegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"}],\"name\":\"delegateWithSignature\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"}],\"name\":\"getAccountDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"uint208\",\"name\":\"balance\",\"type\":\"uint208\"},{\"internalType\":\"uint24\",\"name\":\"nextTwabIndex\",\"type\":\"uint24\"},{\"internalType\":\"uint24\",\"name\":\"cardinality\",\"type\":\"uint24\"}],\"internalType\":\"struct TwabLib.AccountDetails\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"_startTime\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"_endTime\",\"type\":\"uint64\"}],\"name\":\"getAverageBalanceBetween\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"uint64[]\",\"name\":\"_startTimes\",\"type\":\"uint64[]\"},{\"internalType\":\"uint64[]\",\"name\":\"_endTimes\",\"type\":\"uint64[]\"}],\"name\":\"getAverageBalancesBetween\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"_startTimes\",\"type\":\"uint64[]\"},{\"internalType\":\"uint64[]\",\"name\":\"_endTimes\",\"type\":\"uint64[]\"}],\"name\":\"getAverageTotalSuppliesBetween\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"_target\",\"type\":\"uint64\"}],\"name\":\"getBalanceAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"uint64[]\",\"name\":\"_targets\",\"type\":\"uint64[]\"}],\"name\":\"getBalancesAt\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"_targets\",\"type\":\"uint64[]\"}],\"name\":\"getTotalSuppliesAt\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_target\",\"type\":\"uint64\"}],\"name\":\"getTotalSupplyAt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_index\",\"type\":\"uint16\"}],\"name\":\"getTwab\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"amount\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"struct ObservationLib.Observation\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"PoolTogether Inc Team\",\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"See {IERC20Permit-DOMAIN_SEPARATOR}.\"},\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"constructor\":{\"params\":{\"_controller\":\"ERC20 ticket controller address (ie: Prize Pool address).\",\"_name\":\"ERC20 ticket token name.\",\"_symbol\":\"ERC20 ticket token symbol.\",\"decimals_\":\"ERC20 ticket token decimals.\"}},\"controllerBurn(address,uint256)\":{\"details\":\"May be overridden to provide more granular control over burning\",\"params\":{\"_amount\":\"Amount of tokens to burn\",\"_user\":\"Address of the holder account to burn tokens from\"}},\"controllerBurnFrom(address,address,uint256)\":{\"details\":\"May be overridden to provide more granular control over operator-burning\",\"params\":{\"_amount\":\"Amount of tokens to burn\",\"_operator\":\"Address of the operator performing the burn action via the controller contract\",\"_user\":\"Address of the holder account to burn tokens from\"}},\"controllerDelegateFor(address,address)\":{\"params\":{\"delegate\":\"The new delegate\",\"user\":\"The user for whom to delegate\"}},\"controllerMint(address,uint256)\":{\"details\":\"May be overridden to provide more granular control over minting\",\"params\":{\"_amount\":\"Amount of tokens to mint\",\"_user\":\"Address of the receiver of the minted tokens\"}},\"decimals()\":{\"details\":\"This value should be equal to the decimals of the token used to deposit into the pool.\",\"returns\":{\"_0\":\"uint8 decimals.\"}},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"delegate(address)\":{\"details\":\"Transfers (including mints) trigger the storage of a TWAB in delegate(s) account, instead of the targetted sender and/or recipient address(s).To reset the delegate, pass the zero address (0x000.000) as `to` parameter.Current delegate address should be different from the new delegate address `to`.\",\"params\":{\"to\":\"Recipient of delegated TWAB.\"}},\"delegateOf(address)\":{\"details\":\"Address of the delegate will be the zero address if `user` has not delegated their tickets.\",\"params\":{\"user\":\"Address of the delegator.\"},\"returns\":{\"_0\":\"Address of the delegate.\"}},\"delegateWithSignature(address,address,uint256,uint8,bytes32,bytes32)\":{\"params\":{\"deadline\":\"The timestamp by which this must be submitted\",\"delegate\":\"The new delegate\",\"r\":\"The r portion of the ECDSA sig\",\"s\":\"The s portion of the ECDSA sig\",\"user\":\"The user who is delegating\",\"v\":\"The v portion of the ECDSA sig\"}},\"getAccountDetails(address)\":{\"params\":{\"user\":\"The user for whom to fetch the TWAB context.\"},\"returns\":{\"_0\":\"The TWAB context, which includes { balance, nextTwabIndex, cardinality }\"}},\"getAverageBalanceBetween(address,uint64,uint64)\":{\"params\":{\"endTime\":\"The end time of the time frame.\",\"startTime\":\"The start time of the time frame.\",\"user\":\"The user whose balance is checked.\"},\"returns\":{\"_0\":\"The average balance that the user held during the time frame.\"}},\"getAverageBalancesBetween(address,uint64[],uint64[])\":{\"params\":{\"endTimes\":\"The end time of the time frame.\",\"startTimes\":\"The start time of the time frame.\",\"user\":\"The user whose balance is checked.\"},\"returns\":{\"_0\":\"The average balance that the user held during the time frame.\"}},\"getAverageTotalSuppliesBetween(uint64[],uint64[])\":{\"params\":{\"endTimes\":\"Array of end times.\",\"startTimes\":\"Array of start times.\"},\"returns\":{\"_0\":\"The average total supplies held during the time frame.\"}},\"getBalanceAt(address,uint64)\":{\"params\":{\"timestamp\":\"Timestamp at which we want to retrieve the TWAB balance.\",\"user\":\"Address of the user whose TWAB is being fetched.\"},\"returns\":{\"_0\":\"The TWAB balance at the given timestamp.\"}},\"getBalancesAt(address,uint64[])\":{\"params\":{\"timestamps\":\"Timestamps range at which we want to retrieve the TWAB balances.\",\"user\":\"Address of the user whose TWABs are being fetched.\"},\"returns\":{\"_0\":\"`user` TWAB balances.\"}},\"getTotalSuppliesAt(uint64[])\":{\"params\":{\"timestamps\":\"Timestamps range at which we want to retrieve the total supply TWAB balance.\"},\"returns\":{\"_0\":\"Total supply TWAB balances.\"}},\"getTotalSupplyAt(uint64)\":{\"params\":{\"timestamp\":\"Timestamp at which we want to retrieve the total supply TWAB balance.\"},\"returns\":{\"_0\":\"The total supply TWAB balance at the given timestamp.\"}},\"getTwab(address,uint16)\":{\"params\":{\"index\":\"The index of the TWAB to fetch.\",\"user\":\"The user for whom to fetch the TWAB.\"},\"returns\":{\"_0\":\"The TWAB, which includes the twab amount and the timestamp.\"}},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"nonces(address)\":{\"details\":\"See {IERC20Permit-nonces}.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"See {IERC20Permit-permit}.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"}},\"title\":\"PoolTogether V4 Ticket\",\"version\":1},\"userdoc\":{\"events\":{\"Delegated(address,address)\":{\"notice\":\"Emitted when TWAB balance has been delegated to another user.\"},\"NewTotalSupplyTwab((uint224,uint32))\":{\"notice\":\"Emitted when a new total supply TWAB has been recorded.\"},\"NewUserTwab(address,(uint224,uint32))\":{\"notice\":\"Emitted when a new TWAB has been recorded.\"},\"TicketInitialized(string,string,uint8,address)\":{\"notice\":\"Emitted when ticket is initialized.\"}},\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Constructs Ticket with passed parameters.\"},\"controller()\":{\"notice\":\"Interface to the contract responsible for controlling mint/burn\"},\"controllerBurn(address,uint256)\":{\"notice\":\"Allows the controller to burn tokens from a user account\"},\"controllerBurnFrom(address,address,uint256)\":{\"notice\":\"Allows an operator via the controller to burn tokens on behalf of a user account\"},\"controllerDelegateFor(address,address)\":{\"notice\":\"Allows the controller to delegate on a users behalf.\"},\"controllerMint(address,uint256)\":{\"notice\":\"Allows the controller to mint tokens for a user account\"},\"decimals()\":{\"notice\":\"Returns the ERC20 controlled token decimals.\"},\"delegate(address)\":{\"notice\":\"Delegate time-weighted average balances to an alternative address.\"},\"delegateOf(address)\":{\"notice\":\"Retrieves the address of the delegate to whom `user` has delegated their tickets.\"},\"delegateWithSignature(address,address,uint256,uint8,bytes32,bytes32)\":{\"notice\":\"Allows a user to delegate via signature\"},\"getAccountDetails(address)\":{\"notice\":\"Gets a users twab context.  This is a struct with their balance, next twab index, and cardinality.\"},\"getAverageBalanceBetween(address,uint64,uint64)\":{\"notice\":\"Retrieves the average balance held by a user for a given time frame.\"},\"getAverageBalancesBetween(address,uint64[],uint64[])\":{\"notice\":\"Retrieves the average balances held by a user for a given time frame.\"},\"getAverageTotalSuppliesBetween(uint64[],uint64[])\":{\"notice\":\"Retrieves the average total supply balance for a set of given time frames.\"},\"getBalanceAt(address,uint64)\":{\"notice\":\"Retrieves `user` TWAB balance.\"},\"getBalancesAt(address,uint64[])\":{\"notice\":\"Retrieves `user` TWAB balances.\"},\"getTotalSuppliesAt(uint64[])\":{\"notice\":\"Retrieves the total supply TWAB balance between the given timestamps range.\"},\"getTotalSupplyAt(uint64)\":{\"notice\":\"Retrieves the total supply TWAB balance at the given timestamp.\"},\"getTwab(address,uint16)\":{\"notice\":\"Gets the TWAB at a specific index for a user.\"}},\"notice\":\"The Ticket extends the standard ERC20 and ControlledToken interfaces with time-weighted average balance functionality. The average balance held by a user between two timestamps can be calculated, as well as the historic balance.  The historic total supply is available as well as the average total supply between two timestamps. A user may \\\"delegate\\\" their balance; increasing another user's historic balance while retaining their tokens.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"@pooltogether/v4-core/contracts/Ticket.sol\":\"Ticket\"},\"evmVersion\":\"berlin\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":2000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n    mapping(address => uint256) private _balances;\\n\\n    mapping(address => mapping(address => uint256)) private _allowances;\\n\\n    uint256 private _totalSupply;\\n\\n    string private _name;\\n    string private _symbol;\\n\\n    /**\\n     * @dev Sets the values for {name} and {symbol}.\\n     *\\n     * The default value of {decimals} is 18. To select a different value for\\n     * {decimals} you should overload it.\\n     *\\n     * All two of these values are immutable: they can only be set once during\\n     * construction.\\n     */\\n    constructor(string memory name_, string memory symbol_) {\\n        _name = name_;\\n        _symbol = symbol_;\\n    }\\n\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() public view virtual override returns (string memory) {\\n        return _name;\\n    }\\n\\n    /**\\n     * @dev Returns the symbol of the token, usually a shorter version of the\\n     * name.\\n     */\\n    function symbol() public view virtual override returns (string memory) {\\n        return _symbol;\\n    }\\n\\n    /**\\n     * @dev Returns the number of decimals used to get its user representation.\\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n     *\\n     * Tokens usually opt for a value of 18, imitating the relationship between\\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n     * overridden;\\n     *\\n     * NOTE: This information is only used for _display_ purposes: it in\\n     * no way affects any of the arithmetic of the contract, including\\n     * {IERC20-balanceOf} and {IERC20-transfer}.\\n     */\\n    function decimals() public view virtual override returns (uint8) {\\n        return 18;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-totalSupply}.\\n     */\\n    function totalSupply() public view virtual override returns (uint256) {\\n        return _totalSupply;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-balanceOf}.\\n     */\\n    function balanceOf(address account) public view virtual override returns (uint256) {\\n        return _balances[account];\\n    }\\n\\n    /**\\n     * @dev See {IERC20-transfer}.\\n     *\\n     * Requirements:\\n     *\\n     * - `recipient` cannot be the zero address.\\n     * - the caller must have a balance of at least `amount`.\\n     */\\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n        _transfer(_msgSender(), recipient, amount);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-allowance}.\\n     */\\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n        return _allowances[owner][spender];\\n    }\\n\\n    /**\\n     * @dev See {IERC20-approve}.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n        _approve(_msgSender(), spender, amount);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev See {IERC20-transferFrom}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance. This is not\\n     * required by the EIP. See the note at the beginning of {ERC20}.\\n     *\\n     * Requirements:\\n     *\\n     * - `sender` and `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     * - the caller must have allowance for ``sender``'s tokens of at least\\n     * `amount`.\\n     */\\n    function transferFrom(\\n        address sender,\\n        address recipient,\\n        uint256 amount\\n    ) public virtual override returns (bool) {\\n        _transfer(sender, recipient, amount);\\n\\n        uint256 currentAllowance = _allowances[sender][_msgSender()];\\n        require(currentAllowance >= amount, \\\"ERC20: transfer amount exceeds allowance\\\");\\n        unchecked {\\n            _approve(sender, _msgSender(), currentAllowance - amount);\\n        }\\n\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\\n     *\\n     * This is an alternative to {approve} that can be used as a mitigation for\\n     * problems described in {IERC20-approve}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     */\\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n     *\\n     * This is an alternative to {approve} that can be used as a mitigation for\\n     * problems described in {IERC20-approve}.\\n     *\\n     * Emits an {Approval} event indicating the updated allowance.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     * - `spender` must have allowance for the caller of at least\\n     * `subtractedValue`.\\n     */\\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n        uint256 currentAllowance = _allowances[_msgSender()][spender];\\n        require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n        unchecked {\\n            _approve(_msgSender(), spender, currentAllowance - subtractedValue);\\n        }\\n\\n        return true;\\n    }\\n\\n    /**\\n     * @dev Moves `amount` of tokens from `sender` to `recipient`.\\n     *\\n     * This internal function is equivalent to {transfer}, and can be used to\\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\\n     *\\n     * Emits a {Transfer} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `sender` cannot be the zero address.\\n     * - `recipient` cannot be the zero address.\\n     * - `sender` must have a balance of at least `amount`.\\n     */\\n    function _transfer(\\n        address sender,\\n        address recipient,\\n        uint256 amount\\n    ) internal virtual {\\n        require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n        require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n        _beforeTokenTransfer(sender, recipient, amount);\\n\\n        uint256 senderBalance = _balances[sender];\\n        require(senderBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n        unchecked {\\n            _balances[sender] = senderBalance - amount;\\n        }\\n        _balances[recipient] += amount;\\n\\n        emit Transfer(sender, recipient, amount);\\n\\n        _afterTokenTransfer(sender, recipient, amount);\\n    }\\n\\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n     * the total supply.\\n     *\\n     * Emits a {Transfer} event with `from` set to the zero address.\\n     *\\n     * Requirements:\\n     *\\n     * - `account` cannot be the zero address.\\n     */\\n    function _mint(address account, uint256 amount) internal virtual {\\n        require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n        _beforeTokenTransfer(address(0), account, amount);\\n\\n        _totalSupply += amount;\\n        _balances[account] += amount;\\n        emit Transfer(address(0), account, amount);\\n\\n        _afterTokenTransfer(address(0), account, amount);\\n    }\\n\\n    /**\\n     * @dev Destroys `amount` tokens from `account`, reducing the\\n     * total supply.\\n     *\\n     * Emits a {Transfer} event with `to` set to the zero address.\\n     *\\n     * Requirements:\\n     *\\n     * - `account` cannot be the zero address.\\n     * - `account` must have at least `amount` tokens.\\n     */\\n    function _burn(address account, uint256 amount) internal virtual {\\n        require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n        _beforeTokenTransfer(account, address(0), amount);\\n\\n        uint256 accountBalance = _balances[account];\\n        require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n        unchecked {\\n            _balances[account] = accountBalance - amount;\\n        }\\n        _totalSupply -= amount;\\n\\n        emit Transfer(account, address(0), amount);\\n\\n        _afterTokenTransfer(account, address(0), amount);\\n    }\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n     *\\n     * This internal function is equivalent to `approve`, and can be used to\\n     * e.g. set automatic allowances for certain subsystems, etc.\\n     *\\n     * Emits an {Approval} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `owner` cannot be the zero address.\\n     * - `spender` cannot be the zero address.\\n     */\\n    function _approve(\\n        address owner,\\n        address spender,\\n        uint256 amount\\n    ) internal virtual {\\n        require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n        require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n        _allowances[owner][spender] = amount;\\n        emit Approval(owner, spender, amount);\\n    }\\n\\n    /**\\n     * @dev Hook that is called before any transfer of tokens. This includes\\n     * minting and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n     * will be transferred to `to`.\\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n     * - `from` and `to` are never both zero.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _beforeTokenTransfer(\\n        address from,\\n        address to,\\n        uint256 amount\\n    ) internal virtual {}\\n\\n    /**\\n     * @dev Hook that is called after any transfer of tokens. This includes\\n     * minting and burning.\\n     *\\n     * Calling conditions:\\n     *\\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n     * has been transferred to `to`.\\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n     * - `from` and `to` are never both zero.\\n     *\\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n     */\\n    function _afterTokenTransfer(\\n        address from,\\n        address to,\\n        uint256 amount\\n    ) internal virtual {}\\n}\\n\",\"keccak256\":\"0xb03df8481a954604ad0c9125680893b2e3f7ff770fe470e38b89ac61b84e8072\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n    /**\\n     * @dev Returns the amount of tokens in existence.\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the amount of tokens owned by `account`.\\n     */\\n    function balanceOf(address account) external view returns (uint256);\\n\\n    /**\\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Returns the remaining number of tokens that `spender` will be\\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n     * zero by default.\\n     *\\n     * This value changes when {approve} or {transferFrom} are called.\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    /**\\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n     * that someone may use both the old and the new allowance by unfortunate\\n     * transaction ordering. One possible solution to mitigate this race\\n     * condition is to first reduce the spender's allowance to 0 and set the\\n     * desired value afterwards:\\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n     *\\n     * Emits an {Approval} event.\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    /**\\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n     * allowance mechanism. `amount` is then deducted from the caller's\\n     * allowance.\\n     *\\n     * Returns a boolean value indicating whether the operation succeeded.\\n     *\\n     * Emits a {Transfer} event.\\n     */\\n    function transferFrom(\\n        address sender,\\n        address recipient,\\n        uint256 amount\\n    ) external returns (bool);\\n\\n    /**\\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n     * another (`to`).\\n     *\\n     * Note that `value` may be zero.\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n    /**\\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n     * a call to {approve}. `value` is the new allowance.\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x027b891937d20ccf213fdb9c31531574256de774bda99d3a70ecef6e1913ed2a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n    /**\\n     * @dev Returns the name of the token.\\n     */\\n    function name() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the symbol of the token.\\n     */\\n    function symbol() external view returns (string memory);\\n\\n    /**\\n     * @dev Returns the decimals places of the token.\\n     */\\n    function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x83fe24f5c04a56091e50f4a345ff504c8bff658a76d4c43b16878c8f940c53b2\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./draft-IERC20Permit.sol\\\";\\nimport \\\"../ERC20.sol\\\";\\nimport \\\"../../../utils/cryptography/draft-EIP712.sol\\\";\\nimport \\\"../../../utils/cryptography/ECDSA.sol\\\";\\nimport \\\"../../../utils/Counters.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n *\\n * _Available since v3.4._\\n */\\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\\n    using Counters for Counters.Counter;\\n\\n    mapping(address => Counters.Counter) private _nonces;\\n\\n    // solhint-disable-next-line var-name-mixedcase\\n    bytes32 private immutable _PERMIT_TYPEHASH =\\n        keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n\\n    /**\\n     * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n     *\\n     * It's a good idea to use the same `name` that is defined as the ERC20 token name.\\n     */\\n    constructor(string memory name) EIP712(name, \\\"1\\\") {}\\n\\n    /**\\n     * @dev See {IERC20Permit-permit}.\\n     */\\n    function permit(\\n        address owner,\\n        address spender,\\n        uint256 value,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) public virtual override {\\n        require(block.timestamp <= deadline, \\\"ERC20Permit: expired deadline\\\");\\n\\n        bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n\\n        address signer = ECDSA.recover(hash, v, r, s);\\n        require(signer == owner, \\\"ERC20Permit: invalid signature\\\");\\n\\n        _approve(owner, spender, value);\\n    }\\n\\n    /**\\n     * @dev See {IERC20Permit-nonces}.\\n     */\\n    function nonces(address owner) public view virtual override returns (uint256) {\\n        return _nonces[owner].current();\\n    }\\n\\n    /**\\n     * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view override returns (bytes32) {\\n        return _domainSeparatorV4();\\n    }\\n\\n    /**\\n     * @dev \\\"Consume a nonce\\\": return the current value and increment.\\n     *\\n     * _Available since v4.1._\\n     */\\n    function _useNonce(address owner) internal virtual returns (uint256 current) {\\n        Counters.Counter storage nonce = _nonces[owner];\\n        current = nonce.current();\\n        nonce.increment();\\n    }\\n}\\n\",\"keccak256\":\"0x7ce4684ee1fac31ee5671df82b30c10bd2ebf88add2f63524ed00618a8486907\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n    /**\\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n     * given ``owner``'s signed approval.\\n     *\\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n     * ordering also apply here.\\n     *\\n     * Emits an {Approval} event.\\n     *\\n     * Requirements:\\n     *\\n     * - `spender` cannot be the zero address.\\n     * - `deadline` must be a timestamp in the future.\\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n     * over the EIP712-formatted function arguments.\\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\\n     *\\n     * For more information on the signature format, see the\\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n     * section].\\n     */\\n    function permit(\\n        address owner,\\n        address spender,\\n        uint256 value,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external;\\n\\n    /**\\n     * @dev Returns the current nonce for `owner`. This value must be\\n     * included whenever a signature is generated for {permit}.\\n     *\\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n     * prevents a signature from being used multiple times.\\n     */\\n    function nonces(address owner) external view returns (uint256);\\n\\n    /**\\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n     */\\n    // solhint-disable-next-line func-name-mixedcase\\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x3aab711a5f9a5a5a394191e928cc8258e8a243e855bb0275e7834f9686383277\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n    using Address for address;\\n\\n    function safeTransfer(\\n        IERC20 token,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n    }\\n\\n    function safeTransferFrom(\\n        IERC20 token,\\n        address from,\\n        address to,\\n        uint256 value\\n    ) internal {\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n    }\\n\\n    /**\\n     * @dev Deprecated. This function has issues similar to the ones found in\\n     * {IERC20-approve}, and its usage is discouraged.\\n     *\\n     * Whenever possible, use {safeIncreaseAllowance} and\\n     * {safeDecreaseAllowance} instead.\\n     */\\n    function safeApprove(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        // safeApprove should only be called when setting an initial allowance,\\n        // or when resetting it to zero. To increase and decrease it, use\\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n        require(\\n            (value == 0) || (token.allowance(address(this), spender) == 0),\\n            \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n        );\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n    }\\n\\n    function safeIncreaseAllowance(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n    }\\n\\n    function safeDecreaseAllowance(\\n        IERC20 token,\\n        address spender,\\n        uint256 value\\n    ) internal {\\n        unchecked {\\n            uint256 oldAllowance = token.allowance(address(this), spender);\\n            require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n            uint256 newAllowance = oldAllowance - value;\\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n        }\\n    }\\n\\n    /**\\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\\n     * @param token The token targeted by the call.\\n     * @param data The call data (encoded using abi.encode or one of its variants).\\n     */\\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n        // the target address contains contract code and also asserts for success in the low-level call.\\n\\n        bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n        if (returndata.length > 0) {\\n            // Return data is optional\\n            require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x02348b2e4b9f3200c7e3907c5c2661643a6d8520e9f79939fbb9b4005a54894d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\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     */\\n    function isContract(address account) internal view returns (bool) {\\n        // This method relies on extcodesize, which returns 0 for contracts in\\n        // construction, since the code is only stored at the end of the\\n        // constructor execution.\\n\\n        uint256 size;\\n        assembly {\\n            size := extcodesize(account)\\n        }\\n        return size > 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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, \\\"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(\\n        address target,\\n        bytes memory data,\\n        uint256 value\\n    ) 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        require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\\n        return verifyCallResult(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        require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n        (bool success, bytes memory returndata) = target.staticcall(data);\\n        return verifyCallResult(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        require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n        (bool success, bytes memory returndata) = target.delegatecall(data);\\n        return verifyCallResult(success, returndata, errorMessage);\\n    }\\n\\n    /**\\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n     * revert reason 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            // 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\\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}\\n\",\"keccak256\":\"0x3336baae5cf23e94274d75336e2d412193be508504aee185e61dc7d58cd05c8a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\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\",\"keccak256\":\"0x90565a39ae45c80f0468dc96c7b20d0afc3055f344c8203a0c9258239f350b9f\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Counters.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Counters\\n * @author Matt Condon (@shrugs)\\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\\n *\\n * Include with `using Counters for Counters.Counter;`\\n */\\nlibrary Counters {\\n    struct Counter {\\n        // This variable should never be directly accessed by users of the library: interactions must be restricted to\\n        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\\n        // this feature: see https://github.com/ethereum/solidity/issues/4637\\n        uint256 _value; // default: 0\\n    }\\n\\n    function current(Counter storage counter) internal view returns (uint256) {\\n        return counter._value;\\n    }\\n\\n    function increment(Counter storage counter) internal {\\n        unchecked {\\n            counter._value += 1;\\n        }\\n    }\\n\\n    function decrement(Counter storage counter) internal {\\n        uint256 value = counter._value;\\n        require(value > 0, \\\"Counter: decrement overflow\\\");\\n        unchecked {\\n            counter._value = value - 1;\\n        }\\n    }\\n\\n    function reset(Counter storage counter) internal {\\n        counter._value = 0;\\n    }\\n}\\n\",\"keccak256\":\"0x78450f4e3b722cce467b21e285f72ce5eaf361e9ba9dd2241a413926246773cd\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n    enum RecoverError {\\n        NoError,\\n        InvalidSignature,\\n        InvalidSignatureLength,\\n        InvalidSignatureS,\\n        InvalidSignatureV\\n    }\\n\\n    function _throwError(RecoverError error) private pure {\\n        if (error == RecoverError.NoError) {\\n            return; // no error: do nothing\\n        } else if (error == RecoverError.InvalidSignature) {\\n            revert(\\\"ECDSA: invalid signature\\\");\\n        } else if (error == RecoverError.InvalidSignatureLength) {\\n            revert(\\\"ECDSA: invalid signature length\\\");\\n        } else if (error == RecoverError.InvalidSignatureS) {\\n            revert(\\\"ECDSA: invalid signature 's' value\\\");\\n        } else if (error == RecoverError.InvalidSignatureV) {\\n            revert(\\\"ECDSA: invalid signature 'v' value\\\");\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature` or error string. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     *\\n     * Documentation for signature generation:\\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n     *\\n     * _Available since v4.3._\\n     */\\n    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n        // Check the signature length\\n        // - case 65: r,s,v signature (standard)\\n        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\\n        if (signature.length == 65) {\\n            bytes32 r;\\n            bytes32 s;\\n            uint8 v;\\n            // ecrecover takes the signature parameters, and the only way to get them\\n            // currently is to use assembly.\\n            assembly {\\n                r := mload(add(signature, 0x20))\\n                s := mload(add(signature, 0x40))\\n                v := byte(0, mload(add(signature, 0x60)))\\n            }\\n            return tryRecover(hash, v, r, s);\\n        } else if (signature.length == 64) {\\n            bytes32 r;\\n            bytes32 vs;\\n            // ecrecover takes the signature parameters, and the only way to get them\\n            // currently is to use assembly.\\n            assembly {\\n                r := mload(add(signature, 0x20))\\n                vs := mload(add(signature, 0x40))\\n            }\\n            return tryRecover(hash, r, vs);\\n        } else {\\n            return (address(0), RecoverError.InvalidSignatureLength);\\n        }\\n    }\\n\\n    /**\\n     * @dev Returns the address that signed a hashed message (`hash`) with\\n     * `signature`. This address can then be used for verification purposes.\\n     *\\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n     * this function rejects them by requiring the `s` value to be in the lower\\n     * half order, and the `v` value to be either 27 or 28.\\n     *\\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n     * verification to be secure: it is possible to craft signatures that\\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n     * this is by receiving a hash of the original message (which may otherwise\\n     * be too long), and then calling {toEthSignedMessageHash} on it.\\n     */\\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n        (address recovered, RecoverError error) = tryRecover(hash, signature);\\n        _throwError(error);\\n        return recovered;\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n     *\\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n     *\\n     * _Available since v4.3._\\n     */\\n    function tryRecover(\\n        bytes32 hash,\\n        bytes32 r,\\n        bytes32 vs\\n    ) internal pure returns (address, RecoverError) {\\n        bytes32 s;\\n        uint8 v;\\n        assembly {\\n            s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\\n            v := add(shr(255, vs), 27)\\n        }\\n        return tryRecover(hash, v, r, s);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n     *\\n     * _Available since v4.2._\\n     */\\n    function recover(\\n        bytes32 hash,\\n        bytes32 r,\\n        bytes32 vs\\n    ) internal pure returns (address) {\\n        (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n        _throwError(error);\\n        return recovered;\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     *\\n     * _Available since v4.3._\\n     */\\n    function tryRecover(\\n        bytes32 hash,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) internal pure returns (address, RecoverError) {\\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n        // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n        //\\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n        // these malleable signatures as well.\\n        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n            return (address(0), RecoverError.InvalidSignatureS);\\n        }\\n        if (v != 27 && v != 28) {\\n            return (address(0), RecoverError.InvalidSignatureV);\\n        }\\n\\n        // If the signature is valid (and not malleable), return the signer address\\n        address signer = ecrecover(hash, v, r, s);\\n        if (signer == address(0)) {\\n            return (address(0), RecoverError.InvalidSignature);\\n        }\\n\\n        return (signer, RecoverError.NoError);\\n    }\\n\\n    /**\\n     * @dev Overload of {ECDSA-recover} that receives the `v`,\\n     * `r` and `s` signature fields separately.\\n     */\\n    function recover(\\n        bytes32 hash,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) internal pure returns (address) {\\n        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n        _throwError(error);\\n        return recovered;\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n     * produces hash corresponding to the one signed with the\\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n     * JSON-RPC method as part of EIP-191.\\n     *\\n     * See {recover}.\\n     */\\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n        // 32 is the length in bytes of hash,\\n        // enforced by the type signature above\\n        return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n    }\\n\\n    /**\\n     * @dev Returns an Ethereum Signed Typed Data, created from a\\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\\n     * to the one signed with the\\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n     * JSON-RPC method as part of EIP-712.\\n     *\\n     * See {recover}.\\n     */\\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n        return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n    }\\n}\\n\",\"keccak256\":\"0xbc991a1cf357ce19480831a40792c814238a3b5458134703682abd8aa39719fb\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./ECDSA.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * _Available since v3.4._\\n */\\nabstract contract EIP712 {\\n    /* solhint-disable var-name-mixedcase */\\n    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n    // invalidate the cached domain separator if the chain id changes.\\n    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\\n    uint256 private immutable _CACHED_CHAIN_ID;\\n\\n    bytes32 private immutable _HASHED_NAME;\\n    bytes32 private immutable _HASHED_VERSION;\\n    bytes32 private immutable _TYPE_HASH;\\n\\n    /* solhint-enable var-name-mixedcase */\\n\\n    /**\\n     * @dev Initializes the domain separator and parameter caches.\\n     *\\n     * The meaning of `name` and `version` is specified in\\n     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\\n     *\\n     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n     * - `version`: the current major version of the signing domain.\\n     *\\n     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n     * contract upgrade].\\n     */\\n    constructor(string memory name, string memory version) {\\n        bytes32 hashedName = keccak256(bytes(name));\\n        bytes32 hashedVersion = keccak256(bytes(version));\\n        bytes32 typeHash = keccak256(\\n            \\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"\\n        );\\n        _HASHED_NAME = hashedName;\\n        _HASHED_VERSION = hashedVersion;\\n        _CACHED_CHAIN_ID = block.chainid;\\n        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\\n        _TYPE_HASH = typeHash;\\n    }\\n\\n    /**\\n     * @dev Returns the domain separator for the current chain.\\n     */\\n    function _domainSeparatorV4() internal view returns (bytes32) {\\n        if (block.chainid == _CACHED_CHAIN_ID) {\\n            return _CACHED_DOMAIN_SEPARATOR;\\n        } else {\\n            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\\n        }\\n    }\\n\\n    function _buildDomainSeparator(\\n        bytes32 typeHash,\\n        bytes32 nameHash,\\n        bytes32 versionHash\\n    ) private view returns (bytes32) {\\n        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\\n    }\\n\\n    /**\\n     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n     * function returns the hash of the fully encoded EIP712 message for this domain.\\n     *\\n     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n     *\\n     * ```solidity\\n     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n     *     keccak256(\\\"Mail(address to,string contents)\\\"),\\n     *     mailTo,\\n     *     keccak256(bytes(mailContents))\\n     * )));\\n     * address signer = ECDSA.recover(digest, signature);\\n     * ```\\n     */\\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\\n    }\\n}\\n\",\"keccak256\":\"0xba18d725602452307e5b278ed4566616c63792d89f3a0388a6f285428c26e681\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n    /**\\n     * @dev Returns the downcasted uint224 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint224).\\n     *\\n     * Counterpart to Solidity's `uint224` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 224 bits\\n     */\\n    function toUint224(uint256 value) internal pure returns (uint224) {\\n        require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n        return uint224(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint128 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint128).\\n     *\\n     * Counterpart to Solidity's `uint128` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 128 bits\\n     */\\n    function toUint128(uint256 value) internal pure returns (uint128) {\\n        require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n        return uint128(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint96 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint96).\\n     *\\n     * Counterpart to Solidity's `uint96` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 96 bits\\n     */\\n    function toUint96(uint256 value) internal pure returns (uint96) {\\n        require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n        return uint96(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint64 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint64).\\n     *\\n     * Counterpart to Solidity's `uint64` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 64 bits\\n     */\\n    function toUint64(uint256 value) internal pure returns (uint64) {\\n        require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n        return uint64(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint32 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint32).\\n     *\\n     * Counterpart to Solidity's `uint32` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 32 bits\\n     */\\n    function toUint32(uint256 value) internal pure returns (uint32) {\\n        require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n        return uint32(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint16 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint16).\\n     *\\n     * Counterpart to Solidity's `uint16` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 16 bits\\n     */\\n    function toUint16(uint256 value) internal pure returns (uint16) {\\n        require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n        return uint16(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint8 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint8).\\n     *\\n     * Counterpart to Solidity's `uint8` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 8 bits.\\n     */\\n    function toUint8(uint256 value) internal pure returns (uint8) {\\n        require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n        return uint8(value);\\n    }\\n\\n    /**\\n     * @dev Converts a signed int256 into an unsigned uint256.\\n     *\\n     * Requirements:\\n     *\\n     * - input must be greater than or equal to 0.\\n     */\\n    function toUint256(int256 value) internal pure returns (uint256) {\\n        require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n        return uint256(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted int128 from int256, reverting on\\n     * overflow (when the input is less than smallest int128 or\\n     * greater than largest int128).\\n     *\\n     * Counterpart to Solidity's `int128` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 128 bits\\n     *\\n     * _Available since v3.1._\\n     */\\n    function toInt128(int256 value) internal pure returns (int128) {\\n        require(value >= type(int128).min && value <= type(int128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n        return int128(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted int64 from int256, reverting on\\n     * overflow (when the input is less than smallest int64 or\\n     * greater than largest int64).\\n     *\\n     * Counterpart to Solidity's `int64` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 64 bits\\n     *\\n     * _Available since v3.1._\\n     */\\n    function toInt64(int256 value) internal pure returns (int64) {\\n        require(value >= type(int64).min && value <= type(int64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n        return int64(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted int32 from int256, reverting on\\n     * overflow (when the input is less than smallest int32 or\\n     * greater than largest int32).\\n     *\\n     * Counterpart to Solidity's `int32` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 32 bits\\n     *\\n     * _Available since v3.1._\\n     */\\n    function toInt32(int256 value) internal pure returns (int32) {\\n        require(value >= type(int32).min && value <= type(int32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n        return int32(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted int16 from int256, reverting on\\n     * overflow (when the input is less than smallest int16 or\\n     * greater than largest int16).\\n     *\\n     * Counterpart to Solidity's `int16` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 16 bits\\n     *\\n     * _Available since v3.1._\\n     */\\n    function toInt16(int256 value) internal pure returns (int16) {\\n        require(value >= type(int16).min && value <= type(int16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n        return int16(value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted int8 from int256, reverting on\\n     * overflow (when the input is less than smallest int8 or\\n     * greater than largest int8).\\n     *\\n     * Counterpart to Solidity's `int8` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 8 bits.\\n     *\\n     * _Available since v3.1._\\n     */\\n    function toInt8(int256 value) internal pure returns (int8) {\\n        require(value >= type(int8).min && value <= type(int8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n        return int8(value);\\n    }\\n\\n    /**\\n     * @dev Converts an unsigned uint256 into a signed int256.\\n     *\\n     * Requirements:\\n     *\\n     * - input must be less than or equal to maxInt256.\\n     */\\n    function toInt256(uint256 value) internal pure returns (int256) {\\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n        require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n        return int256(value);\\n    }\\n}\\n\",\"keccak256\":\"0x08d867b4c0bb782b9135691fa732b6846e0f133006489c3aa505abd1f6de56cb\",\"license\":\"MIT\"},\"@pooltogether/v4-core/contracts/ControlledToken.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.6;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol\\\";\\n\\nimport \\\"./interfaces/IControlledToken.sol\\\";\\n\\n/**\\n * @title  PoolTogether V4 Controlled ERC20 Token\\n * @author PoolTogether Inc Team\\n * @notice  ERC20 Tokens with a controller for minting & burning\\n */\\ncontract ControlledToken is ERC20Permit, IControlledToken {\\n    /* ============ Global Variables ============ */\\n\\n    /// @notice Interface to the contract responsible for controlling mint/burn\\n    address public override immutable controller;\\n\\n    /// @notice ERC20 controlled token decimals.\\n    uint8 private immutable _decimals;\\n\\n    /* ============ Events ============ */\\n\\n    /// @dev Emitted when contract is deployed\\n    event Deployed(string name, string symbol, uint8 decimals, address indexed controller);\\n\\n    /* ============ Modifiers ============ */\\n\\n    /// @dev Function modifier to ensure that the caller is the controller contract\\n    modifier onlyController() {\\n        require(msg.sender == address(controller), \\\"ControlledToken/only-controller\\\");\\n        _;\\n    }\\n\\n    /* ============ Constructor ============ */\\n\\n    /// @notice Deploy the Controlled Token with Token Details and the Controller\\n    /// @param _name The name of the Token\\n    /// @param _symbol The symbol for the Token\\n    /// @param decimals_ The number of decimals for the Token\\n    /// @param _controller Address of the Controller contract for minting & burning\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 decimals_,\\n        address _controller\\n    ) ERC20Permit(\\\"PoolTogether ControlledToken\\\") ERC20(_name, _symbol) {\\n        require(address(_controller) != address(0), \\\"ControlledToken/controller-not-zero-address\\\");\\n        controller = _controller;\\n\\n        require(decimals_ > 0, \\\"ControlledToken/decimals-gt-zero\\\");\\n        _decimals = decimals_;\\n\\n        emit Deployed(_name, _symbol, decimals_, _controller);\\n    }\\n\\n    /* ============ External Functions ============ */\\n\\n    /// @notice Allows the controller to mint tokens for a user account\\n    /// @dev May be overridden to provide more granular control over minting\\n    /// @param _user Address of the receiver of the minted tokens\\n    /// @param _amount Amount of tokens to mint\\n    function controllerMint(address _user, uint256 _amount)\\n        external\\n        virtual\\n        override\\n        onlyController\\n    {\\n        _mint(_user, _amount);\\n    }\\n\\n    /// @notice Allows the controller to burn tokens from a user account\\n    /// @dev May be overridden to provide more granular control over burning\\n    /// @param _user Address of the holder account to burn tokens from\\n    /// @param _amount Amount of tokens to burn\\n    function controllerBurn(address _user, uint256 _amount)\\n        external\\n        virtual\\n        override\\n        onlyController\\n    {\\n        _burn(_user, _amount);\\n    }\\n\\n    /// @notice Allows an operator via the controller to burn tokens on behalf of a user account\\n    /// @dev May be overridden to provide more granular control over operator-burning\\n    /// @param _operator Address of the operator performing the burn action via the controller contract\\n    /// @param _user Address of the holder account to burn tokens from\\n    /// @param _amount Amount of tokens to burn\\n    function controllerBurnFrom(\\n        address _operator,\\n        address _user,\\n        uint256 _amount\\n    ) external virtual override onlyController {\\n        if (_operator != _user) {\\n            _approve(_user, _operator, allowance(_user, _operator) - _amount);\\n        }\\n\\n        _burn(_user, _amount);\\n    }\\n\\n    /// @notice Returns the ERC20 controlled token decimals.\\n    /// @dev This value should be equal to the decimals of the token used to deposit into the pool.\\n    /// @return uint8 decimals.\\n    function decimals() public view virtual override returns (uint8) {\\n        return _decimals;\\n    }\\n}\\n\",\"keccak256\":\"0x7dec4c4427ea75702a706e574d17751ca989b2aaea4991380a126b611d95ff9e\",\"license\":\"GPL-3.0\"},\"@pooltogether/v4-core/contracts/Ticket.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.6;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"./libraries/ExtendedSafeCastLib.sol\\\";\\nimport \\\"./libraries/TwabLib.sol\\\";\\nimport \\\"./interfaces/ITicket.sol\\\";\\nimport \\\"./ControlledToken.sol\\\";\\n\\n/**\\n  * @title  PoolTogether V4 Ticket\\n  * @author PoolTogether Inc Team\\n  * @notice The Ticket extends the standard ERC20 and ControlledToken interfaces with time-weighted average balance functionality.\\n            The average balance held by a user between two timestamps can be calculated, as well as the historic balance.  The\\n            historic total supply is available as well as the average total supply between two timestamps.\\n\\n            A user may \\\"delegate\\\" their balance; increasing another user's historic balance while retaining their tokens.\\n*/\\ncontract Ticket is ControlledToken, ITicket {\\n    using SafeERC20 for IERC20;\\n    using ExtendedSafeCastLib for uint256;\\n\\n    // solhint-disable-next-line var-name-mixedcase\\n    bytes32 private immutable _DELEGATE_TYPEHASH =\\n        keccak256(\\\"Delegate(address user,address delegate,uint256 nonce,uint256 deadline)\\\");\\n\\n    /// @notice Record of token holders TWABs for each account.\\n    mapping(address => TwabLib.Account) internal userTwabs;\\n\\n    /// @notice Record of tickets total supply and ring buff parameters used for observation.\\n    TwabLib.Account internal totalSupplyTwab;\\n\\n    /// @notice Mapping of delegates.  Each address can delegate their ticket power to another.\\n    mapping(address => address) internal delegates;\\n\\n    /* ============ Constructor ============ */\\n\\n    /**\\n     * @notice Constructs Ticket with passed parameters.\\n     * @param _name ERC20 ticket token name.\\n     * @param _symbol ERC20 ticket token symbol.\\n     * @param decimals_ ERC20 ticket token decimals.\\n     * @param _controller ERC20 ticket controller address (ie: Prize Pool address).\\n     */\\n    constructor(\\n        string memory _name,\\n        string memory _symbol,\\n        uint8 decimals_,\\n        address _controller\\n    ) ControlledToken(_name, _symbol, decimals_, _controller) {}\\n\\n    /* ============ External Functions ============ */\\n\\n    /// @inheritdoc ITicket\\n    function getAccountDetails(address _user)\\n        external\\n        view\\n        override\\n        returns (TwabLib.AccountDetails memory)\\n    {\\n        return userTwabs[_user].details;\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function getTwab(address _user, uint16 _index)\\n        external\\n        view\\n        override\\n        returns (ObservationLib.Observation memory)\\n    {\\n        return userTwabs[_user].twabs[_index];\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function getBalanceAt(address _user, uint64 _target) external view override returns (uint256) {\\n        TwabLib.Account storage account = userTwabs[_user];\\n\\n        return\\n            TwabLib.getBalanceAt(\\n                account.twabs,\\n                account.details,\\n                uint32(_target),\\n                uint32(block.timestamp)\\n            );\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function getAverageBalancesBetween(\\n        address _user,\\n        uint64[] calldata _startTimes,\\n        uint64[] calldata _endTimes\\n    ) external view override returns (uint256[] memory) {\\n        return _getAverageBalancesBetween(userTwabs[_user], _startTimes, _endTimes);\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function getAverageTotalSuppliesBetween(\\n        uint64[] calldata _startTimes,\\n        uint64[] calldata _endTimes\\n    ) external view override returns (uint256[] memory) {\\n        return _getAverageBalancesBetween(totalSupplyTwab, _startTimes, _endTimes);\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function getAverageBalanceBetween(\\n        address _user,\\n        uint64 _startTime,\\n        uint64 _endTime\\n    ) external view override returns (uint256) {\\n        TwabLib.Account storage account = userTwabs[_user];\\n\\n        return\\n            TwabLib.getAverageBalanceBetween(\\n                account.twabs,\\n                account.details,\\n                uint32(_startTime),\\n                uint32(_endTime),\\n                uint32(block.timestamp)\\n            );\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function getBalancesAt(address _user, uint64[] calldata _targets)\\n        external\\n        view\\n        override\\n        returns (uint256[] memory)\\n    {\\n        uint256 length = _targets.length;\\n        uint256[] memory _balances = new uint256[](length);\\n\\n        TwabLib.Account storage twabContext = userTwabs[_user];\\n        TwabLib.AccountDetails memory details = twabContext.details;\\n\\n        for (uint256 i = 0; i < length; i++) {\\n            _balances[i] = TwabLib.getBalanceAt(\\n                twabContext.twabs,\\n                details,\\n                uint32(_targets[i]),\\n                uint32(block.timestamp)\\n            );\\n        }\\n\\n        return _balances;\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function getTotalSupplyAt(uint64 _target) external view override returns (uint256) {\\n        return\\n            TwabLib.getBalanceAt(\\n                totalSupplyTwab.twabs,\\n                totalSupplyTwab.details,\\n                uint32(_target),\\n                uint32(block.timestamp)\\n            );\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function getTotalSuppliesAt(uint64[] calldata _targets)\\n        external\\n        view\\n        override\\n        returns (uint256[] memory)\\n    {\\n        uint256 length = _targets.length;\\n        uint256[] memory totalSupplies = new uint256[](length);\\n\\n        TwabLib.AccountDetails memory details = totalSupplyTwab.details;\\n\\n        for (uint256 i = 0; i < length; i++) {\\n            totalSupplies[i] = TwabLib.getBalanceAt(\\n                totalSupplyTwab.twabs,\\n                details,\\n                uint32(_targets[i]),\\n                uint32(block.timestamp)\\n            );\\n        }\\n\\n        return totalSupplies;\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function delegateOf(address _user) external view override returns (address) {\\n        return delegates[_user];\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function controllerDelegateFor(address _user, address _to) external override onlyController {\\n        _delegate(_user, _to);\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function delegateWithSignature(\\n        address _user,\\n        address _newDelegate,\\n        uint256 _deadline,\\n        uint8 _v,\\n        bytes32 _r,\\n        bytes32 _s\\n    ) external virtual override {\\n        require(block.timestamp <= _deadline, \\\"Ticket/delegate-expired-deadline\\\");\\n\\n        bytes32 structHash = keccak256(abi.encode(_DELEGATE_TYPEHASH, _user, _newDelegate, _useNonce(_user), _deadline));\\n\\n        bytes32 hash = _hashTypedDataV4(structHash);\\n\\n        address signer = ECDSA.recover(hash, _v, _r, _s);\\n        require(signer == _user, \\\"Ticket/delegate-invalid-signature\\\");\\n\\n        _delegate(_user, _newDelegate);\\n    }\\n\\n    /// @inheritdoc ITicket\\n    function delegate(address _to) external virtual override {\\n        _delegate(msg.sender, _to);\\n    }\\n\\n    /// @notice Delegates a users chance to another\\n    /// @param _user The user whose balance should be delegated\\n    /// @param _to The delegate\\n    function _delegate(address _user, address _to) internal {\\n        uint256 balance = balanceOf(_user);\\n        address currentDelegate = delegates[_user];\\n\\n        if (currentDelegate == _to) {\\n            return;\\n        }\\n\\n        delegates[_user] = _to;\\n\\n        _transferTwab(currentDelegate, _to, balance);\\n\\n        emit Delegated(_user, _to);\\n    }\\n\\n    /* ============ Internal Functions ============ */\\n\\n    /**\\n     * @notice Retrieves the average balances held by a user for a given time frame.\\n     * @param _account The user whose balance is checked.\\n     * @param _startTimes The start time of the time frame.\\n     * @param _endTimes The end time of the time frame.\\n     * @return The average balance that the user held during the time frame.\\n     */\\n    function _getAverageBalancesBetween(\\n        TwabLib.Account storage _account,\\n        uint64[] calldata _startTimes,\\n        uint64[] calldata _endTimes\\n    ) internal view returns (uint256[] memory) {\\n        uint256 startTimesLength = _startTimes.length;\\n        require(startTimesLength == _endTimes.length, \\\"Ticket/start-end-times-length-match\\\");\\n\\n        TwabLib.AccountDetails memory accountDetails = _account.details;\\n\\n        uint256[] memory averageBalances = new uint256[](startTimesLength);\\n        uint32 currentTimestamp = uint32(block.timestamp);\\n\\n        for (uint256 i = 0; i < startTimesLength; i++) {\\n            averageBalances[i] = TwabLib.getAverageBalanceBetween(\\n                _account.twabs,\\n                accountDetails,\\n                uint32(_startTimes[i]),\\n                uint32(_endTimes[i]),\\n                currentTimestamp\\n            );\\n        }\\n\\n        return averageBalances;\\n    }\\n\\n    // @inheritdoc ERC20\\n    function _beforeTokenTransfer(address _from, address _to, uint256 _amount) internal override {\\n        if (_from == _to) {\\n            return;\\n        }\\n\\n        address _fromDelegate;\\n        if (_from != address(0)) {\\n            _fromDelegate = delegates[_from];\\n        }\\n\\n        address _toDelegate;\\n        if (_to != address(0)) {\\n            _toDelegate = delegates[_to];\\n        }\\n\\n        _transferTwab(_fromDelegate, _toDelegate, _amount);\\n    }\\n\\n    /// @notice Transfers the given TWAB balance from one user to another\\n    /// @param _from The user to transfer the balance from.  May be zero in the event of a mint.\\n    /// @param _to The user to transfer the balance to.  May be zero in the event of a burn.\\n    /// @param _amount The balance that is being transferred.\\n    function _transferTwab(address _from, address _to, uint256 _amount) internal {\\n        // If we are transferring tokens from a delegated account to an undelegated account\\n        if (_from != address(0)) {\\n            _decreaseUserTwab(_from, _amount);\\n\\n            if (_to == address(0)) {\\n                _decreaseTotalSupplyTwab(_amount);\\n            }\\n        }\\n\\n        // If we are transferring tokens from an undelegated account to a delegated account\\n        if (_to != address(0)) {\\n            _increaseUserTwab(_to, _amount);\\n\\n            if (_from == address(0)) {\\n                _increaseTotalSupplyTwab(_amount);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @notice Increase `_to` TWAB balance.\\n     * @param _to Address of the delegate.\\n     * @param _amount Amount of tokens to be added to `_to` TWAB balance.\\n     */\\n    function _increaseUserTwab(\\n        address _to,\\n        uint256 _amount\\n    ) internal {\\n        if (_amount == 0) {\\n            return;\\n        }\\n\\n        TwabLib.Account storage _account = userTwabs[_to];\\n\\n        (\\n            TwabLib.AccountDetails memory accountDetails,\\n            ObservationLib.Observation memory twab,\\n            bool isNew\\n        ) = TwabLib.increaseBalance(_account, _amount.toUint208(), uint32(block.timestamp));\\n\\n        _account.details = accountDetails;\\n\\n        if (isNew) {\\n            emit NewUserTwab(_to, twab);\\n        }\\n    }\\n\\n    /**\\n     * @notice Decrease `_to` TWAB balance.\\n     * @param _to Address of the delegate.\\n     * @param _amount Amount of tokens to be added to `_to` TWAB balance.\\n     */\\n    function _decreaseUserTwab(\\n        address _to,\\n        uint256 _amount\\n    ) internal {\\n        if (_amount == 0) {\\n            return;\\n        }\\n\\n        TwabLib.Account storage _account = userTwabs[_to];\\n\\n        (\\n            TwabLib.AccountDetails memory accountDetails,\\n            ObservationLib.Observation memory twab,\\n            bool isNew\\n        ) = TwabLib.decreaseBalance(\\n                _account,\\n                _amount.toUint208(),\\n                \\\"Ticket/twab-burn-lt-balance\\\",\\n                uint32(block.timestamp)\\n            );\\n\\n        _account.details = accountDetails;\\n\\n        if (isNew) {\\n            emit NewUserTwab(_to, twab);\\n        }\\n    }\\n\\n    /// @notice Decreases the total supply twab.  Should be called anytime a balance moves from delegated to undelegated\\n    /// @param _amount The amount to decrease the total by\\n    function _decreaseTotalSupplyTwab(uint256 _amount) internal {\\n        if (_amount == 0) {\\n            return;\\n        }\\n\\n        (\\n            TwabLib.AccountDetails memory accountDetails,\\n            ObservationLib.Observation memory tsTwab,\\n            bool tsIsNew\\n        ) = TwabLib.decreaseBalance(\\n                totalSupplyTwab,\\n                _amount.toUint208(),\\n                \\\"Ticket/burn-amount-exceeds-total-supply-twab\\\",\\n                uint32(block.timestamp)\\n            );\\n\\n        totalSupplyTwab.details = accountDetails;\\n\\n        if (tsIsNew) {\\n            emit NewTotalSupplyTwab(tsTwab);\\n        }\\n    }\\n\\n    /// @notice Increases the total supply twab.  Should be called anytime a balance moves from undelegated to delegated\\n    /// @param _amount The amount to increase the total by\\n    function _increaseTotalSupplyTwab(uint256 _amount) internal {\\n        if (_amount == 0) {\\n            return;\\n        }\\n\\n        (\\n            TwabLib.AccountDetails memory accountDetails,\\n            ObservationLib.Observation memory _totalSupply,\\n            bool tsIsNew\\n        ) = TwabLib.increaseBalance(totalSupplyTwab, _amount.toUint208(), uint32(block.timestamp));\\n\\n        totalSupplyTwab.details = accountDetails;\\n\\n        if (tsIsNew) {\\n            emit NewTotalSupplyTwab(_totalSupply);\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x8a28b868583b1e04c4bcd8667b9e06309f94b4e854bcc7cdc7716fc396bd21b8\",\"license\":\"GPL-3.0\"},\"@pooltogether/v4-core/contracts/interfaces/IControlledToken.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.6;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/** @title IControlledToken\\n  * @author PoolTogether Inc Team\\n  * @notice ERC20 Tokens with a controller for minting & burning.\\n*/\\ninterface IControlledToken is IERC20 {\\n\\n    /** \\n        @notice Interface to the contract responsible for controlling mint/burn\\n    */\\n    function controller() external view returns (address);\\n\\n    /** \\n      * @notice Allows the controller to mint tokens for a user account\\n      * @dev May be overridden to provide more granular control over minting\\n      * @param user Address of the receiver of the minted tokens\\n      * @param amount Amount of tokens to mint\\n    */\\n    function controllerMint(address user, uint256 amount) external;\\n\\n    /** \\n      * @notice Allows the controller to burn tokens from a user account\\n      * @dev May be overridden to provide more granular control over burning\\n      * @param user Address of the holder account to burn tokens from\\n      * @param amount Amount of tokens to burn\\n    */\\n    function controllerBurn(address user, uint256 amount) external;\\n\\n    /** \\n      * @notice Allows an operator via the controller to burn tokens on behalf of a user account\\n      * @dev May be overridden to provide more granular control over operator-burning\\n      * @param operator Address of the operator performing the burn action via the controller contract\\n      * @param user Address of the holder account to burn tokens from\\n      * @param amount Amount of tokens to burn\\n    */\\n    function controllerBurnFrom(\\n        address operator,\\n        address user,\\n        uint256 amount\\n    ) external;\\n}\\n\",\"keccak256\":\"0x90dceeec1eea6e49021e8db88b084f3f0c503c60b6f7e0bbecd2529ffde87ef3\",\"license\":\"GPL-3.0\"},\"@pooltogether/v4-core/contracts/interfaces/ITicket.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.6;\\n\\nimport \\\"../libraries/TwabLib.sol\\\";\\nimport \\\"./IControlledToken.sol\\\";\\n\\ninterface ITicket is IControlledToken {\\n    /**\\n     * @notice A struct containing details for an Account.\\n     * @param balance The current balance for an Account.\\n     * @param nextTwabIndex The next available index to store a new twab.\\n     * @param cardinality The number of recorded twabs (plus one!).\\n     */\\n    struct AccountDetails {\\n        uint224 balance;\\n        uint16 nextTwabIndex;\\n        uint16 cardinality;\\n    }\\n\\n    /**\\n     * @notice Combines account details with their twab history.\\n     * @param details The account details.\\n     * @param twabs The history of twabs for this account.\\n     */\\n    struct Account {\\n        AccountDetails details;\\n        ObservationLib.Observation[65535] twabs;\\n    }\\n\\n    /**\\n     * @notice Emitted when TWAB balance has been delegated to another user.\\n     * @param delegator Address of the delegator.\\n     * @param delegate Address of the delegate.\\n     */\\n    event Delegated(address indexed delegator, address indexed delegate);\\n\\n    /**\\n     * @notice Emitted when ticket is initialized.\\n     * @param name Ticket name (eg: PoolTogether Dai Ticket (Compound)).\\n     * @param symbol Ticket symbol (eg: PcDAI).\\n     * @param decimals Ticket decimals.\\n     * @param controller Token controller address.\\n     */\\n    event TicketInitialized(string name, string symbol, uint8 decimals, address indexed controller);\\n\\n    /**\\n     * @notice Emitted when a new TWAB has been recorded.\\n     * @param delegate The recipient of the ticket power (may be the same as the user).\\n     * @param newTwab Updated TWAB of a ticket holder after a successful TWAB recording.\\n     */\\n    event NewUserTwab(\\n        address indexed delegate,\\n        ObservationLib.Observation newTwab\\n    );\\n\\n    /**\\n     * @notice Emitted when a new total supply TWAB has been recorded.\\n     * @param newTotalSupplyTwab Updated TWAB of tickets total supply after a successful total supply TWAB recording.\\n     */\\n    event NewTotalSupplyTwab(ObservationLib.Observation newTotalSupplyTwab);\\n\\n    /**\\n     * @notice Retrieves the address of the delegate to whom `user` has delegated their tickets.\\n     * @dev Address of the delegate will be the zero address if `user` has not delegated their tickets.\\n     * @param user Address of the delegator.\\n     * @return Address of the delegate.\\n     */\\n    function delegateOf(address user) external view returns (address);\\n\\n    /**\\n    * @notice Delegate time-weighted average balances to an alternative address.\\n    * @dev    Transfers (including mints) trigger the storage of a TWAB in delegate(s) account, instead of the\\n              targetted sender and/or recipient address(s).\\n    * @dev    To reset the delegate, pass the zero address (0x000.000) as `to` parameter.\\n    * @dev Current delegate address should be different from the new delegate address `to`.\\n    * @param  to Recipient of delegated TWAB.\\n    */\\n    function delegate(address to) external;\\n\\n    /**\\n     * @notice Allows the controller to delegate on a users behalf.\\n     * @param user The user for whom to delegate\\n     * @param delegate The new delegate\\n     */\\n    function controllerDelegateFor(address user, address delegate) external;\\n\\n    /**\\n     * @notice Allows a user to delegate via signature\\n     * @param user The user who is delegating\\n     * @param delegate The new delegate\\n     * @param deadline The timestamp by which this must be submitted\\n     * @param v The v portion of the ECDSA sig\\n     * @param r The r portion of the ECDSA sig\\n     * @param s The s portion of the ECDSA sig\\n     */\\n    function delegateWithSignature(\\n        address user,\\n        address delegate,\\n        uint256 deadline,\\n        uint8 v,\\n        bytes32 r,\\n        bytes32 s\\n    ) external;\\n\\n    /**\\n     * @notice Gets a users twab context.  This is a struct with their balance, next twab index, and cardinality.\\n     * @param user The user for whom to fetch the TWAB context.\\n     * @return The TWAB context, which includes { balance, nextTwabIndex, cardinality }\\n     */\\n    function getAccountDetails(address user) external view returns (TwabLib.AccountDetails memory);\\n\\n    /**\\n     * @notice Gets the TWAB at a specific index for a user.\\n     * @param user The user for whom to fetch the TWAB.\\n     * @param index The index of the TWAB to fetch.\\n     * @return The TWAB, which includes the twab amount and the timestamp.\\n     */\\n    function getTwab(address user, uint16 index)\\n        external\\n        view\\n        returns (ObservationLib.Observation memory);\\n\\n    /**\\n     * @notice Retrieves `user` TWAB balance.\\n     * @param user Address of the user whose TWAB is being fetched.\\n     * @param timestamp Timestamp at which we want to retrieve the TWAB balance.\\n     * @return The TWAB balance at the given timestamp.\\n     */\\n    function getBalanceAt(address user, uint64 timestamp) external view returns (uint256);\\n\\n    /**\\n     * @notice Retrieves `user` TWAB balances.\\n     * @param user Address of the user whose TWABs are being fetched.\\n     * @param timestamps Timestamps range at which we want to retrieve the TWAB balances.\\n     * @return `user` TWAB balances.\\n     */\\n    function getBalancesAt(address user, uint64[] calldata timestamps)\\n        external\\n        view\\n        returns (uint256[] memory);\\n\\n    /**\\n     * @notice Retrieves the average balance held by a user for a given time frame.\\n     * @param user The user whose balance is checked.\\n     * @param startTime The start time of the time frame.\\n     * @param endTime The end time of the time frame.\\n     * @return The average balance that the user held during the time frame.\\n     */\\n    function getAverageBalanceBetween(\\n        address user,\\n        uint64 startTime,\\n        uint64 endTime\\n    ) external view returns (uint256);\\n\\n    /**\\n     * @notice Retrieves the average balances held by a user for a given time frame.\\n     * @param user The user whose balance is checked.\\n     * @param startTimes The start time of the time frame.\\n     * @param endTimes The end time of the time frame.\\n     * @return The average balance that the user held during the time frame.\\n     */\\n    function getAverageBalancesBetween(\\n        address user,\\n        uint64[] calldata startTimes,\\n        uint64[] calldata endTimes\\n    ) external view returns (uint256[] memory);\\n\\n    /**\\n     * @notice Retrieves the total supply TWAB balance at the given timestamp.\\n     * @param timestamp Timestamp at which we want to retrieve the total supply TWAB balance.\\n     * @return The total supply TWAB balance at the given timestamp.\\n     */\\n    function getTotalSupplyAt(uint64 timestamp) external view returns (uint256);\\n\\n    /**\\n     * @notice Retrieves the total supply TWAB balance between the given timestamps range.\\n     * @param timestamps Timestamps range at which we want to retrieve the total supply TWAB balance.\\n     * @return Total supply TWAB balances.\\n     */\\n    function getTotalSuppliesAt(uint64[] calldata timestamps)\\n        external\\n        view\\n        returns (uint256[] memory);\\n\\n    /**\\n     * @notice Retrieves the average total supply balance for a set of given time frames.\\n     * @param startTimes Array of start times.\\n     * @param endTimes Array of end times.\\n     * @return The average total supplies held during the time frame.\\n     */\\n    function getAverageTotalSuppliesBetween(\\n        uint64[] calldata startTimes,\\n        uint64[] calldata endTimes\\n    ) external view returns (uint256[] memory);\\n}\\n\",\"keccak256\":\"0xb9f6423a8a9c7394941cb84723b82cc66c5f815d689dc0562e612ae4d9f1cc27\",\"license\":\"GPL-3.0\"},\"@pooltogether/v4-core/contracts/libraries/ExtendedSafeCastLib.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.6;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary ExtendedSafeCastLib {\\n\\n    /**\\n     * @dev Returns the downcasted uint104 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint104).\\n     *\\n     * Counterpart to Solidity's `uint104` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 104 bits\\n     */\\n    function toUint104(uint256 _value) internal pure returns (uint104) {\\n        require(_value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n        return uint104(_value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint208 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint208).\\n     *\\n     * Counterpart to Solidity's `uint208` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 208 bits\\n     */\\n    function toUint208(uint256 _value) internal pure returns (uint208) {\\n        require(_value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n        return uint208(_value);\\n    }\\n\\n    /**\\n     * @dev Returns the downcasted uint224 from uint256, reverting on\\n     * overflow (when the input is greater than largest uint224).\\n     *\\n     * Counterpart to Solidity's `uint224` operator.\\n     *\\n     * Requirements:\\n     *\\n     * - input must fit into 224 bits\\n     */\\n    function toUint224(uint256 _value) internal pure returns (uint224) {\\n        require(_value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n        return uint224(_value);\\n    }\\n}\\n\",\"keccak256\":\"0x1e8add7802f19dbf5957b4d921b2d7b5277f39c9e44505c0375e52f02134e434\",\"license\":\"GPL-3.0\"},\"@pooltogether/v4-core/contracts/libraries/ObservationLib.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.6;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\nimport \\\"./OverflowSafeComparatorLib.sol\\\";\\nimport \\\"./RingBufferLib.sol\\\";\\n\\n/**\\n* @title Observation Library\\n* @notice This library allows one to store an array of timestamped values and efficiently binary search them.\\n* @dev Largely pulled from Uniswap V3 Oracle.sol: https://github.com/Uniswap/v3-core/blob/c05a0e2c8c08c460fb4d05cfdda30b3ad8deeaac/contracts/libraries/Oracle.sol\\n* @author PoolTogether Inc.\\n*/\\nlibrary ObservationLib {\\n    using OverflowSafeComparatorLib for uint32;\\n    using SafeCast for uint256;\\n\\n    /// @notice The maximum number of observations\\n    uint24 public constant MAX_CARDINALITY = 16777215; // 2**24\\n\\n    /**\\n    * @notice Observation, which includes an amount and timestamp.\\n    * @param amount `amount` at `timestamp`.\\n    * @param timestamp Recorded `timestamp`.\\n    */\\n    struct Observation {\\n        uint224 amount;\\n        uint32 timestamp;\\n    }\\n\\n    /**\\n    * @notice Fetches Observations `beforeOrAt` and `atOrAfter` a `_target`, eg: where [`beforeOrAt`, `atOrAfter`] is satisfied.\\n    * The result may be the same Observation, or adjacent Observations.\\n    * @dev The answer must be contained in the array used when the target is located within the stored Observation.\\n    * boundaries: older than the most recent Observation and younger, or the same age as, the oldest Observation.\\n    * @dev  If `_newestObservationIndex` is less than `_oldestObservationIndex`, it means that we've wrapped around the circular buffer.\\n    *       So the most recent observation will be at `_oldestObservationIndex + _cardinality - 1`, at the beginning of the circular buffer.\\n    * @param _observations List of Observations to search through.\\n    * @param _newestObservationIndex Index of the newest Observation. Right side of the circular buffer.\\n    * @param _oldestObservationIndex Index of the oldest Observation. Left side of the circular buffer.\\n    * @param _target Timestamp at which we are searching the Observation.\\n    * @param _cardinality Cardinality of the circular buffer we are searching through.\\n    * @param _time Timestamp at which we perform the binary search.\\n    * @return beforeOrAt Observation recorded before, or at, the target.\\n    * @return atOrAfter Observation recorded at, or after, the target.\\n    */\\n    function binarySearch(\\n        Observation[MAX_CARDINALITY] storage _observations,\\n        uint24 _newestObservationIndex,\\n        uint24 _oldestObservationIndex,\\n        uint32 _target,\\n        uint24 _cardinality,\\n        uint32 _time\\n    ) internal view returns (Observation memory beforeOrAt, Observation memory atOrAfter) {\\n        uint256 leftSide = _oldestObservationIndex;\\n        uint256 rightSide = _newestObservationIndex < leftSide\\n            ? leftSide + _cardinality - 1\\n            : _newestObservationIndex;\\n        uint256 currentIndex;\\n\\n        while (true) {\\n            // We start our search in the middle of the `leftSide` and `rightSide`.\\n            // After each iteration, we narrow down the search to the left or the right side while still starting our search in the middle.\\n            currentIndex = (leftSide + rightSide) / 2;\\n\\n            beforeOrAt = _observations[uint24(RingBufferLib.wrap(currentIndex, _cardinality))];\\n            uint32 beforeOrAtTimestamp = beforeOrAt.timestamp;\\n\\n            // We've landed on an uninitialized timestamp, keep searching higher (more recently).\\n            if (beforeOrAtTimestamp == 0) {\\n                leftSide = currentIndex + 1;\\n                continue;\\n            }\\n\\n            atOrAfter = _observations[uint24(RingBufferLib.nextIndex(currentIndex, _cardinality))];\\n\\n            bool targetAtOrAfter = beforeOrAtTimestamp.lte(_target, _time);\\n\\n            // Check if we've found the corresponding Observation.\\n            if (targetAtOrAfter && _target.lte(atOrAfter.timestamp, _time)) {\\n                break;\\n            }\\n\\n            // If `beforeOrAtTimestamp` is greater than `_target`, then we keep searching lower. To the left of the current index.\\n            if (!targetAtOrAfter) {\\n                rightSide = currentIndex - 1;\\n            } else {\\n                // Otherwise, we keep searching higher. To the left of the current index.\\n                leftSide = currentIndex + 1;\\n            }\\n        }\\n    }\\n}\\n\",\"keccak256\":\"0x225592b42013fc0af60822e75bc047d53b42a5fcf15f2173cdc3b50bea334b0a\",\"license\":\"GPL-3.0\"},\"@pooltogether/v4-core/contracts/libraries/OverflowSafeComparatorLib.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.6;\\n\\n/// @title OverflowSafeComparatorLib library to share comparator functions between contracts\\n/// @dev Code taken from Uniswap V3 Oracle.sol: https://github.com/Uniswap/v3-core/blob/3e88af408132fc957e3e406f65a0ce2b1ca06c3d/contracts/libraries/Oracle.sol\\n/// @author PoolTogether Inc.\\nlibrary OverflowSafeComparatorLib {\\n    /// @notice 32-bit timestamps comparator.\\n    /// @dev safe for 0 or 1 overflows, `_a` and `_b` must be chronologically before or equal to time.\\n    /// @param _a A comparison timestamp from which to determine the relative position of `_timestamp`.\\n    /// @param _b Timestamp to compare against `_a`.\\n    /// @param _timestamp A timestamp truncated to 32 bits.\\n    /// @return bool Whether `_a` is chronologically < `_b`.\\n    function lt(\\n        uint32 _a,\\n        uint32 _b,\\n        uint32 _timestamp\\n    ) internal pure returns (bool) {\\n        // No need to adjust if there hasn't been an overflow\\n        if (_a <= _timestamp && _b <= _timestamp) return _a < _b;\\n\\n        uint256 aAdjusted = _a > _timestamp ? _a : _a + 2**32;\\n        uint256 bAdjusted = _b > _timestamp ? _b : _b + 2**32;\\n\\n        return aAdjusted < bAdjusted;\\n    }\\n\\n    /// @notice 32-bit timestamps comparator.\\n    /// @dev safe for 0 or 1 overflows, `_a` and `_b` must be chronologically before or equal to time.\\n    /// @param _a A comparison timestamp from which to determine the relative position of `_timestamp`.\\n    /// @param _b Timestamp to compare against `_a`.\\n    /// @param _timestamp A timestamp truncated to 32 bits.\\n    /// @return bool Whether `_a` is chronologically <= `_b`.\\n    function lte(\\n        uint32 _a,\\n        uint32 _b,\\n        uint32 _timestamp\\n    ) internal pure returns (bool) {\\n\\n        // No need to adjust if there hasn't been an overflow\\n        if (_a <= _timestamp && _b <= _timestamp) return _a <= _b;\\n\\n        uint256 aAdjusted = _a > _timestamp ? _a : _a + 2**32;\\n        uint256 bAdjusted = _b > _timestamp ? _b : _b + 2**32;\\n\\n        return aAdjusted <= bAdjusted;\\n    }\\n\\n    /// @notice 32-bit timestamp subtractor\\n    /// @dev safe for 0 or 1 overflows, where `_a` and `_b` must be chronologically before or equal to time\\n    /// @param _a The subtraction left operand\\n    /// @param _b The subtraction right operand\\n    /// @param _timestamp The current time.  Expected to be chronologically after both.\\n    /// @return The difference between a and b, adjusted for overflow\\n    function checkedSub(\\n        uint32 _a,\\n        uint32 _b,\\n        uint32 _timestamp\\n    ) internal pure returns (uint32) {\\n        // No need to adjust if there hasn't been an overflow\\n\\n        if (_a <= _timestamp && _b <= _timestamp) return _a - _b;\\n\\n        uint256 aAdjusted = _a > _timestamp ? _a : _a + 2**32;\\n        uint256 bAdjusted = _b > _timestamp ? _b : _b + 2**32;\\n\\n        return uint32(aAdjusted - bAdjusted);\\n    }\\n}\\n\",\"keccak256\":\"0x20630cf89e7b92462946defe979fd0e69fa119841d55886121948ad810778c74\",\"license\":\"GPL-3.0\"},\"@pooltogether/v4-core/contracts/libraries/RingBufferLib.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.6;\\n\\nlibrary RingBufferLib {\\n    /**\\n    * @notice Returns wrapped TWAB index.\\n    * @dev  In order to navigate the TWAB circular buffer, we need to use the modulo operator.\\n    * @dev  For example, if `_index` is equal to 32 and the TWAB circular buffer is of `_cardinality` 32,\\n    *       it will return 0 and will point to the first element of the array.\\n    * @param _index Index used to navigate through the TWAB circular buffer.\\n    * @param _cardinality TWAB buffer cardinality.\\n    * @return TWAB index.\\n    */\\n    function wrap(uint256 _index, uint256 _cardinality) internal pure returns (uint256) {\\n        return _index % _cardinality;\\n    }\\n\\n    /**\\n    * @notice Computes the negative offset from the given index, wrapped by the cardinality.\\n    * @dev  We add `_cardinality` to `_index` to be able to offset even if `_amount` is superior to `_cardinality`.\\n    * @param _index The index from which to offset\\n    * @param _amount The number of indices to offset.  This is subtracted from the given index.\\n    * @param _cardinality The number of elements in the ring buffer\\n    * @return Offsetted index.\\n     */\\n    function offset(\\n        uint256 _index,\\n        uint256 _amount,\\n        uint256 _cardinality\\n    ) internal pure returns (uint256) {\\n        return wrap(_index + _cardinality - _amount, _cardinality);\\n    }\\n\\n    /// @notice Returns the index of the last recorded TWAB\\n    /// @param _nextIndex The next available twab index.  This will be recorded to next.\\n    /// @param _cardinality The cardinality of the TWAB history.\\n    /// @return The index of the last recorded TWAB\\n    function newestIndex(uint256 _nextIndex, uint256 _cardinality)\\n        internal\\n        pure\\n        returns (uint256)\\n    {\\n        if (_cardinality == 0) {\\n            return 0;\\n        }\\n\\n        return wrap(_nextIndex + _cardinality - 1, _cardinality);\\n    }\\n\\n    /// @notice Computes the ring buffer index that follows the given one, wrapped by cardinality\\n    /// @param _index The index to increment\\n    /// @param _cardinality The number of elements in the Ring Buffer\\n    /// @return The next index relative to the given index.  Will wrap around to 0 if the next index == cardinality\\n    function nextIndex(uint256 _index, uint256 _cardinality)\\n        internal\\n        pure\\n        returns (uint256)\\n    {\\n        return wrap(_index + 1, _cardinality);\\n    }\\n}\\n\",\"keccak256\":\"0x052e3bf6bfb30f32950e322c853589a8d153cf34f4b1ee292b17eb46f2ae656c\",\"license\":\"GPL-3.0\"},\"@pooltogether/v4-core/contracts/libraries/TwabLib.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity 0.8.6;\\n\\nimport \\\"./ExtendedSafeCastLib.sol\\\";\\nimport \\\"./OverflowSafeComparatorLib.sol\\\";\\nimport \\\"./RingBufferLib.sol\\\";\\nimport \\\"./ObservationLib.sol\\\";\\n\\n/**\\n  * @title  PoolTogether V4 TwabLib (Library)\\n  * @author PoolTogether Inc Team\\n  * @dev    Time-Weighted Average Balance Library for ERC20 tokens.\\n  * @notice This TwabLib adds on-chain historical lookups to a user(s) time-weighted average balance.\\n            Each user is mapped to an Account struct containing the TWAB history (ring bufffer) and\\n            ring buffer parameters. Every token.transfer() creates a new TWAB checkpoint. The new TWAB\\n            checkpoint is stored in the circular ring buffer, as either a new checkpoint or rewriting\\n            a previous checkpoint with new parameters. The TwabLib (using existing blocktimes 1block/15sec)\\n            guarantees minimum 7.4 years of search history.\\n */\\nlibrary TwabLib {\\n    using OverflowSafeComparatorLib for uint32;\\n    using ExtendedSafeCastLib for uint256;\\n\\n    /**\\n      * @notice Sets max ring buffer length in the Account.twabs Observation list.\\n                As users transfer/mint/burn tickets new Observation checkpoints are\\n                recorded. The current max cardinality guarantees a six month minimum,\\n                of historical accurate lookups with current estimates of 1 new block\\n                every 15 seconds - the of course contain a transfer to trigger an\\n                observation write to storage.\\n      * @dev    The user Account.AccountDetails.cardinality parameter can NOT exceed\\n                the max cardinality variable. Preventing \\\"corrupted\\\" ring buffer lookup\\n                pointers and new observation checkpoints.\\n\\n                The MAX_CARDINALITY in fact guarantees at least 7.4 years of records:\\n                If 14 = block time in seconds\\n                (2**24) * 14 = 234881024 seconds of history\\n                234881024 / (365 * 24 * 60 * 60) ~= 7.44 years\\n    */\\n    uint24 public constant MAX_CARDINALITY = 16777215; // 2**24\\n\\n    /** @notice Struct ring buffer parameters for single user Account\\n      * @param balance       Current balance for an Account\\n      * @param nextTwabIndex Next uninitialized or updatable ring buffer checkpoint storage slot\\n      * @param cardinality   Current total \\\"initialized\\\" ring buffer checkpoints for single user AccountDetails.\\n                             Used to set initial boundary conditions for an efficient binary search.\\n    */\\n    struct AccountDetails {\\n        uint208 balance;\\n        uint24 nextTwabIndex;\\n        uint24 cardinality;\\n    }\\n\\n    /// @notice Combines account details with their twab history\\n    /// @param details The account details\\n    /// @param twabs The history of twabs for this account\\n    struct Account {\\n        AccountDetails details;\\n        ObservationLib.Observation[MAX_CARDINALITY] twabs;\\n    }\\n\\n    /// @notice Increases an account's balance and records a new twab.\\n    /// @param _account The account whose balance will be increased\\n    /// @param _amount The amount to increase the balance by\\n    /// @param _currentTime The current time\\n    /// @return accountDetails The new AccountDetails\\n    /// @return twab The user's latest TWAB\\n    /// @return isNew Whether the TWAB is new\\n    function increaseBalance(\\n        Account storage _account,\\n        uint208 _amount,\\n        uint32 _currentTime\\n    )\\n        internal\\n        returns (\\n            AccountDetails memory accountDetails,\\n            ObservationLib.Observation memory twab,\\n            bool isNew\\n        )\\n    {\\n        AccountDetails memory _accountDetails = _account.details;\\n        (accountDetails, twab, isNew) = _nextTwab(_account.twabs, _accountDetails, _currentTime);\\n        accountDetails.balance = _accountDetails.balance + _amount;\\n    }\\n\\n    /** @notice Calculates the next TWAB checkpoint for an account with a decreasing balance.\\n     * @dev    With Account struct and amount decreasing calculates the next TWAB observable checkpoint.\\n     * @param _account        Account whose balance will be decreased\\n     * @param _amount         Amount to decrease the balance by\\n     * @param _revertMessage  Revert message for insufficient balance\\n     * @return accountDetails Updated Account.details struct\\n     * @return twab           TWAB observation (with decreasing average)\\n     * @return isNew          Whether TWAB is new or calling twice in the same block\\n     */\\n    function decreaseBalance(\\n        Account storage _account,\\n        uint208 _amount,\\n        string memory _revertMessage,\\n        uint32 _currentTime\\n    )\\n        internal\\n        returns (\\n            AccountDetails memory accountDetails,\\n            ObservationLib.Observation memory twab,\\n            bool isNew\\n        )\\n    {\\n        AccountDetails memory _accountDetails = _account.details;\\n\\n        require(_accountDetails.balance >= _amount, _revertMessage);\\n\\n        (accountDetails, twab, isNew) = _nextTwab(_account.twabs, _accountDetails, _currentTime);\\n        unchecked {\\n            accountDetails.balance -= _amount;\\n        }\\n    }\\n\\n    /** @notice Calculates the average balance held by a user for a given time frame.\\n      * @dev    Finds the average balance between start and end timestamp epochs.\\n                Validates the supplied end time is within the range of elapsed time i.e. less then timestamp of now.\\n      * @param _twabs          Individual user Observation recorded checkpoints passed as storage pointer\\n      * @param _accountDetails User AccountDetails struct loaded in memory\\n      * @param _startTime      Start of timestamp range as an epoch\\n      * @param _endTime        End of timestamp range as an epoch\\n      * @param _currentTime    Block.timestamp\\n      * @return Average balance of user held between epoch timestamps start and end\\n    */\\n    function getAverageBalanceBetween(\\n        ObservationLib.Observation[MAX_CARDINALITY] storage _twabs,\\n        AccountDetails memory _accountDetails,\\n        uint32 _startTime,\\n        uint32 _endTime,\\n        uint32 _currentTime\\n    ) internal view returns (uint256) {\\n        uint32 endTime = _endTime > _currentTime ? _currentTime : _endTime;\\n\\n        return\\n            _getAverageBalanceBetween(_twabs, _accountDetails, _startTime, endTime, _currentTime);\\n    }\\n\\n    /// @notice Retrieves the oldest TWAB\\n    /// @param _twabs The storage array of twabs\\n    /// @param _accountDetails The TWAB account details\\n    /// @return index The index of the oldest TWAB in the twabs array\\n    /// @return twab The oldest TWAB\\n    function oldestTwab(\\n        ObservationLib.Observation[MAX_CARDINALITY] storage _twabs,\\n        AccountDetails memory _accountDetails\\n    ) internal view returns (uint24 index, ObservationLib.Observation memory twab) {\\n        index = _accountDetails.nextTwabIndex;\\n        twab = _twabs[index];\\n\\n        // If the TWAB is not initialized we go to the beginning of the TWAB circular buffer at index 0\\n        if (twab.timestamp == 0) {\\n            index = 0;\\n            twab = _twabs[0];\\n        }\\n    }\\n\\n    /// @notice Retrieves the newest TWAB\\n    /// @param _twabs The storage array of twabs\\n    /// @param _accountDetails The TWAB account details\\n    /// @return index The index of the newest TWAB in the twabs array\\n    /// @return twab The newest TWAB\\n    function newestTwab(\\n        ObservationLib.Observation[MAX_CARDINALITY] storage _twabs,\\n        AccountDetails memory _accountDetails\\n    ) internal view returns (uint24 index, ObservationLib.Observation memory twab) {\\n        index = uint24(RingBufferLib.newestIndex(_accountDetails.nextTwabIndex, MAX_CARDINALITY));\\n        twab = _twabs[index];\\n    }\\n\\n    /// @notice Retrieves amount at `_targetTime` timestamp\\n    /// @param _twabs List of TWABs to search through.\\n    /// @param _accountDetails Accounts details\\n    /// @param _targetTime Timestamp at which the reserved TWAB should be for.\\n    /// @return uint256 TWAB amount at `_targetTime`.\\n    function getBalanceAt(\\n        ObservationLib.Observation[MAX_CARDINALITY] storage _twabs,\\n        AccountDetails memory _accountDetails,\\n        uint32 _targetTime,\\n        uint32 _currentTime\\n    ) internal view returns (uint256) {\\n        uint32 timeToTarget = _targetTime > _currentTime ? _currentTime : _targetTime;\\n        return _getBalanceAt(_twabs, _accountDetails, timeToTarget, _currentTime);\\n    }\\n\\n    /// @notice Calculates the average balance held by a user for a given time frame.\\n    /// @param _startTime The start time of the time frame.\\n    /// @param _endTime The end time of the time frame.\\n    /// @return The average balance that the user held during the time frame.\\n    function _getAverageBalanceBetween(\\n        ObservationLib.Observation[MAX_CARDINALITY] storage _twabs,\\n        AccountDetails memory _accountDetails,\\n        uint32 _startTime,\\n        uint32 _endTime,\\n        uint32 _currentTime\\n    ) private view returns (uint256) {\\n        (uint24 oldestTwabIndex, ObservationLib.Observation memory oldTwab) = oldestTwab(\\n            _twabs,\\n            _accountDetails\\n        );\\n\\n        (uint24 newestTwabIndex, ObservationLib.Observation memory newTwab) = newestTwab(\\n            _twabs,\\n            _accountDetails\\n        );\\n\\n        ObservationLib.Observation memory startTwab = _calculateTwab(\\n            _twabs,\\n            _accountDetails,\\n            newTwab,\\n            oldTwab,\\n            newestTwabIndex,\\n            oldestTwabIndex,\\n            _startTime,\\n            _currentTime\\n        );\\n\\n        ObservationLib.Observation memory endTwab = _calculateTwab(\\n            _twabs,\\n            _accountDetails,\\n            newTwab,\\n            oldTwab,\\n            newestTwabIndex,\\n            oldestTwabIndex,\\n            _endTime,\\n            _currentTime\\n        );\\n\\n        // Difference in amount / time\\n        return (endTwab.amount - startTwab.amount) / OverflowSafeComparatorLib.checkedSub(endTwab.timestamp, startTwab.timestamp, _currentTime);\\n    }\\n\\n    /** @notice Searches TWAB history and calculate the difference between amount(s)/timestamp(s) to return average balance\\n                between the Observations closes to the supplied targetTime.\\n      * @param _twabs          Individual user Observation recorded checkpoints passed as storage pointer\\n      * @param _accountDetails User AccountDetails struct loaded in memory\\n      * @param _targetTime     Target timestamp to filter Observations in the ring buffer binary search\\n      * @param _currentTime    Block.timestamp\\n      * @return uint256 Time-weighted average amount between two closest observations.\\n    */\\n    function _getBalanceAt(\\n        ObservationLib.Observation[MAX_CARDINALITY] storage _twabs,\\n        AccountDetails memory _accountDetails,\\n        uint32 _targetTime,\\n        uint32 _currentTime\\n    ) private view returns (uint256) {\\n        uint24 newestTwabIndex;\\n        ObservationLib.Observation memory afterOrAt;\\n        ObservationLib.Observation memory beforeOrAt;\\n        (newestTwabIndex, beforeOrAt) = newestTwab(_twabs, _accountDetails);\\n\\n        // If `_targetTime` is chronologically after the newest TWAB, we can simply return the current balance\\n        if (beforeOrAt.timestamp.lte(_targetTime, _currentTime)) {\\n            return _accountDetails.balance;\\n        }\\n\\n        uint24 oldestTwabIndex;\\n        // Now, set before to the oldest TWAB\\n        (oldestTwabIndex, beforeOrAt) = oldestTwab(_twabs, _accountDetails);\\n\\n        // If `_targetTime` is chronologically before the oldest TWAB, we can early return\\n        if (_targetTime.lt(beforeOrAt.timestamp, _currentTime)) {\\n            return 0;\\n        }\\n\\n        // Otherwise, we perform the `binarySearch`\\n        (beforeOrAt, afterOrAt) = ObservationLib.binarySearch(\\n            _twabs,\\n            newestTwabIndex,\\n            oldestTwabIndex,\\n            _targetTime,\\n            _accountDetails.cardinality,\\n            _currentTime\\n        );\\n\\n        // Sum the difference in amounts and divide by the difference in timestamps.\\n        // The time-weighted average balance uses time measured between two epoch timestamps as\\n        // a constaint on the measurement when calculating the time weighted average balance.\\n        return\\n            (afterOrAt.amount - beforeOrAt.amount) / OverflowSafeComparatorLib.checkedSub(afterOrAt.timestamp, beforeOrAt.timestamp, _currentTime);\\n    }\\n\\n    /** @notice Calculates a user TWAB for a target timestamp using the historical TWAB records.\\n                The balance is linearly interpolated: amount differences / timestamp differences\\n                using the simple (after.amount - before.amount / end.timestamp - start.timestamp) formula.\\n    /** @dev    Binary search in _calculateTwab fails when searching out of bounds. Thus, before\\n                searching we exclude target timestamps out of range of newest/oldest TWAB(s).\\n                IF a search is before or after the range we \\\"extrapolate\\\" a Observation from the expected state.\\n      * @param _twabs           Individual user Observation recorded checkpoints passed as storage pointer\\n      * @param _accountDetails  User AccountDetails struct loaded in memory\\n      * @param _newestTwab      Newest TWAB in history (end of ring buffer)\\n      * @param _oldestTwab      Olderst TWAB in history (end of ring buffer)\\n      * @param _newestTwabIndex Pointer in ring buffer to newest TWAB\\n      * @param _oldestTwabIndex Pointer in ring buffer to oldest TWAB\\n      * @param _targetTimestamp Epoch timestamp to calculate for time (T) in the TWAB\\n      * @param _time            Block.timestamp\\n      * @return accountDetails Updated Account.details struct\\n    */\\n    function _calculateTwab(\\n        ObservationLib.Observation[MAX_CARDINALITY] storage _twabs,\\n        AccountDetails memory _accountDetails,\\n        ObservationLib.Observation memory _newestTwab,\\n        ObservationLib.Observation memory _oldestTwab,\\n        uint24 _newestTwabIndex,\\n        uint24 _oldestTwabIndex,\\n        uint32 _targetTimestamp,\\n        uint32 _time\\n    ) private view returns (ObservationLib.Observation memory) {\\n        // If `_targetTimestamp` is chronologically after the newest TWAB, we extrapolate a new one\\n        if (_newestTwab.timestamp.lt(_targetTimestamp, _time)) {\\n            return _computeNextTwab(_newestTwab, _accountDetails.balance, _targetTimestamp);\\n        }\\n\\n        if (_newestTwab.timestamp == _targetTimestamp) {\\n            return _newestTwab;\\n        }\\n\\n        if (_oldestTwab.timestamp == _targetTimestamp) {\\n            return _oldestTwab;\\n        }\\n\\n        // If `_targetTimestamp` is chronologically before the oldest TWAB, we create a zero twab\\n        if (_targetTimestamp.lt(_oldestTwab.timestamp, _time)) {\\n            return ObservationLib.Observation({ amount: 0, timestamp: _targetTimestamp });\\n        }\\n\\n        // Otherwise, both timestamps must be surrounded by twabs.\\n        (\\n            ObservationLib.Observation memory beforeOrAtStart,\\n            ObservationLib.Observation memory afterOrAtStart\\n        ) = ObservationLib.binarySearch(\\n                _twabs,\\n                _newestTwabIndex,\\n                _oldestTwabIndex,\\n                _targetTimestamp,\\n                _accountDetails.cardinality,\\n                _time\\n            );\\n\\n        uint224 heldBalance = (afterOrAtStart.amount - beforeOrAtStart.amount) /\\n            OverflowSafeComparatorLib.checkedSub(afterOrAtStart.timestamp, beforeOrAtStart.timestamp, _time);\\n\\n        return _computeNextTwab(beforeOrAtStart, heldBalance, _targetTimestamp);\\n    }\\n\\n    /**\\n     * @notice Calculates the next TWAB using the newestTwab and updated balance.\\n     * @dev    Storage of the TWAB obersation is managed by the calling function and not _computeNextTwab.\\n     * @param _currentTwab    Newest Observation in the Account.twabs list\\n     * @param _currentBalance User balance at time of most recent (newest) checkpoint write\\n     * @param _time           Current block.timestamp\\n     * @return TWAB Observation\\n     */\\n    function _computeNextTwab(\\n        ObservationLib.Observation memory _currentTwab,\\n        uint224 _currentBalance,\\n        uint32 _time\\n    ) private pure returns (ObservationLib.Observation memory) {\\n        // New twab amount = last twab amount (or zero) + (current amount * elapsed seconds)\\n        return\\n            ObservationLib.Observation({\\n                amount: _currentTwab.amount +\\n                    _currentBalance *\\n                    (_time.checkedSub(_currentTwab.timestamp, _time)),\\n                timestamp: _time\\n            });\\n    }\\n\\n    /// @notice Sets a new TWAB Observation at the next available index and returns the new account details.\\n    /// @dev Note that if _currentTime is before the last observation timestamp, it appears as an overflow\\n    /// @param _twabs The twabs array to insert into\\n    /// @param _accountDetails The current account details\\n    /// @param _currentTime The current time\\n    /// @return accountDetails The new account details\\n    /// @return twab The newest twab (may or may not be brand-new)\\n    /// @return isNew Whether the newest twab was created by this call\\n    function _nextTwab(\\n        ObservationLib.Observation[MAX_CARDINALITY] storage _twabs,\\n        AccountDetails memory _accountDetails,\\n        uint32 _currentTime\\n    )\\n        private\\n        returns (\\n            AccountDetails memory accountDetails,\\n            ObservationLib.Observation memory twab,\\n            bool isNew\\n        )\\n    {\\n        (, ObservationLib.Observation memory _newestTwab) = newestTwab(_twabs, _accountDetails);\\n\\n        // if we're in the same block, return\\n        if (_newestTwab.timestamp == _currentTime) {\\n            return (_accountDetails, _newestTwab, false);\\n        }\\n\\n        ObservationLib.Observation memory newTwab = _computeNextTwab(\\n            _newestTwab,\\n            _accountDetails.balance,\\n            _currentTime\\n        );\\n\\n        _twabs[_accountDetails.nextTwabIndex] = newTwab;\\n\\n        AccountDetails memory nextAccountDetails = push(_accountDetails);\\n\\n        return (nextAccountDetails, newTwab, true);\\n    }\\n\\n    /// @notice \\\"Pushes\\\" a new element on the AccountDetails ring buffer, and returns the new AccountDetails\\n    /// @param _accountDetails The account details from which to pull the cardinality and next index\\n    /// @return The new AccountDetails\\n    function push(AccountDetails memory _accountDetails)\\n        internal\\n        pure\\n        returns (AccountDetails memory)\\n    {\\n        _accountDetails.nextTwabIndex = uint24(\\n            RingBufferLib.nextIndex(_accountDetails.nextTwabIndex, MAX_CARDINALITY)\\n        );\\n\\n        // Prevent the Account specific cardinality from exceeding the MAX_CARDINALITY.\\n        // The ring buffer length is limited by MAX_CARDINALITY. IF the account.cardinality\\n        // exceeds the max cardinality, new observations would be incorrectly set or the\\n        // observation would be out of \\\"bounds\\\" of the ring buffer. Once reached the\\n        // AccountDetails.cardinality will continue to be equal to max cardinality.\\n        if (_accountDetails.cardinality < MAX_CARDINALITY) {\\n            _accountDetails.cardinality += 1;\\n        }\\n\\n        return _accountDetails;\\n    }\\n}\\n\",\"keccak256\":\"0xa9cd1103707325d2eaba038d7c0f2b271d934448b8782b82f922653eccb8c90a\",\"license\":\"GPL-3.0\"}},\"version\":1}",
  "bytecode": "0x6101a06040527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9610120527f94019368dc6b2ee4ac32010c9d0081ec29874325b541829d001d22c296b5246c610180523480156200005c57600080fd5b5060405162003cbf38038062003cbf8339810160408190526200007f916200041f565b838383836040518060400160405280601c81526020017f506f6f6c546f67657468657220436f6e74726f6c6c6564546f6b656e0000000081525080604051806040016040528060018152602001603160f81b81525086868160039080519060200190620000ee929190620002e8565b50805162000104906004906020840190620002e8565b5050825160209384012082519284019290922060c083815260e08290524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818a018190528183019890985260608101959095526080808601939093523085830152805180860390920182529390920190925280519401939093209092526101005250506001600160a01b038116620002015760405162461bcd60e51b815260206004820152602b60248201527f436f6e74726f6c6c6564546f6b656e2f636f6e74726f6c6c65722d6e6f742d7a60448201526a65726f2d6164647265737360a81b60648201526084015b60405180910390fd5b6001600160601b0319606082901b166101405260ff8216620002665760405162461bcd60e51b815260206004820181905260248201527f436f6e74726f6c6c6564546f6b656e2f646563696d616c732d67742d7a65726f6044820152606401620001f8565b7fff0000000000000000000000000000000000000000000000000000000000000060f883901b16610160526040516001600160a01b038216907fde72fc29218361f33503847e6f32be813f9ec92fc7c772bb59e46675c890fd0e90620002d290879087908790620004f1565b60405180910390a25050505050505050620005b4565b828054620002f69062000561565b90600052602060002090601f0160209004810192826200031a576000855562000365565b82601f106200033557805160ff191683800117855562000365565b8280016001018555821562000365579182015b828111156200036557825182559160200191906001019062000348565b506200037392915062000377565b5090565b5b8082111562000373576000815560010162000378565b600082601f830112620003a057600080fd5b81516001600160401b0380821115620003bd57620003bd6200059e565b604051601f8301601f19908116603f01168101908282118183101715620003e857620003e86200059e565b816040528381528660208588010111156200040257600080fd5b620004158460208301602089016200052e565b9695505050505050565b600080600080608085870312156200043657600080fd5b84516001600160401b03808211156200044e57600080fd5b6200045c888389016200038e565b955060208701519150808211156200047357600080fd5b5062000482878288016200038e565b935050604085015160ff811681146200049a57600080fd5b60608601519092506001600160a01b0381168114620004b857600080fd5b939692955090935050565b60008151808452620004dd8160208601602086016200052e565b601f01601f19169290920160200192915050565b606081526000620005066060830186620004c3565b82810360208401526200051a8186620004c3565b91505060ff83166040830152949350505050565b60005b838110156200054b57818101518382015260200162000531565b838111156200055b576000848401525b50505050565b600181811c908216806200057657607f821691505b602082108114156200059857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b60805160a05160c05160e05161010051610120516101405160601c6101605160f81c61018051613678620006476000396000610d600152600061031b0152600081816105920152818161077a015281816108d001528181610a6e0152610c950152600061108501526000611669015260006116b801526000611693015260006116170152600061164001526136786000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c806368c7fd571161010f57806395d89b41116100a2578063a9059cbb11610071578063a9059cbb1461052e578063d505accf14610541578063dd62ed3e14610554578063f77c47911461058d57600080fd5b806395d89b41146104ed57806398b16f36146104f55780639ecb037014610508578063a457c2d71461051b57600080fd5b80638d22ea2a116100de5780638d22ea2a1461046d5780638e6d536a146104b457806390596dd1146104c7578063919974dc146104da57600080fd5b806368c7fd571461040b57806370a082311461041e5780637ecebe001461044757806385beb5f11461045a57600080fd5b806333e39b61116101875780635c19a95c116101565780635c19a95c146103b25780635d7b0758146103c5578063613ed6bd146103d8578063631b5dfb146103f857600080fd5b806333e39b61146103455780633644e5151461035a57806336bb2a3814610362578063395093511461039f57600080fd5b806323b872dd116101c357806323b872dd1461023d5780632aceb534146102505780632d0dd68614610301578063313ce5671461031457600080fd5b806306fdde03146101ea578063095ea7b31461020857806318160ddd1461022b575b600080fd5b6101f26105b4565b6040516101ff9190613369565b60405180910390f35b61021b6102163660046131c5565b610646565b60405190151581526020016101ff565b6002545b6040519081526020016101ff565b61021b61024b366004612fae565b61065d565b6102c961025e366004612f60565b6040805160608082018352600080835260208084018290529284018190526001600160a01b03949094168452600682529282902082519384018352546001600160d01b038116845262ffffff600160d01b8204811692850192909252600160e81b9004169082015290565b6040805182516001600160d01b0316815260208084015162ffffff9081169183019190915292820151909216908201526060016101ff565b61022f61030f36600461330a565b610723565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101ff565b610358610353366004612f7b565b61076f565b005b61022f6107f5565b610375610370366004613187565b610804565b6040805182516001600160e01b0316815260209283015163ffffffff1692810192909252016101ff565b61021b6103ad3660046131c5565b61087c565b6103586103c0366004612f60565b6108b8565b6103586103d33660046131c5565b6108c5565b6103eb6103e63660046130b3565b610947565b6040516101ff9190613325565b610358610406366004612fae565b610a63565b6103eb610419366004613106565b610b3c565b61022f61042c366004612f60565b6001600160a01b031660009081526020819052604090205490565b61022f610455366004612f60565b610b6e565b6103eb61046836600461325c565b610b8c565b61049c61047b366004612f60565b6001600160a01b039081166000908152630100000760205260409020541690565b6040516001600160a01b0390911681526020016101ff565b6103eb6104c236600461329e565b610c6f565b6103586104d53660046131c5565b610c8a565b6103586104e8366004613054565b610d0c565b6101f2610e8c565b61022f610503366004613219565b610e9b565b61022f6105163660046131ef565b610f0c565b61021b6105293660046131c5565b610f73565b61021b61053c3660046131c5565b611024565b61035861054f366004612fea565b611031565b61022f610562366004612f7b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b61049c7f000000000000000000000000000000000000000000000000000000000000000081565b6060600380546105c390613526565b80601f01602080910402602001604051908101604052809291908181526020018280546105ef90613526565b801561063c5780601f106106115761010080835404028352916020019161063c565b820191906000526020600020905b81548152906001019060200180831161061f57829003601f168201915b5050505050905090565b6000610653338484611195565b5060015b92915050565b600061066a8484846112ed565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156107095760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6107168533858403611195565b60019150505b9392505050565b604080516060810182526007546001600160d01b038116825262ffffff600160d01b820481166020840152600160e81b9091041691810191909152600090610657906008908442611511565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107e75760405162461bcd60e51b815260206004820152601f60248201527f436f6e74726f6c6c6564546f6b656e2f6f6e6c792d636f6e74726f6c6c6572006044820152606401610700565b6107f1828261153d565b5050565b60006107ff611613565b905090565b60408051808201909152600080825260208201526001600160a01b038316600090815260066020526040902060010161ffff831662ffffff811061084a5761084a6135ea565b604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff1660208201529392505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916106539185906108b3908690613429565b611195565b6108c2338261153d565b50565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461093d5760405162461bcd60e51b815260206004820152601f60248201527f436f6e74726f6c6c6564546f6b656e2f6f6e6c792d636f6e74726f6c6c6572006044820152606401610700565b6107f18282611706565b60608160008167ffffffffffffffff81111561096557610965613600565b60405190808252806020026020018201604052801561098e578160200160208202803683370190505b506001600160a01b0387166000908152600660209081526040808320815160608101835281546001600160d01b038116825262ffffff600160d01b8204811695830195909552600160e81b900490931691830191909152929350905b84811015610a5657610a2783600101838a8a85818110610a0c57610a0c6135ea565b9050602002016020810190610a21919061330a565b42611511565b848281518110610a3957610a396135ea565b602090810291909101015280610a4e8161355b565b9150506109ea565b5091979650505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610adb5760405162461bcd60e51b815260206004820152601f60248201527f436f6e74726f6c6c6564546f6b656e2f6f6e6c792d636f6e74726f6c6c6572006044820152606401610700565b816001600160a01b0316836001600160a01b031614610b2d576001600160a01b03828116600090815260016020908152604080832093871683529290522054610b2d90839085906108b39085906134f2565b610b3782826117f1565b505050565b6001600160a01b0385166000908152600660205260409020606090610b649086868686611982565b9695505050505050565b6001600160a01b038116600090815260056020526040812054610657565b60608160008167ffffffffffffffff811115610baa57610baa613600565b604051908082528060200260200182016040528015610bd3578160200160208202803683370190505b50604080516060810182526007546001600160d01b038116825262ffffff600160d01b820481166020840152600160e81b909104169181019190915290915060005b83811015610c6457610c35600883898985818110610a0c57610a0c6135ea565b838281518110610c4757610c476135ea565b602090810291909101015280610c5c8161355b565b915050610c15565b509095945050505050565b6060610c7f600786868686611982565b90505b949350505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d025760405162461bcd60e51b815260206004820152601f60248201527f436f6e74726f6c6c6564546f6b656e2f6f6e6c792d636f6e74726f6c6c6572006044820152606401610700565b6107f182826117f1565b83421115610d5c5760405162461bcd60e51b815260206004820181905260248201527f5469636b65742f64656c65676174652d657870697265642d646561646c696e656044820152606401610700565b60007f00000000000000000000000000000000000000000000000000000000000000008787610d8a8a611b21565b6040805160208101959095526001600160a01b039384169085015291166060830152608082015260a0810186905260c0016040516020818303038152906040528051906020012090506000610dde82611b49565b90506000610dee82878787611bb2565b9050886001600160a01b0316816001600160a01b031614610e775760405162461bcd60e51b815260206004820152602160248201527f5469636b65742f64656c65676174652d696e76616c69642d7369676e6174757260448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610700565b610e81898961153d565b505050505050505050565b6060600480546105c390613526565b6001600160a01b0383166000908152600660209081526040808320815160608101835281546001600160d01b038116825262ffffff600160d01b8204811695830195909552600160e81b90049093169183019190915290610f03906001830190868642611bda565b95945050505050565b6001600160a01b0382166000908152600660209081526040808320815160608101835281546001600160d01b038116825262ffffff600160d01b8204811695830195909552600160e81b90049093169183019190915290610c829060018301908542611511565b3360009081526001602090815260408083206001600160a01b03861684529091528120548281101561100d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610700565b61101a3385858403611195565b5060019392505050565b60006106533384846112ed565b834211156110815760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610700565b60007f00000000000000000000000000000000000000000000000000000000000000008888886110b08c611b21565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e001604051602081830303815290604052805190602001209050600061110b82611b49565b9050600061111b82878787611bb2565b9050896001600160a01b0316816001600160a01b03161461117e5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610700565b6111898a8a8a611195565b50505050505050505050565b6001600160a01b0383166112105760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610700565b6001600160a01b03821661128c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610700565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166113695760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610700565b6001600160a01b0382166113e55760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610700565b6113f0838383611c12565b6001600160a01b0383166000908152602081905260409020548181101561147f5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610700565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906114b6908490613429565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161150291815260200190565b60405180910390a35b50505050565b6000808263ffffffff168463ffffffff161161152d578361152f565b825b9050610b6486868386611ca5565b6001600160a01b038281166000908152602081815260408083205463010000079092529091205490919081169083168114156115795750505050565b6001600160a01b03848116600090815263010000076020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169185169190911790556115cd818484611dbe565b826001600160a01b0316846001600160a01b03167f4bc154dd35d6a5cb9206482ecb473cdbf2473006d6bce728b9cc0741bcc59ea260405160405180910390a350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046141561166257507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6001600160a01b03821661175c5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610700565b61176860008383611c12565b806002600082825461177a9190613429565b90915550506001600160a01b038216600090815260208190526040812080548392906117a7908490613429565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b03821661186d5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610700565b61187982600083611c12565b6001600160a01b038216600090815260208190526040902054818110156119085760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610700565b6001600160a01b03831660009081526020819052604081208383039055600280548492906119379084906134f2565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6060838281146119fa5760405162461bcd60e51b815260206004820152602360248201527f5469636b65742f73746172742d656e642d74696d65732d6c656e6774682d6d6160448201527f74636800000000000000000000000000000000000000000000000000000000006064820152608401610700565b6040805160608101825288546001600160d01b038116825262ffffff600160d01b820481166020840152600160e81b909104169181019190915260008267ffffffffffffffff811115611a4f57611a4f613600565b604051908082528060200260200182016040528015611a78578160200160208202803683370190505b5090504260005b84811015611b1257611ae38b600101858c8c85818110611aa157611aa16135ea565b9050602002016020810190611ab6919061330a565b8b8b86818110611ac857611ac86135ea565b9050602002016020810190611add919061330a565b86611bda565b838281518110611af557611af56135ea565b602090810291909101015280611b0a8161355b565b915050611a7f565b50909998505050505050505050565b6001600160a01b03811660009081526005602052604090208054600181018255905b50919050565b6000610657611b56611613565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000611bc387878787611e1e565b91509150611bd081611f0b565b5095945050505050565b6000808263ffffffff168463ffffffff1611611bf65783611bf8565b825b9050611c0787878784876120fc565b979650505050505050565b816001600160a01b0316836001600160a01b03161415611c3157505050565b60006001600160a01b03841615611c6257506001600160a01b03808416600090815263010000076020526040902054165b60006001600160a01b03841615611c9357506001600160a01b03808416600090815263010000076020526040902054165b611c9e828285611dbe565b5050505050565b604080518082019091526000808252602082018190529081906040805180820190915260008082526020820152611cdc8888612198565b60208101519194509150611cfd9063ffffffff908116908890889061221816565b15611d1857505084516001600160d01b03169150610c829050565b6000611d2489896122e9565b6020810151909350909150611d459063ffffffff808a169190899061236616565b15611d57576000945050505050610c82565b611d698985838a8c604001518b612435565b8094508193505050611d848360200151836020015188612602565b63ffffffff1682600001518460000151611d9e91906134ca565b611da89190613461565b6001600160e01b03169998505050505050505050565b6001600160a01b03831615611dee57611dd783826126cc565b6001600160a01b038216611dee57611dee81612821565b6001600160a01b03821615610b3757611e07828261293a565b6001600160a01b038316610b3757610b3781612971565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611e555750600090506003611f02565b8460ff16601b14158015611e6d57508460ff16601c14155b15611e7e5750600090506004611f02565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611ed2573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611efb57600060019250925050611f02565b9150600090505b94509492505050565b6000816004811115611f1f57611f1f6135d4565b1415611f285750565b6001816004811115611f3c57611f3c6135d4565b1415611f8a5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610700565b6002816004811115611f9e57611f9e6135d4565b1415611fec5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610700565b6003816004811115612000576120006135d4565b14156120745760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610700565b6004816004811115612088576120886135d4565b14156108c25760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610700565b600080600061210b88886122e9565b9150915060008061211c8a8a612198565b9150915060006121328b8b8487878a8f8e61298c565b905060006121468c8c8588888b8f8f61298c565b905061215b816020015183602001518a612602565b63ffffffff168260000151826000015161217591906134ca565b61217f9190613461565b6001600160e01b03169c9b505050505050505050505050565b60408051808201909152600080825260208201819052906121c7836020015162ffffff1662ffffff8016612ad6565b9150838262ffffff1662ffffff81106121e2576121e26135ea565b604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff166020820152919491935090915050565b60008163ffffffff168463ffffffff161115801561224257508163ffffffff168363ffffffff1611155b1561225e578263ffffffff168463ffffffff161115905061071c565b60008263ffffffff168563ffffffff161161228d5761228863ffffffff8616640100000000613441565b612295565b8463ffffffff165b64ffffffffff16905060008363ffffffff168563ffffffff16116122cd576122c863ffffffff8616640100000000613441565b6122d5565b8463ffffffff165b64ffffffffff169091111595945050505050565b604080518082019091526000808252602082018190529082602001519150838262ffffff1662ffffff8110612320576123206135ea565b604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff166020820181905290915061235f576000915083826121e2565b9250929050565b60008163ffffffff168463ffffffff161115801561239057508163ffffffff168363ffffffff1611155b156123ab578263ffffffff168463ffffffff1610905061071c565b60008263ffffffff168563ffffffff16116123da576123d563ffffffff8616640100000000613441565b6123e2565b8463ffffffff165b64ffffffffff16905060008363ffffffff168563ffffffff161161241a5761241563ffffffff8616640100000000613441565b612422565b8463ffffffff165b64ffffffffff1690911095945050505050565b6040805180820190915260008082526020820152604080518082019091526000808252602082015260008662ffffff1690506000818962ffffff1610612480578862ffffff1661249b565b600161249162ffffff881684613429565b61249b91906134f2565b905060005b60026124ac8385613429565b6124b69190613487565b90508a6124c8828962ffffff16612b00565b62ffffff1662ffffff81106124df576124df6135ea565b604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff1660208201819052909550806125275761251f826001613429565b9350506124a0565b8b612537838a62ffffff16612b0c565b62ffffff1662ffffff811061254e5761254e6135ea565b604080518082019091529101546001600160e01b038116825263ffffffff600160e01b9091048116602083015290955060009061259390838116908c908b9061221816565b90508080156125bc57506125bc8660200151898c63ffffffff166122189092919063ffffffff16565b156125c85750506125f4565b806125df576125d86001846134f2565b93506125ed565b6125ea836001613429565b94505b50506124a0565b505050965096945050505050565b60008163ffffffff168463ffffffff161115801561262c57508163ffffffff168363ffffffff1611155b156126425761263b8385613509565b905061071c565b60008263ffffffff168563ffffffff16116126715761266c63ffffffff8616640100000000613441565b612679565b8463ffffffff165b64ffffffffff16905060008363ffffffff168563ffffffff16116126b1576126ac63ffffffff8616640100000000613441565b6126b9565b8463ffffffff165b64ffffffffff169050610b6481836134f2565b806126d5575050565b6001600160a01b0382166000908152600660205260408120908080612739846126fd87612b1c565b6040518060400160405280601b81526020017f5469636b65742f747761622d6275726e2d6c742d62616c616e6365000000000081525042612b9f565b82518754602085015160408601516001600160d01b039093167fffffff000000000000000000000000000000000000000000000000000000000090921691909117600160d01b62ffffff92831602177cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e81b9190921602178755919450925090508015612819576040805183516001600160e01b0316815260208085015163ffffffff16908201526001600160a01b038816917fdd3e7cd3a260a292b0b3306b2ca62f30a7349619a9d09c58109318774c6b627d910160405180910390a25b505050505050565b806128295750565b600080600061285b600761283c86612b1c565b6040518060600160405280602c8152602001613617602c913942612b9f565b825160078054602086015160408701516001600160d01b039094167fffffff000000000000000000000000000000000000000000000000000000000090921691909117600160d01b62ffffff92831602177cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e81b919093160291909117905591945092509050801561150b576040805183516001600160e01b0316815260208085015163ffffffff16908201527f3375b905d617084fa6b7531688cc8046feb1f1a0b8ba2273de03c59d8d84416c910160405180910390a150505050565b80612943575050565b6001600160a01b03821660009081526006602052604081209080806127398461296b87612b1c565b42612c63565b806129795750565b600080600061285b600761296b86612b1c565b60408051808201909152600080825260208201526129bf8383896020015163ffffffff166123669092919063ffffffff16565b156129e3576129dc8789600001516001600160d01b031685612d0c565b9050612aca565b8263ffffffff16876020015163ffffffff161415612a02575085612aca565b8263ffffffff16866020015163ffffffff161415612a21575084612aca565b612a408660200151838563ffffffff166123669092919063ffffffff16565b15612a655750604080518082019091526000815263ffffffff83166020820152612aca565b600080612a7a8b8888888e6040015189612435565b915091506000612a938260200151846020015187612602565b63ffffffff1683600001518360000151612aad91906134ca565b612ab79190613461565b9050612ac4838288612d0c565b93505050505b98975050505050505050565b600081612ae557506000610657565b61071c6001612af48486613429565b612afe91906134f2565b835b600061071c8284613594565b600061071c612afe846001613429565b60006001600160d01b03821115612b9b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203260448201527f30382062697473000000000000000000000000000000000000000000000000006064820152608401610700565b5090565b604080516060810182526000808252602082018190529181019190915260408051808201909152600080825260208201526040805160608101825287546001600160d01b0380821680845262ffffff600160d01b840481166020860152600160e81b9093049092169383019390935260009287919089161115612c355760405162461bcd60e51b81526004016107009190613369565b50612c44886001018287612d87565b8251999099036001600160d01b03168252909990985095505050505050565b604080516060810182526000808252602082018190529181019190915260408051808201909152600080825260208201526040805160608101825286546001600160d01b038116825262ffffff600160d01b820481166020840152600160e81b9091041691810191909152600090612cdf600188018287612d87565b83519296509094509250612cf49087906133be565b6001600160d01b031684525091959094509092509050565b60408051808201909152600080825260208201526040518060400160405280612d4a8660200151858663ffffffff166126029092919063ffffffff16565b612d5a9063ffffffff168661349b565b8651612d6691906133e9565b6001600160e01b031681526020018363ffffffff1681525090509392505050565b60408051606081018252600080825260208201819052918101919091526040805180820190915260008082526020820152600080612dc58787612198565b9150508463ffffffff16816020015163ffffffff161415612dee57859350915060009050612e65565b6000612e088288600001516001600160d01b031688612d0c565b90508088886020015162ffffff1662ffffff8110612e2857612e286135ea565b825160209093015163ffffffff16600160e01b026001600160e01b03909316929092179101556000612e5988612e6e565b95509093506001925050505b93509350939050565b60408051606081018252600080825260208083018290529282015290820151612e9e9062ffffff90811690612b0c565b62ffffff9081166020840152604083015181161015612b9b57600182604001818151612eca919061340b565b62ffffff169052505090565b80356001600160a01b0381168114612eed57600080fd5b919050565b60008083601f840112612f0457600080fd5b50813567ffffffffffffffff811115612f1c57600080fd5b6020830191508360208260051b850101111561235f57600080fd5b803567ffffffffffffffff81168114612eed57600080fd5b803560ff81168114612eed57600080fd5b600060208284031215612f7257600080fd5b61071c82612ed6565b60008060408385031215612f8e57600080fd5b612f9783612ed6565b9150612fa560208401612ed6565b90509250929050565b600080600060608486031215612fc357600080fd5b612fcc84612ed6565b9250612fda60208501612ed6565b9150604084013590509250925092565b600080600080600080600060e0888a03121561300557600080fd5b61300e88612ed6565b965061301c60208901612ed6565b9550604088013594506060880135935061303860808901612f4f565b925060a0880135915060c0880135905092959891949750929550565b60008060008060008060c0878903121561306d57600080fd5b61307687612ed6565b955061308460208801612ed6565b94506040870135935061309960608801612f4f565b92506080870135915060a087013590509295509295509295565b6000806000604084860312156130c857600080fd5b6130d184612ed6565b9250602084013567ffffffffffffffff8111156130ed57600080fd5b6130f986828701612ef2565b9497909650939450505050565b60008060008060006060868803121561311e57600080fd5b61312786612ed6565b9450602086013567ffffffffffffffff8082111561314457600080fd5b61315089838a01612ef2565b9096509450604088013591508082111561316957600080fd5b5061317688828901612ef2565b969995985093965092949392505050565b6000806040838503121561319a57600080fd5b6131a383612ed6565b9150602083013561ffff811681146131ba57600080fd5b809150509250929050565b600080604083850312156131d857600080fd5b6131e183612ed6565b946020939093013593505050565b6000806040838503121561320257600080fd5b61320b83612ed6565b9150612fa560208401612f37565b60008060006060848603121561322e57600080fd5b61323784612ed6565b925061324560208501612f37565b915061325360408501612f37565b90509250925092565b6000806020838503121561326f57600080fd5b823567ffffffffffffffff81111561328657600080fd5b61329285828601612ef2565b90969095509350505050565b600080600080604085870312156132b457600080fd5b843567ffffffffffffffff808211156132cc57600080fd5b6132d888838901612ef2565b909650945060208701359150808211156132f157600080fd5b506132fe87828801612ef2565b95989497509550505050565b60006020828403121561331c57600080fd5b61071c82612f37565b6020808252825182820181905260009190848201906040850190845b8181101561335d57835183529284019291840191600101613341565b50909695505050505050565b600060208083528351808285015260005b818110156133965785810183015185820160400152820161337a565b818111156133a8576000604083870101525b50601f01601f1916929092016040019392505050565b60006001600160d01b038083168185168083038211156133e0576133e06135a8565b01949350505050565b60006001600160e01b038083168185168083038211156133e0576133e06135a8565b600062ffffff8083168185168083038211156133e0576133e06135a8565b6000821982111561343c5761343c6135a8565b500190565b600064ffffffffff8083168185168083038211156133e0576133e06135a8565b60006001600160e01b038084168061347b5761347b6135be565b92169190910492915050565b600082613496576134966135be565b500490565b60006001600160e01b03808316818516818304811182151516156134c1576134c16135a8565b02949350505050565b60006001600160e01b03838116908316818110156134ea576134ea6135a8565b039392505050565b600082821015613504576135046135a8565b500390565b600063ffffffff838116908316818110156134ea576134ea6135a8565b600181811c9082168061353a57607f821691505b60208210811415611b4357634e487b7160e01b600052602260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561358d5761358d6135a8565b5060010190565b6000826135a3576135a36135be565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfe5469636b65742f6275726e2d616d6f756e742d657863656564732d746f74616c2d737570706c792d74776162a2646970667358221220db45750c1000f519fe3c159aece3b6f8c265a9af06ab7578e87d9e2f5383ceaf64736f6c63430008060033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101e55760003560e01c806368c7fd571161010f57806395d89b41116100a2578063a9059cbb11610071578063a9059cbb1461052e578063d505accf14610541578063dd62ed3e14610554578063f77c47911461058d57600080fd5b806395d89b41146104ed57806398b16f36146104f55780639ecb037014610508578063a457c2d71461051b57600080fd5b80638d22ea2a116100de5780638d22ea2a1461046d5780638e6d536a146104b457806390596dd1146104c7578063919974dc146104da57600080fd5b806368c7fd571461040b57806370a082311461041e5780637ecebe001461044757806385beb5f11461045a57600080fd5b806333e39b61116101875780635c19a95c116101565780635c19a95c146103b25780635d7b0758146103c5578063613ed6bd146103d8578063631b5dfb146103f857600080fd5b806333e39b61146103455780633644e5151461035a57806336bb2a3814610362578063395093511461039f57600080fd5b806323b872dd116101c357806323b872dd1461023d5780632aceb534146102505780632d0dd68614610301578063313ce5671461031457600080fd5b806306fdde03146101ea578063095ea7b31461020857806318160ddd1461022b575b600080fd5b6101f26105b4565b6040516101ff9190613369565b60405180910390f35b61021b6102163660046131c5565b610646565b60405190151581526020016101ff565b6002545b6040519081526020016101ff565b61021b61024b366004612fae565b61065d565b6102c961025e366004612f60565b6040805160608082018352600080835260208084018290529284018190526001600160a01b03949094168452600682529282902082519384018352546001600160d01b038116845262ffffff600160d01b8204811692850192909252600160e81b9004169082015290565b6040805182516001600160d01b0316815260208084015162ffffff9081169183019190915292820151909216908201526060016101ff565b61022f61030f36600461330a565b610723565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101ff565b610358610353366004612f7b565b61076f565b005b61022f6107f5565b610375610370366004613187565b610804565b6040805182516001600160e01b0316815260209283015163ffffffff1692810192909252016101ff565b61021b6103ad3660046131c5565b61087c565b6103586103c0366004612f60565b6108b8565b6103586103d33660046131c5565b6108c5565b6103eb6103e63660046130b3565b610947565b6040516101ff9190613325565b610358610406366004612fae565b610a63565b6103eb610419366004613106565b610b3c565b61022f61042c366004612f60565b6001600160a01b031660009081526020819052604090205490565b61022f610455366004612f60565b610b6e565b6103eb61046836600461325c565b610b8c565b61049c61047b366004612f60565b6001600160a01b039081166000908152630100000760205260409020541690565b6040516001600160a01b0390911681526020016101ff565b6103eb6104c236600461329e565b610c6f565b6103586104d53660046131c5565b610c8a565b6103586104e8366004613054565b610d0c565b6101f2610e8c565b61022f610503366004613219565b610e9b565b61022f6105163660046131ef565b610f0c565b61021b6105293660046131c5565b610f73565b61021b61053c3660046131c5565b611024565b61035861054f366004612fea565b611031565b61022f610562366004612f7b565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b61049c7f000000000000000000000000000000000000000000000000000000000000000081565b6060600380546105c390613526565b80601f01602080910402602001604051908101604052809291908181526020018280546105ef90613526565b801561063c5780601f106106115761010080835404028352916020019161063c565b820191906000526020600020905b81548152906001019060200180831161061f57829003601f168201915b5050505050905090565b6000610653338484611195565b5060015b92915050565b600061066a8484846112ed565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156107095760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e636500000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6107168533858403611195565b60019150505b9392505050565b604080516060810182526007546001600160d01b038116825262ffffff600160d01b820481166020840152600160e81b9091041691810191909152600090610657906008908442611511565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107e75760405162461bcd60e51b815260206004820152601f60248201527f436f6e74726f6c6c6564546f6b656e2f6f6e6c792d636f6e74726f6c6c6572006044820152606401610700565b6107f1828261153d565b5050565b60006107ff611613565b905090565b60408051808201909152600080825260208201526001600160a01b038316600090815260066020526040902060010161ffff831662ffffff811061084a5761084a6135ea565b604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff1660208201529392505050565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916106539185906108b3908690613429565b611195565b6108c2338261153d565b50565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461093d5760405162461bcd60e51b815260206004820152601f60248201527f436f6e74726f6c6c6564546f6b656e2f6f6e6c792d636f6e74726f6c6c6572006044820152606401610700565b6107f18282611706565b60608160008167ffffffffffffffff81111561096557610965613600565b60405190808252806020026020018201604052801561098e578160200160208202803683370190505b506001600160a01b0387166000908152600660209081526040808320815160608101835281546001600160d01b038116825262ffffff600160d01b8204811695830195909552600160e81b900490931691830191909152929350905b84811015610a5657610a2783600101838a8a85818110610a0c57610a0c6135ea565b9050602002016020810190610a21919061330a565b42611511565b848281518110610a3957610a396135ea565b602090810291909101015280610a4e8161355b565b9150506109ea565b5091979650505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610adb5760405162461bcd60e51b815260206004820152601f60248201527f436f6e74726f6c6c6564546f6b656e2f6f6e6c792d636f6e74726f6c6c6572006044820152606401610700565b816001600160a01b0316836001600160a01b031614610b2d576001600160a01b03828116600090815260016020908152604080832093871683529290522054610b2d90839085906108b39085906134f2565b610b3782826117f1565b505050565b6001600160a01b0385166000908152600660205260409020606090610b649086868686611982565b9695505050505050565b6001600160a01b038116600090815260056020526040812054610657565b60608160008167ffffffffffffffff811115610baa57610baa613600565b604051908082528060200260200182016040528015610bd3578160200160208202803683370190505b50604080516060810182526007546001600160d01b038116825262ffffff600160d01b820481166020840152600160e81b909104169181019190915290915060005b83811015610c6457610c35600883898985818110610a0c57610a0c6135ea565b838281518110610c4757610c476135ea565b602090810291909101015280610c5c8161355b565b915050610c15565b509095945050505050565b6060610c7f600786868686611982565b90505b949350505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d025760405162461bcd60e51b815260206004820152601f60248201527f436f6e74726f6c6c6564546f6b656e2f6f6e6c792d636f6e74726f6c6c6572006044820152606401610700565b6107f182826117f1565b83421115610d5c5760405162461bcd60e51b815260206004820181905260248201527f5469636b65742f64656c65676174652d657870697265642d646561646c696e656044820152606401610700565b60007f00000000000000000000000000000000000000000000000000000000000000008787610d8a8a611b21565b6040805160208101959095526001600160a01b039384169085015291166060830152608082015260a0810186905260c0016040516020818303038152906040528051906020012090506000610dde82611b49565b90506000610dee82878787611bb2565b9050886001600160a01b0316816001600160a01b031614610e775760405162461bcd60e51b815260206004820152602160248201527f5469636b65742f64656c65676174652d696e76616c69642d7369676e6174757260448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610700565b610e81898961153d565b505050505050505050565b6060600480546105c390613526565b6001600160a01b0383166000908152600660209081526040808320815160608101835281546001600160d01b038116825262ffffff600160d01b8204811695830195909552600160e81b90049093169183019190915290610f03906001830190868642611bda565b95945050505050565b6001600160a01b0382166000908152600660209081526040808320815160608101835281546001600160d01b038116825262ffffff600160d01b8204811695830195909552600160e81b90049093169183019190915290610c829060018301908542611511565b3360009081526001602090815260408083206001600160a01b03861684529091528120548281101561100d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610700565b61101a3385858403611195565b5060019392505050565b60006106533384846112ed565b834211156110815760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610700565b60007f00000000000000000000000000000000000000000000000000000000000000008888886110b08c611b21565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e001604051602081830303815290604052805190602001209050600061110b82611b49565b9050600061111b82878787611bb2565b9050896001600160a01b0316816001600160a01b03161461117e5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610700565b6111898a8a8a611195565b50505050505050505050565b6001600160a01b0383166112105760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610700565b6001600160a01b03821661128c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610700565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166113695760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610700565b6001600160a01b0382166113e55760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610700565b6113f0838383611c12565b6001600160a01b0383166000908152602081905260409020548181101561147f5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610700565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906114b6908490613429565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161150291815260200190565b60405180910390a35b50505050565b6000808263ffffffff168463ffffffff161161152d578361152f565b825b9050610b6486868386611ca5565b6001600160a01b038281166000908152602081815260408083205463010000079092529091205490919081169083168114156115795750505050565b6001600160a01b03848116600090815263010000076020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169185169190911790556115cd818484611dbe565b826001600160a01b0316846001600160a01b03167f4bc154dd35d6a5cb9206482ecb473cdbf2473006d6bce728b9cc0741bcc59ea260405160405180910390a350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046141561166257507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6001600160a01b03821661175c5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610700565b61176860008383611c12565b806002600082825461177a9190613429565b90915550506001600160a01b038216600090815260208190526040812080548392906117a7908490613429565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b03821661186d5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610700565b61187982600083611c12565b6001600160a01b038216600090815260208190526040902054818110156119085760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610700565b6001600160a01b03831660009081526020819052604081208383039055600280548492906119379084906134f2565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6060838281146119fa5760405162461bcd60e51b815260206004820152602360248201527f5469636b65742f73746172742d656e642d74696d65732d6c656e6774682d6d6160448201527f74636800000000000000000000000000000000000000000000000000000000006064820152608401610700565b6040805160608101825288546001600160d01b038116825262ffffff600160d01b820481166020840152600160e81b909104169181019190915260008267ffffffffffffffff811115611a4f57611a4f613600565b604051908082528060200260200182016040528015611a78578160200160208202803683370190505b5090504260005b84811015611b1257611ae38b600101858c8c85818110611aa157611aa16135ea565b9050602002016020810190611ab6919061330a565b8b8b86818110611ac857611ac86135ea565b9050602002016020810190611add919061330a565b86611bda565b838281518110611af557611af56135ea565b602090810291909101015280611b0a8161355b565b915050611a7f565b50909998505050505050505050565b6001600160a01b03811660009081526005602052604090208054600181018255905b50919050565b6000610657611b56611613565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000611bc387878787611e1e565b91509150611bd081611f0b565b5095945050505050565b6000808263ffffffff168463ffffffff1611611bf65783611bf8565b825b9050611c0787878784876120fc565b979650505050505050565b816001600160a01b0316836001600160a01b03161415611c3157505050565b60006001600160a01b03841615611c6257506001600160a01b03808416600090815263010000076020526040902054165b60006001600160a01b03841615611c9357506001600160a01b03808416600090815263010000076020526040902054165b611c9e828285611dbe565b5050505050565b604080518082019091526000808252602082018190529081906040805180820190915260008082526020820152611cdc8888612198565b60208101519194509150611cfd9063ffffffff908116908890889061221816565b15611d1857505084516001600160d01b03169150610c829050565b6000611d2489896122e9565b6020810151909350909150611d459063ffffffff808a169190899061236616565b15611d57576000945050505050610c82565b611d698985838a8c604001518b612435565b8094508193505050611d848360200151836020015188612602565b63ffffffff1682600001518460000151611d9e91906134ca565b611da89190613461565b6001600160e01b03169998505050505050505050565b6001600160a01b03831615611dee57611dd783826126cc565b6001600160a01b038216611dee57611dee81612821565b6001600160a01b03821615610b3757611e07828261293a565b6001600160a01b038316610b3757610b3781612971565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611e555750600090506003611f02565b8460ff16601b14158015611e6d57508460ff16601c14155b15611e7e5750600090506004611f02565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611ed2573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116611efb57600060019250925050611f02565b9150600090505b94509492505050565b6000816004811115611f1f57611f1f6135d4565b1415611f285750565b6001816004811115611f3c57611f3c6135d4565b1415611f8a5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610700565b6002816004811115611f9e57611f9e6135d4565b1415611fec5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610700565b6003816004811115612000576120006135d4565b14156120745760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610700565b6004816004811115612088576120886135d4565b14156108c25760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610700565b600080600061210b88886122e9565b9150915060008061211c8a8a612198565b9150915060006121328b8b8487878a8f8e61298c565b905060006121468c8c8588888b8f8f61298c565b905061215b816020015183602001518a612602565b63ffffffff168260000151826000015161217591906134ca565b61217f9190613461565b6001600160e01b03169c9b505050505050505050505050565b60408051808201909152600080825260208201819052906121c7836020015162ffffff1662ffffff8016612ad6565b9150838262ffffff1662ffffff81106121e2576121e26135ea565b604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff166020820152919491935090915050565b60008163ffffffff168463ffffffff161115801561224257508163ffffffff168363ffffffff1611155b1561225e578263ffffffff168463ffffffff161115905061071c565b60008263ffffffff168563ffffffff161161228d5761228863ffffffff8616640100000000613441565b612295565b8463ffffffff165b64ffffffffff16905060008363ffffffff168563ffffffff16116122cd576122c863ffffffff8616640100000000613441565b6122d5565b8463ffffffff165b64ffffffffff169091111595945050505050565b604080518082019091526000808252602082018190529082602001519150838262ffffff1662ffffff8110612320576123206135ea565b604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff166020820181905290915061235f576000915083826121e2565b9250929050565b60008163ffffffff168463ffffffff161115801561239057508163ffffffff168363ffffffff1611155b156123ab578263ffffffff168463ffffffff1610905061071c565b60008263ffffffff168563ffffffff16116123da576123d563ffffffff8616640100000000613441565b6123e2565b8463ffffffff165b64ffffffffff16905060008363ffffffff168563ffffffff161161241a5761241563ffffffff8616640100000000613441565b612422565b8463ffffffff165b64ffffffffff1690911095945050505050565b6040805180820190915260008082526020820152604080518082019091526000808252602082015260008662ffffff1690506000818962ffffff1610612480578862ffffff1661249b565b600161249162ffffff881684613429565b61249b91906134f2565b905060005b60026124ac8385613429565b6124b69190613487565b90508a6124c8828962ffffff16612b00565b62ffffff1662ffffff81106124df576124df6135ea565b604080518082019091529101546001600160e01b0381168252600160e01b900463ffffffff1660208201819052909550806125275761251f826001613429565b9350506124a0565b8b612537838a62ffffff16612b0c565b62ffffff1662ffffff811061254e5761254e6135ea565b604080518082019091529101546001600160e01b038116825263ffffffff600160e01b9091048116602083015290955060009061259390838116908c908b9061221816565b90508080156125bc57506125bc8660200151898c63ffffffff166122189092919063ffffffff16565b156125c85750506125f4565b806125df576125d86001846134f2565b93506125ed565b6125ea836001613429565b94505b50506124a0565b505050965096945050505050565b60008163ffffffff168463ffffffff161115801561262c57508163ffffffff168363ffffffff1611155b156126425761263b8385613509565b905061071c565b60008263ffffffff168563ffffffff16116126715761266c63ffffffff8616640100000000613441565b612679565b8463ffffffff165b64ffffffffff16905060008363ffffffff168563ffffffff16116126b1576126ac63ffffffff8616640100000000613441565b6126b9565b8463ffffffff165b64ffffffffff169050610b6481836134f2565b806126d5575050565b6001600160a01b0382166000908152600660205260408120908080612739846126fd87612b1c565b6040518060400160405280601b81526020017f5469636b65742f747761622d6275726e2d6c742d62616c616e6365000000000081525042612b9f565b82518754602085015160408601516001600160d01b039093167fffffff000000000000000000000000000000000000000000000000000000000090921691909117600160d01b62ffffff92831602177cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e81b9190921602178755919450925090508015612819576040805183516001600160e01b0316815260208085015163ffffffff16908201526001600160a01b038816917fdd3e7cd3a260a292b0b3306b2ca62f30a7349619a9d09c58109318774c6b627d910160405180910390a25b505050505050565b806128295750565b600080600061285b600761283c86612b1c565b6040518060600160405280602c8152602001613617602c913942612b9f565b825160078054602086015160408701516001600160d01b039094167fffffff000000000000000000000000000000000000000000000000000000000090921691909117600160d01b62ffffff92831602177cffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e81b919093160291909117905591945092509050801561150b576040805183516001600160e01b0316815260208085015163ffffffff16908201527f3375b905d617084fa6b7531688cc8046feb1f1a0b8ba2273de03c59d8d84416c910160405180910390a150505050565b80612943575050565b6001600160a01b03821660009081526006602052604081209080806127398461296b87612b1c565b42612c63565b806129795750565b600080600061285b600761296b86612b1c565b60408051808201909152600080825260208201526129bf8383896020015163ffffffff166123669092919063ffffffff16565b156129e3576129dc8789600001516001600160d01b031685612d0c565b9050612aca565b8263ffffffff16876020015163ffffffff161415612a02575085612aca565b8263ffffffff16866020015163ffffffff161415612a21575084612aca565b612a408660200151838563ffffffff166123669092919063ffffffff16565b15612a655750604080518082019091526000815263ffffffff83166020820152612aca565b600080612a7a8b8888888e6040015189612435565b915091506000612a938260200151846020015187612602565b63ffffffff1683600001518360000151612aad91906134ca565b612ab79190613461565b9050612ac4838288612d0c565b93505050505b98975050505050505050565b600081612ae557506000610657565b61071c6001612af48486613429565b612afe91906134f2565b835b600061071c8284613594565b600061071c612afe846001613429565b60006001600160d01b03821115612b9b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203260448201527f30382062697473000000000000000000000000000000000000000000000000006064820152608401610700565b5090565b604080516060810182526000808252602082018190529181019190915260408051808201909152600080825260208201526040805160608101825287546001600160d01b0380821680845262ffffff600160d01b840481166020860152600160e81b9093049092169383019390935260009287919089161115612c355760405162461bcd60e51b81526004016107009190613369565b50612c44886001018287612d87565b8251999099036001600160d01b03168252909990985095505050505050565b604080516060810182526000808252602082018190529181019190915260408051808201909152600080825260208201526040805160608101825286546001600160d01b038116825262ffffff600160d01b820481166020840152600160e81b9091041691810191909152600090612cdf600188018287612d87565b83519296509094509250612cf49087906133be565b6001600160d01b031684525091959094509092509050565b60408051808201909152600080825260208201526040518060400160405280612d4a8660200151858663ffffffff166126029092919063ffffffff16565b612d5a9063ffffffff168661349b565b8651612d6691906133e9565b6001600160e01b031681526020018363ffffffff1681525090509392505050565b60408051606081018252600080825260208201819052918101919091526040805180820190915260008082526020820152600080612dc58787612198565b9150508463ffffffff16816020015163ffffffff161415612dee57859350915060009050612e65565b6000612e088288600001516001600160d01b031688612d0c565b90508088886020015162ffffff1662ffffff8110612e2857612e286135ea565b825160209093015163ffffffff16600160e01b026001600160e01b03909316929092179101556000612e5988612e6e565b95509093506001925050505b93509350939050565b60408051606081018252600080825260208083018290529282015290820151612e9e9062ffffff90811690612b0c565b62ffffff9081166020840152604083015181161015612b9b57600182604001818151612eca919061340b565b62ffffff169052505090565b80356001600160a01b0381168114612eed57600080fd5b919050565b60008083601f840112612f0457600080fd5b50813567ffffffffffffffff811115612f1c57600080fd5b6020830191508360208260051b850101111561235f57600080fd5b803567ffffffffffffffff81168114612eed57600080fd5b803560ff81168114612eed57600080fd5b600060208284031215612f7257600080fd5b61071c82612ed6565b60008060408385031215612f8e57600080fd5b612f9783612ed6565b9150612fa560208401612ed6565b90509250929050565b600080600060608486031215612fc357600080fd5b612fcc84612ed6565b9250612fda60208501612ed6565b9150604084013590509250925092565b600080600080600080600060e0888a03121561300557600080fd5b61300e88612ed6565b965061301c60208901612ed6565b9550604088013594506060880135935061303860808901612f4f565b925060a0880135915060c0880135905092959891949750929550565b60008060008060008060c0878903121561306d57600080fd5b61307687612ed6565b955061308460208801612ed6565b94506040870135935061309960608801612f4f565b92506080870135915060a087013590509295509295509295565b6000806000604084860312156130c857600080fd5b6130d184612ed6565b9250602084013567ffffffffffffffff8111156130ed57600080fd5b6130f986828701612ef2565b9497909650939450505050565b60008060008060006060868803121561311e57600080fd5b61312786612ed6565b9450602086013567ffffffffffffffff8082111561314457600080fd5b61315089838a01612ef2565b9096509450604088013591508082111561316957600080fd5b5061317688828901612ef2565b969995985093965092949392505050565b6000806040838503121561319a57600080fd5b6131a383612ed6565b9150602083013561ffff811681146131ba57600080fd5b809150509250929050565b600080604083850312156131d857600080fd5b6131e183612ed6565b946020939093013593505050565b6000806040838503121561320257600080fd5b61320b83612ed6565b9150612fa560208401612f37565b60008060006060848603121561322e57600080fd5b61323784612ed6565b925061324560208501612f37565b915061325360408501612f37565b90509250925092565b6000806020838503121561326f57600080fd5b823567ffffffffffffffff81111561328657600080fd5b61329285828601612ef2565b90969095509350505050565b600080600080604085870312156132b457600080fd5b843567ffffffffffffffff808211156132cc57600080fd5b6132d888838901612ef2565b909650945060208701359150808211156132f157600080fd5b506132fe87828801612ef2565b95989497509550505050565b60006020828403121561331c57600080fd5b61071c82612f37565b6020808252825182820181905260009190848201906040850190845b8181101561335d57835183529284019291840191600101613341565b50909695505050505050565b600060208083528351808285015260005b818110156133965785810183015185820160400152820161337a565b818111156133a8576000604083870101525b50601f01601f1916929092016040019392505050565b60006001600160d01b038083168185168083038211156133e0576133e06135a8565b01949350505050565b60006001600160e01b038083168185168083038211156133e0576133e06135a8565b600062ffffff8083168185168083038211156133e0576133e06135a8565b6000821982111561343c5761343c6135a8565b500190565b600064ffffffffff8083168185168083038211156133e0576133e06135a8565b60006001600160e01b038084168061347b5761347b6135be565b92169190910492915050565b600082613496576134966135be565b500490565b60006001600160e01b03808316818516818304811182151516156134c1576134c16135a8565b02949350505050565b60006001600160e01b03838116908316818110156134ea576134ea6135a8565b039392505050565b600082821015613504576135046135a8565b500390565b600063ffffffff838116908316818110156134ea576134ea6135a8565b600181811c9082168061353a57607f821691505b60208210811415611b4357634e487b7160e01b600052602260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561358d5761358d6135a8565b5060010190565b6000826135a3576135a36135be565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfe5469636b65742f6275726e2d616d6f756e742d657863656564732d746f74616c2d737570706c792d74776162a2646970667358221220db45750c1000f519fe3c159aece3b6f8c265a9af06ab7578e87d9e2f5383ceaf64736f6c63430008060033",
  "devdoc": {
    "author": "PoolTogether Inc Team",
    "kind": "dev",
    "methods": {
      "DOMAIN_SEPARATOR()": {
        "details": "See {IERC20Permit-DOMAIN_SEPARATOR}."
      },
      "allowance(address,address)": {
        "details": "See {IERC20-allowance}."
      },
      "approve(address,uint256)": {
        "details": "See {IERC20-approve}. Requirements: - `spender` cannot be the zero address."
      },
      "balanceOf(address)": {
        "details": "See {IERC20-balanceOf}."
      },
      "constructor": {
        "params": {
          "_controller": "ERC20 ticket controller address (ie: Prize Pool address).",
          "_name": "ERC20 ticket token name.",
          "_symbol": "ERC20 ticket token symbol.",
          "decimals_": "ERC20 ticket token decimals."
        }
      },
      "controllerBurn(address,uint256)": {
        "details": "May be overridden to provide more granular control over burning",
        "params": {
          "_amount": "Amount of tokens to burn",
          "_user": "Address of the holder account to burn tokens from"
        }
      },
      "controllerBurnFrom(address,address,uint256)": {
        "details": "May be overridden to provide more granular control over operator-burning",
        "params": {
          "_amount": "Amount of tokens to burn",
          "_operator": "Address of the operator performing the burn action via the controller contract",
          "_user": "Address of the holder account to burn tokens from"
        }
      },
      "controllerDelegateFor(address,address)": {
        "params": {
          "delegate": "The new delegate",
          "user": "The user for whom to delegate"
        }
      },
      "controllerMint(address,uint256)": {
        "details": "May be overridden to provide more granular control over minting",
        "params": {
          "_amount": "Amount of tokens to mint",
          "_user": "Address of the receiver of the minted tokens"
        }
      },
      "decimals()": {
        "details": "This value should be equal to the decimals of the token used to deposit into the pool.",
        "returns": {
          "_0": "uint8 decimals."
        }
      },
      "decreaseAllowance(address,uint256)": {
        "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`."
      },
      "delegate(address)": {
        "details": "Transfers (including mints) trigger the storage of a TWAB in delegate(s) account, instead of the targetted sender and/or recipient address(s).To reset the delegate, pass the zero address (0x000.000) as `to` parameter.Current delegate address should be different from the new delegate address `to`.",
        "params": {
          "to": "Recipient of delegated TWAB."
        }
      },
      "delegateOf(address)": {
        "details": "Address of the delegate will be the zero address if `user` has not delegated their tickets.",
        "params": {
          "user": "Address of the delegator."
        },
        "returns": {
          "_0": "Address of the delegate."
        }
      },
      "delegateWithSignature(address,address,uint256,uint8,bytes32,bytes32)": {
        "params": {
          "deadline": "The timestamp by which this must be submitted",
          "delegate": "The new delegate",
          "r": "The r portion of the ECDSA sig",
          "s": "The s portion of the ECDSA sig",
          "user": "The user who is delegating",
          "v": "The v portion of the ECDSA sig"
        }
      },
      "getAccountDetails(address)": {
        "params": {
          "user": "The user for whom to fetch the TWAB context."
        },
        "returns": {
          "_0": "The TWAB context, which includes { balance, nextTwabIndex, cardinality }"
        }
      },
      "getAverageBalanceBetween(address,uint64,uint64)": {
        "params": {
          "endTime": "The end time of the time frame.",
          "startTime": "The start time of the time frame.",
          "user": "The user whose balance is checked."
        },
        "returns": {
          "_0": "The average balance that the user held during the time frame."
        }
      },
      "getAverageBalancesBetween(address,uint64[],uint64[])": {
        "params": {
          "endTimes": "The end time of the time frame.",
          "startTimes": "The start time of the time frame.",
          "user": "The user whose balance is checked."
        },
        "returns": {
          "_0": "The average balance that the user held during the time frame."
        }
      },
      "getAverageTotalSuppliesBetween(uint64[],uint64[])": {
        "params": {
          "endTimes": "Array of end times.",
          "startTimes": "Array of start times."
        },
        "returns": {
          "_0": "The average total supplies held during the time frame."
        }
      },
      "getBalanceAt(address,uint64)": {
        "params": {
          "timestamp": "Timestamp at which we want to retrieve the TWAB balance.",
          "user": "Address of the user whose TWAB is being fetched."
        },
        "returns": {
          "_0": "The TWAB balance at the given timestamp."
        }
      },
      "getBalancesAt(address,uint64[])": {
        "params": {
          "timestamps": "Timestamps range at which we want to retrieve the TWAB balances.",
          "user": "Address of the user whose TWABs are being fetched."
        },
        "returns": {
          "_0": "`user` TWAB balances."
        }
      },
      "getTotalSuppliesAt(uint64[])": {
        "params": {
          "timestamps": "Timestamps range at which we want to retrieve the total supply TWAB balance."
        },
        "returns": {
          "_0": "Total supply TWAB balances."
        }
      },
      "getTotalSupplyAt(uint64)": {
        "params": {
          "timestamp": "Timestamp at which we want to retrieve the total supply TWAB balance."
        },
        "returns": {
          "_0": "The total supply TWAB balance at the given timestamp."
        }
      },
      "getTwab(address,uint16)": {
        "params": {
          "index": "The index of the TWAB to fetch.",
          "user": "The user for whom to fetch the TWAB."
        },
        "returns": {
          "_0": "The TWAB, which includes the twab amount and the timestamp."
        }
      },
      "increaseAllowance(address,uint256)": {
        "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address."
      },
      "name()": {
        "details": "Returns the name of the token."
      },
      "nonces(address)": {
        "details": "See {IERC20Permit-nonces}."
      },
      "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": {
        "details": "See {IERC20Permit-permit}."
      },
      "symbol()": {
        "details": "Returns the symbol of the token, usually a shorter version of the name."
      },
      "totalSupply()": {
        "details": "See {IERC20-totalSupply}."
      },
      "transfer(address,uint256)": {
        "details": "See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`."
      },
      "transferFrom(address,address,uint256)": {
        "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`."
      }
    },
    "title": "PoolTogether V4 Ticket",
    "version": 1
  },
  "userdoc": {
    "events": {
      "Delegated(address,address)": {
        "notice": "Emitted when TWAB balance has been delegated to another user."
      },
      "NewTotalSupplyTwab((uint224,uint32))": {
        "notice": "Emitted when a new total supply TWAB has been recorded."
      },
      "NewUserTwab(address,(uint224,uint32))": {
        "notice": "Emitted when a new TWAB has been recorded."
      },
      "TicketInitialized(string,string,uint8,address)": {
        "notice": "Emitted when ticket is initialized."
      }
    },
    "kind": "user",
    "methods": {
      "constructor": {
        "notice": "Constructs Ticket with passed parameters."
      },
      "controller()": {
        "notice": "Interface to the contract responsible for controlling mint/burn"
      },
      "controllerBurn(address,uint256)": {
        "notice": "Allows the controller to burn tokens from a user account"
      },
      "controllerBurnFrom(address,address,uint256)": {
        "notice": "Allows an operator via the controller to burn tokens on behalf of a user account"
      },
      "controllerDelegateFor(address,address)": {
        "notice": "Allows the controller to delegate on a users behalf."
      },
      "controllerMint(address,uint256)": {
        "notice": "Allows the controller to mint tokens for a user account"
      },
      "decimals()": {
        "notice": "Returns the ERC20 controlled token decimals."
      },
      "delegate(address)": {
        "notice": "Delegate time-weighted average balances to an alternative address."
      },
      "delegateOf(address)": {
        "notice": "Retrieves the address of the delegate to whom `user` has delegated their tickets."
      },
      "delegateWithSignature(address,address,uint256,uint8,bytes32,bytes32)": {
        "notice": "Allows a user to delegate via signature"
      },
      "getAccountDetails(address)": {
        "notice": "Gets a users twab context.  This is a struct with their balance, next twab index, and cardinality."
      },
      "getAverageBalanceBetween(address,uint64,uint64)": {
        "notice": "Retrieves the average balance held by a user for a given time frame."
      },
      "getAverageBalancesBetween(address,uint64[],uint64[])": {
        "notice": "Retrieves the average balances held by a user for a given time frame."
      },
      "getAverageTotalSuppliesBetween(uint64[],uint64[])": {
        "notice": "Retrieves the average total supply balance for a set of given time frames."
      },
      "getBalanceAt(address,uint64)": {
        "notice": "Retrieves `user` TWAB balance."
      },
      "getBalancesAt(address,uint64[])": {
        "notice": "Retrieves `user` TWAB balances."
      },
      "getTotalSuppliesAt(uint64[])": {
        "notice": "Retrieves the total supply TWAB balance between the given timestamps range."
      },
      "getTotalSupplyAt(uint64)": {
        "notice": "Retrieves the total supply TWAB balance at the given timestamp."
      },
      "getTwab(address,uint16)": {
        "notice": "Gets the TWAB at a specific index for a user."
      }
    },
    "notice": "The Ticket extends the standard ERC20 and ControlledToken interfaces with time-weighted average balance functionality. The average balance held by a user between two timestamps can be calculated, as well as the historic balance.  The historic total supply is available as well as the average total supply between two timestamps. A user may \"delegate\" their balance; increasing another user's historic balance while retaining their tokens.",
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 55,
        "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
        "label": "_balances",
        "offset": 0,
        "slot": "0",
        "type": "t_mapping(t_address,t_uint256)"
      },
      {
        "astId": 61,
        "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
        "label": "_allowances",
        "offset": 0,
        "slot": "1",
        "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))"
      },
      {
        "astId": 63,
        "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
        "label": "_totalSupply",
        "offset": 0,
        "slot": "2",
        "type": "t_uint256"
      },
      {
        "astId": 65,
        "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
        "label": "_name",
        "offset": 0,
        "slot": "3",
        "type": "t_string_storage"
      },
      {
        "astId": 67,
        "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
        "label": "_symbol",
        "offset": 0,
        "slot": "4",
        "type": "t_string_storage"
      },
      {
        "astId": 711,
        "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
        "label": "_nonces",
        "offset": 0,
        "slot": "5",
        "type": "t_mapping(t_address,t_struct(Counter)1576_storage)"
      },
      {
        "astId": 8782,
        "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
        "label": "userTwabs",
        "offset": 0,
        "slot": "6",
        "type": "t_mapping(t_address,t_struct(Account)11613_storage)"
      },
      {
        "astId": 8786,
        "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
        "label": "totalSupplyTwab",
        "offset": 0,
        "slot": "7",
        "type": "t_struct(Account)11613_storage"
      },
      {
        "astId": 8791,
        "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
        "label": "delegates",
        "offset": 0,
        "slot": "16777223",
        "type": "t_mapping(t_address,t_address)"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_array(t_struct(Observation)11185_storage)16777215_storage": {
        "base": "t_struct(Observation)11185_storage",
        "encoding": "inplace",
        "label": "struct ObservationLib.Observation[16777215]",
        "numberOfBytes": "536870880"
      },
      "t_mapping(t_address,t_address)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => address)",
        "numberOfBytes": "32",
        "value": "t_address"
      },
      "t_mapping(t_address,t_mapping(t_address,t_uint256))": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => mapping(address => uint256))",
        "numberOfBytes": "32",
        "value": "t_mapping(t_address,t_uint256)"
      },
      "t_mapping(t_address,t_struct(Account)11613_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct TwabLib.Account)",
        "numberOfBytes": "32",
        "value": "t_struct(Account)11613_storage"
      },
      "t_mapping(t_address,t_struct(Counter)1576_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct Counters.Counter)",
        "numberOfBytes": "32",
        "value": "t_struct(Counter)1576_storage"
      },
      "t_mapping(t_address,t_uint256)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => uint256)",
        "numberOfBytes": "32",
        "value": "t_uint256"
      },
      "t_string_storage": {
        "encoding": "bytes",
        "label": "string",
        "numberOfBytes": "32"
      },
      "t_struct(Account)11613_storage": {
        "encoding": "inplace",
        "label": "struct TwabLib.Account",
        "members": [
          {
            "astId": 11607,
            "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
            "label": "details",
            "offset": 0,
            "slot": "0",
            "type": "t_struct(AccountDetails)11604_storage"
          },
          {
            "astId": 11612,
            "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
            "label": "twabs",
            "offset": 0,
            "slot": "1",
            "type": "t_array(t_struct(Observation)11185_storage)16777215_storage"
          }
        ],
        "numberOfBytes": "536870912"
      },
      "t_struct(AccountDetails)11604_storage": {
        "encoding": "inplace",
        "label": "struct TwabLib.AccountDetails",
        "members": [
          {
            "astId": 11599,
            "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
            "label": "balance",
            "offset": 0,
            "slot": "0",
            "type": "t_uint208"
          },
          {
            "astId": 11601,
            "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
            "label": "nextTwabIndex",
            "offset": 26,
            "slot": "0",
            "type": "t_uint24"
          },
          {
            "astId": 11603,
            "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
            "label": "cardinality",
            "offset": 29,
            "slot": "0",
            "type": "t_uint24"
          }
        ],
        "numberOfBytes": "32"
      },
      "t_struct(Counter)1576_storage": {
        "encoding": "inplace",
        "label": "struct Counters.Counter",
        "members": [
          {
            "astId": 1575,
            "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
            "label": "_value",
            "offset": 0,
            "slot": "0",
            "type": "t_uint256"
          }
        ],
        "numberOfBytes": "32"
      },
      "t_struct(Observation)11185_storage": {
        "encoding": "inplace",
        "label": "struct ObservationLib.Observation",
        "members": [
          {
            "astId": 11182,
            "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
            "label": "amount",
            "offset": 0,
            "slot": "0",
            "type": "t_uint224"
          },
          {
            "astId": 11184,
            "contract": "@pooltogether/v4-core/contracts/Ticket.sol:Ticket",
            "label": "timestamp",
            "offset": 28,
            "slot": "0",
            "type": "t_uint32"
          }
        ],
        "numberOfBytes": "32"
      },
      "t_uint208": {
        "encoding": "inplace",
        "label": "uint208",
        "numberOfBytes": "26"
      },
      "t_uint224": {
        "encoding": "inplace",
        "label": "uint224",
        "numberOfBytes": "28"
      },
      "t_uint24": {
        "encoding": "inplace",
        "label": "uint24",
        "numberOfBytes": "3"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      },
      "t_uint32": {
        "encoding": "inplace",
        "label": "uint32",
        "numberOfBytes": "4"
      }
    }
  }
}