{
  "address": "0x1ADBde469581Bfd0454fC61c7E74Ec2Bf7330024",
  "abi": [
    {
      "inputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "cashPrior",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "interestAccumulated",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "borrowIndex",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "totalBorrows",
          "type": "uint256"
        }
      ],
      "name": "AccrueInterest",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "indexed": true,
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "Approval",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "borrower",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "borrowAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "accountBorrows",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "totalBorrows",
          "type": "uint256"
        }
      ],
      "name": "Borrow",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "error",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "info",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "detail",
          "type": "uint256"
        }
      ],
      "name": "Failure",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "internalType": "address",
          "name": "receiver",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "totalFee",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "reservesFee",
          "type": "uint256"
        }
      ],
      "name": "Flashloan",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "liquidator",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "borrower",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "repayAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "jTokenCollateral",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "seizeTokens",
          "type": "uint256"
        }
      ],
      "name": "LiquidateBorrow",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "minter",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "mintAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "mintTokens",
          "type": "uint256"
        }
      ],
      "name": "Mint",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "oldAdmin",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "newAdmin",
          "type": "address"
        }
      ],
      "name": "NewAdmin",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "token",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "newCap",
          "type": "uint256"
        }
      ],
      "name": "NewCollateralCap",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "contract JoetrollerInterface",
          "name": "oldJoetroller",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "contract JoetrollerInterface",
          "name": "newJoetroller",
          "type": "address"
        }
      ],
      "name": "NewJoetroller",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "contract InterestRateModel",
          "name": "oldInterestRateModel",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "contract InterestRateModel",
          "name": "newInterestRateModel",
          "type": "address"
        }
      ],
      "name": "NewMarketInterestRateModel",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "oldPendingAdmin",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "newPendingAdmin",
          "type": "address"
        }
      ],
      "name": "NewPendingAdmin",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "oldProtocolSeizeShareMantissa",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "newProtocolSeizeShareMantissa",
          "type": "uint256"
        }
      ],
      "name": "NewProtocolSeizeShare",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "oldReserveFactorMantissa",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "newReserveFactorMantissa",
          "type": "uint256"
        }
      ],
      "name": "NewReserveFactor",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "redeemer",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "redeemAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "redeemTokens",
          "type": "uint256"
        }
      ],
      "name": "Redeem",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "payer",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "borrower",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "repayAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "accountBorrows",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "totalBorrows",
          "type": "uint256"
        }
      ],
      "name": "RepayBorrow",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "benefactor",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "addAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "newTotalReserves",
          "type": "uint256"
        }
      ],
      "name": "ReservesAdded",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "admin",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "reduceAmount",
          "type": "uint256"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "newTotalReserves",
          "type": "uint256"
        }
      ],
      "name": "ReservesReduced",
      "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": "amount",
          "type": "uint256"
        }
      ],
      "name": "Transfer",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "address",
          "name": "account",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "newCollateralTokens",
          "type": "uint256"
        }
      ],
      "name": "UserCollateralChanged",
      "type": "event"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "_acceptAdmin",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "addAmount",
          "type": "uint256"
        }
      ],
      "name": "_addReserves",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        }
      ],
      "name": "_becomeImplementation",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "reduceAmount",
          "type": "uint256"
        }
      ],
      "name": "_reduceReserves",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "_resignImplementation",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "newCollateralCap",
          "type": "uint256"
        }
      ],
      "name": "_setCollateralCap",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "contract InterestRateModel",
          "name": "newInterestRateModel",
          "type": "address"
        }
      ],
      "name": "_setInterestRateModel",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "contract JoetrollerInterface",
          "name": "newJoetroller",
          "type": "address"
        }
      ],
      "name": "_setJoetroller",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address payable",
          "name": "newPendingAdmin",
          "type": "address"
        }
      ],
      "name": "_setPendingAdmin",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "newProtocolSeizeShareMantissa",
          "type": "uint256"
        }
      ],
      "name": "_setProtocolSeizeShare",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "newReserveFactorMantissa",
          "type": "uint256"
        }
      ],
      "name": "_setReserveFactor",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "name": "accountCollateralTokens",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "accrualBlockTimestamp",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "accrueInterest",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "admin",
      "outputs": [
        {
          "internalType": "address payable",
          "name": "",
          "type": "address"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        }
      ],
      "name": "allowance",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "spender",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "approve",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        }
      ],
      "name": "balanceOf",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "owner",
          "type": "address"
        }
      ],
      "name": "balanceOfUnderlying",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "borrowAmount",
          "type": "uint256"
        }
      ],
      "name": "borrow",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "borrowBalanceCurrent",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "borrowBalanceStored",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "borrowIndex",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "borrowRatePerSecond",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "collateralCap",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "decimals",
      "outputs": [
        {
          "internalType": "uint8",
          "name": "",
          "type": "uint8"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "change",
          "type": "uint256"
        },
        {
          "internalType": "bool",
          "name": "repay",
          "type": "bool"
        }
      ],
      "name": "estimateBorrowRatePerSecondAfterChange",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "change",
          "type": "uint256"
        },
        {
          "internalType": "bool",
          "name": "repay",
          "type": "bool"
        }
      ],
      "name": "estimateSupplyRatePerSecondAfterChange",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "exchangeRateCurrent",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "exchangeRateStored",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "flashFee",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "flashFeeBips",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "contract ERC3156FlashBorrowerInterface",
          "name": "receiver",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "initiator",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        },
        {
          "internalType": "bytes",
          "name": "data",
          "type": "bytes"
        }
      ],
      "name": "flashLoan",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "getAccountSnapshot",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        },
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "getCash",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "gulp",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "implementation",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "underlying_",
          "type": "address"
        },
        {
          "internalType": "contract JoetrollerInterface",
          "name": "joetroller_",
          "type": "address"
        },
        {
          "internalType": "contract InterestRateModel",
          "name": "interestRateModel_",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "initialExchangeRateMantissa_",
          "type": "uint256"
        },
        {
          "internalType": "string",
          "name": "name_",
          "type": "string"
        },
        {
          "internalType": "string",
          "name": "symbol_",
          "type": "string"
        },
        {
          "internalType": "uint8",
          "name": "decimals_",
          "type": "uint8"
        }
      ],
      "name": "initialize",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "contract JoetrollerInterface",
          "name": "joetroller_",
          "type": "address"
        },
        {
          "internalType": "contract InterestRateModel",
          "name": "interestRateModel_",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "initialExchangeRateMantissa_",
          "type": "uint256"
        },
        {
          "internalType": "string",
          "name": "name_",
          "type": "string"
        },
        {
          "internalType": "string",
          "name": "symbol_",
          "type": "string"
        },
        {
          "internalType": "uint8",
          "name": "decimals_",
          "type": "uint8"
        }
      ],
      "name": "initialize",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "interestRateModel",
      "outputs": [
        {
          "internalType": "contract InterestRateModel",
          "name": "",
          "type": "address"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "internalCash",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "name": "isCollateralTokenInit",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "isJToken",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "joetroller",
      "outputs": [
        {
          "internalType": "contract JoetrollerInterface",
          "name": "",
          "type": "address"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "borrower",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "repayAmount",
          "type": "uint256"
        },
        {
          "internalType": "contract JTokenInterface",
          "name": "jTokenCollateral",
          "type": "address"
        }
      ],
      "name": "liquidateBorrow",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "maxFlashLoan",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "mintAmount",
          "type": "uint256"
        }
      ],
      "name": "mint",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "name",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "pendingAdmin",
      "outputs": [
        {
          "internalType": "address payable",
          "name": "",
          "type": "address"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "protocolSeizeShareMantissa",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "redeemTokens",
          "type": "uint256"
        }
      ],
      "name": "redeem",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "redeemAmount",
          "type": "uint256"
        }
      ],
      "name": "redeemUnderlying",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "registerCollateral",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "uint256",
          "name": "repayAmount",
          "type": "uint256"
        }
      ],
      "name": "repayBorrow",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "borrower",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "repayAmount",
          "type": "uint256"
        }
      ],
      "name": "repayBorrowBehalf",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "reserveFactorMantissa",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "liquidator",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "borrower",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "seizeTokens",
          "type": "uint256"
        }
      ],
      "name": "seize",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "supplyRatePerSecond",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "symbol",
      "outputs": [
        {
          "internalType": "string",
          "name": "",
          "type": "string"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "totalBorrows",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "totalBorrowsCurrent",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "totalCollateralTokens",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "totalReserves",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "totalSupply",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "dst",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "transfer",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "src",
          "type": "address"
        },
        {
          "internalType": "address",
          "name": "dst",
          "type": "address"
        },
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      "name": "transferFrom",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "underlying",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "account",
          "type": "address"
        }
      ],
      "name": "unregisterCollateral",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0x4e660032649fcd776b6c6ac65f47b1458826aec499de9ad1fd0d1738ead2626b",
  "receipt": {
    "to": null,
    "from": "0x5D3e4C0FE11e0aE4c32F0FF74B4544C49538AC61",
    "contractAddress": "0x1ADBde469581Bfd0454fC61c7E74Ec2Bf7330024",
    "transactionIndex": 0,
    "gasUsed": "5178450",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x5b0b15b1f2df6b500e37b550b478a12ea2844550fc5ec0d76031ca949340d989",
    "transactionHash": "0x4e660032649fcd776b6c6ac65f47b1458826aec499de9ad1fd0d1738ead2626b",
    "logs": [],
    "blockNumber": 7821549,
    "cumulativeGasUsed": "5178450",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "solcInputHash": "46ea8ab28a8b9ffe2635abe69f1fb3a7",
  "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"cashPrior\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"interestAccumulated\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"borrowIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"}],\"name\":\"AccrueInterest\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"accountBorrows\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"}],\"name\":\"Borrow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reservesFee\",\"type\":\"uint256\"}],\"name\":\"Flashloan\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"jTokenCollateral\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"LiquidateBorrow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"NewAdmin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCap\",\"type\":\"uint256\"}],\"name\":\"NewCollateralCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract JoetrollerInterface\",\"name\":\"oldJoetroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract JoetrollerInterface\",\"name\":\"newJoetroller\",\"type\":\"address\"}],\"name\":\"NewJoetroller\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract InterestRateModel\",\"name\":\"oldInterestRateModel\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract InterestRateModel\",\"name\":\"newInterestRateModel\",\"type\":\"address\"}],\"name\":\"NewMarketInterestRateModel\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPendingAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPendingAdmin\",\"type\":\"address\"}],\"name\":\"NewPendingAdmin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldProtocolSeizeShareMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newProtocolSeizeShareMantissa\",\"type\":\"uint256\"}],\"name\":\"NewProtocolSeizeShare\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldReserveFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newReserveFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewReserveFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"Redeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"accountBorrows\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"}],\"name\":\"RepayBorrow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"benefactor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"addAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTotalReserves\",\"type\":\"uint256\"}],\"name\":\"ReservesAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reduceAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTotalReserves\",\"type\":\"uint256\"}],\"name\":\"ReservesReduced\",\"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\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralTokens\",\"type\":\"uint256\"}],\"name\":\"UserCollateralChanged\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[],\"name\":\"_acceptAdmin\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"addAmount\",\"type\":\"uint256\"}],\"name\":\"_addReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"_becomeImplementation\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reduceAmount\",\"type\":\"uint256\"}],\"name\":\"_reduceReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"_resignImplementation\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCollateralCap\",\"type\":\"uint256\"}],\"name\":\"_setCollateralCap\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract InterestRateModel\",\"name\":\"newInterestRateModel\",\"type\":\"address\"}],\"name\":\"_setInterestRateModel\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract JoetrollerInterface\",\"name\":\"newJoetroller\",\"type\":\"address\"}],\"name\":\"_setJoetroller\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"newPendingAdmin\",\"type\":\"address\"}],\"name\":\"_setPendingAdmin\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newProtocolSeizeShareMantissa\",\"type\":\"uint256\"}],\"name\":\"_setProtocolSeizeShare\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newReserveFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setReserveFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"accountCollateralTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"accrualBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"accrueInterest\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOfUnderlying\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"borrowBalanceCurrent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"borrowBalanceStored\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"borrowRatePerSecond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"collateralCap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"change\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"repay\",\"type\":\"bool\"}],\"name\":\"estimateBorrowRatePerSecondAfterChange\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"change\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"repay\",\"type\":\"bool\"}],\"name\":\"estimateSupplyRatePerSecondAfterChange\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"exchangeRateCurrent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"exchangeRateStored\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"flashFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"flashFeeBips\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract ERC3156FlashBorrowerInterface\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"initiator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"flashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountSnapshot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCash\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"gulp\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"underlying_\",\"type\":\"address\"},{\"internalType\":\"contract JoetrollerInterface\",\"name\":\"joetroller_\",\"type\":\"address\"},{\"internalType\":\"contract InterestRateModel\",\"name\":\"interestRateModel_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"initialExchangeRateMantissa_\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract JoetrollerInterface\",\"name\":\"joetroller_\",\"type\":\"address\"},{\"internalType\":\"contract InterestRateModel\",\"name\":\"interestRateModel_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"initialExchangeRateMantissa_\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"interestRateModel\",\"outputs\":[{\"internalType\":\"contract InterestRateModel\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"internalCash\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isCollateralTokenInit\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isJToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"joetroller\",\"outputs\":[{\"internalType\":\"contract JoetrollerInterface\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"contract JTokenInterface\",\"name\":\"jTokenCollateral\",\"type\":\"address\"}],\"name\":\"liquidateBorrow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxFlashLoan\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"protocolSeizeShareMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"}],\"name\":\"redeemUnderlying\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"registerCollateral\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"reserveFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seize\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"supplyRatePerSecond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalBorrows\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"totalBorrowsCurrent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalCollateralTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"underlying\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"unregisterCollateral\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Cream\",\"methods\":{\"_acceptAdmin()\":{\"details\":\"Admin function for pending admin to accept role and update admin\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_addReserves(uint256)\":{\"params\":{\"addAmount\":\"The amount fo underlying token to add as reserves\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_becomeImplementation(bytes)\":{\"params\":{\"data\":\"The encoded bytes data for any initialization\"}},\"_reduceReserves(uint256)\":{\"params\":{\"reduceAmount\":\"Amount of reduction to reserves\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_setCollateralCap(uint256)\":{\"params\":{\"newCollateralCap\":\"New collateral cap for this market. A value of 0 corresponds to no cap.\"}},\"_setInterestRateModel(address)\":{\"details\":\"Admin function to accrue interest and update the interest rate model\",\"params\":{\"newInterestRateModel\":\"the new interest rate model to use\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_setJoetroller(address)\":{\"details\":\"Admin function to set a new joetroller\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_setPendingAdmin(address)\":{\"details\":\"Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\",\"params\":{\"newPendingAdmin\":\"New pending admin.\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_setProtocolSeizeShare(uint256)\":{\"details\":\"Admin function to accrue interest and set a new collateral seize share\",\"return\":\"uint256 0=success, otherwise a failure (see ErrorReport.sol for details)\"},\"_setReserveFactor(uint256)\":{\"details\":\"Admin function to accrue interest and set a new reserve factor\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"accrueInterest()\":{\"details\":\"This calculates interest accrued from the last checkpointed timestamp  up to the current timestamp and writes new checkpoint to storage.\"},\"allowance(address,address)\":{\"params\":{\"owner\":\"The address of the account which owns the tokens to be spent\",\"spender\":\"The address of the account which may transfer tokens\"},\"return\":\"The number of tokens allowed to be spent (-1 means infinite)\"},\"approve(address,uint256)\":{\"details\":\"This will overwrite the approval amount for `spender` and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\",\"params\":{\"amount\":\"The number of tokens that are approved (-1 means infinite)\",\"spender\":\"The address of the account which may transfer tokens\"},\"return\":\"Whether or not the approval succeeded\"},\"balanceOf(address)\":{\"params\":{\"owner\":\"The address of the account to query\"},\"return\":\"The number of tokens owned by `owner`\"},\"balanceOfUnderlying(address)\":{\"details\":\"This also accrues interest in a transaction\",\"params\":{\"owner\":\"The address of the account to query\"},\"return\":\"The amount of underlying owned by `owner`\"},\"borrow(uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset to borrow\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"borrowBalanceCurrent(address)\":{\"params\":{\"account\":\"The address whose balance should be calculated after updating borrowIndex\"},\"return\":\"The calculated balance\"},\"borrowBalanceStored(address)\":{\"params\":{\"account\":\"The address whose balance should be calculated\"},\"return\":\"The calculated balance\"},\"borrowRatePerSecond()\":{\"return\":\"The borrow interest rate per sec, scaled by 1e18\"},\"estimateBorrowRatePerSecondAfterChange(uint256,bool)\":{\"return\":\"The borrow interest rate per sec, scaled by 1e18\"},\"estimateSupplyRatePerSecondAfterChange(uint256,bool)\":{\"return\":\"The supply interest rate per sec, scaled by 1e18\"},\"exchangeRateCurrent()\":{\"return\":\"Calculated exchange rate scaled by 1e18\"},\"exchangeRateStored()\":{\"details\":\"This function does not accrue interest before calculating the exchange rate\",\"return\":\"Calculated exchange rate scaled by 1e18\"},\"flashFee(uint256)\":{\"params\":{\"amount\":\"amount of token to borrow\"}},\"flashLoan(address,address,uint256,bytes)\":{\"params\":{\"amount\":\"The amount of the funds to be loaned\",\"data\":\"The other data\",\"initiator\":\"flash loan initiator\",\"receiver\":\"The receiver address for the funds\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"getAccountSnapshot(address)\":{\"details\":\"This is used by joetroller to more efficiently perform liquidity checks.\",\"params\":{\"account\":\"Address of the account to snapshot\"},\"return\":\"(possible error, token balance, borrow balance, exchange rate mantissa)\"},\"getCash()\":{\"return\":\"The quantity of underlying asset owned by this contract\"},\"initialize(address,address,address,uint256,string,string,uint8)\":{\"params\":{\"decimals_\":\"ERC-20 decimal precision of this token\",\"initialExchangeRateMantissa_\":\"The initial exchange rate, scaled by 1e18\",\"interestRateModel_\":\"The address of the interest rate model\",\"joetroller_\":\"The address of the Joetroller\",\"name_\":\"ERC-20 name of this token\",\"symbol_\":\"ERC-20 symbol of this token\",\"underlying_\":\"The address of the underlying asset\"}},\"initialize(address,address,uint256,string,string,uint8)\":{\"params\":{\"decimals_\":\"EIP-20 decimal precision of this token\",\"initialExchangeRateMantissa_\":\"The initial exchange rate, scaled by 1e18\",\"interestRateModel_\":\"The address of the interest rate model\",\"joetroller_\":\"The address of the Joetroller\",\"name_\":\"EIP-20 name of this token\",\"symbol_\":\"EIP-20 symbol of this token\"}},\"liquidateBorrow(address,uint256,address)\":{\"params\":{\"borrower\":\"The borrower of this jToken to be liquidated\",\"jTokenCollateral\":\"The market in which to seize collateral from the borrower\",\"repayAmount\":\"The amount of the underlying borrowed asset to repay\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"mint(uint256)\":{\"details\":\"Accrues interest whether or not the operation succeeds, unless reverted\",\"params\":{\"mintAmount\":\"The amount of the underlying asset to supply\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"redeem(uint256)\":{\"details\":\"Accrues interest whether or not the operation succeeds, unless reverted\",\"params\":{\"redeemTokens\":\"The number of jTokens to redeem into underlying\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"redeemUnderlying(uint256)\":{\"details\":\"Accrues interest whether or not the operation succeeds, unless reverted\",\"params\":{\"redeemAmount\":\"The amount of underlying to redeem\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"registerCollateral(address)\":{\"details\":\"This function could only be called by joetroller.\",\"params\":{\"account\":\"The account to register\"},\"return\":\"The actual registered amount of collateral\"},\"repayBorrow(uint256)\":{\"params\":{\"repayAmount\":\"The amount to repay\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"repayBorrowBehalf(address,uint256)\":{\"params\":{\"borrower\":\"the account with the debt being payed off\",\"repayAmount\":\"The amount to repay\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"seize(address,address,uint256)\":{\"details\":\"Will fail unless called by another jToken during the process of liquidation. Its absolutely critical to use msg.sender as the borrowed jToken and not a parameter.\",\"params\":{\"borrower\":\"The account having collateral seized\",\"liquidator\":\"The account receiving seized collateral\",\"seizeTokens\":\"The number of jTokens to seize\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"supplyRatePerSecond()\":{\"return\":\"The supply interest rate per sec, scaled by 1e18\"},\"totalBorrowsCurrent()\":{\"return\":\"The total borrows with interest\"},\"transfer(address,uint256)\":{\"params\":{\"amount\":\"The number of tokens to transfer\",\"dst\":\"The address of the destination account\"},\"return\":\"Whether or not the transfer succeeded\"},\"transferFrom(address,address,uint256)\":{\"params\":{\"amount\":\"The number of tokens to transfer\",\"dst\":\"The address of the destination account\",\"src\":\"The address of the source account\"},\"return\":\"Whether or not the transfer succeeded\"},\"unregisterCollateral(address)\":{\"details\":\"This function could only be called by joetroller.\",\"params\":{\"account\":\"The account to unregister\"}}},\"title\":\"Cream's JCollateralCapErc20Delegate Contract\"},\"userdoc\":{\"methods\":{\"_acceptAdmin()\":{\"notice\":\"Accepts transfer of admin rights. msg.sender must be pendingAdmin\"},\"_addReserves(uint256)\":{\"notice\":\"The sender adds to reserves.\"},\"_becomeImplementation(bytes)\":{\"notice\":\"Called by the delegator on a delegate to initialize it for duty\"},\"_reduceReserves(uint256)\":{\"notice\":\"Accrues interest and reduces reserves by transferring to admin\"},\"_resignImplementation()\":{\"notice\":\"Called by the delegator on a delegate to forfeit its responsibility\"},\"_setCollateralCap(uint256)\":{\"notice\":\"Set the given collateral cap for the market.\"},\"_setInterestRateModel(address)\":{\"notice\":\"accrues interest and updates the interest rate model using _setInterestRateModelFresh\"},\"_setJoetroller(address)\":{\"notice\":\"Sets a new joetroller for the market\"},\"_setPendingAdmin(address)\":{\"notice\":\"Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\"},\"_setProtocolSeizeShare(uint256)\":{\"notice\":\"Accrues interest and sets a new collateral seize share for the protocol using _setProtocolSeizeShareFresh\"},\"_setReserveFactor(uint256)\":{\"notice\":\"Accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\"},\"accrueInterest()\":{\"notice\":\"Applies accrued interest to total borrows and reserves\"},\"allowance(address,address)\":{\"notice\":\"Get the current allowance from `owner` for `spender`\"},\"approve(address,uint256)\":{\"notice\":\"Approve `spender` to transfer up to `amount` from `src`\"},\"balanceOf(address)\":{\"notice\":\"Get the token balance of the `owner`\"},\"balanceOfUnderlying(address)\":{\"notice\":\"Get the underlying balance of the `owner`\"},\"borrow(uint256)\":{\"notice\":\"Sender borrows assets from the protocol to their own address\"},\"borrowBalanceCurrent(address)\":{\"notice\":\"Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\"},\"borrowBalanceStored(address)\":{\"notice\":\"Return the borrow balance of account based on stored data\"},\"borrowRatePerSecond()\":{\"notice\":\"Returns the current per-sec borrow interest rate for this jToken\"},\"constructor\":\"Construct an empty delegate\",\"estimateBorrowRatePerSecondAfterChange(uint256,bool)\":{\"notice\":\"Returns the estimated per-sec borrow interest rate for this jToken after some change\"},\"estimateSupplyRatePerSecondAfterChange(uint256,bool)\":{\"notice\":\"Returns the estimated per-sec supply interest rate for this jToken after some change\"},\"exchangeRateCurrent()\":{\"notice\":\"Accrue interest then return the up-to-date exchange rate\"},\"exchangeRateStored()\":{\"notice\":\"Calculates the exchange rate from the underlying to the JToken\"},\"flashFee(uint256)\":{\"notice\":\"Get the flash loan fees\"},\"flashLoan(address,address,uint256,bytes)\":{\"notice\":\"Flash loan funds to a given account.\"},\"getAccountSnapshot(address)\":{\"notice\":\"Get a snapshot of the account's balances, and the cached exchange rate\"},\"getCash()\":{\"notice\":\"Get cash balance of this jToken in the underlying asset\"},\"gulp()\":{\"notice\":\"Absorb excess cash into reserves.\"},\"initialize(address,address,address,uint256,string,string,uint8)\":{\"notice\":\"Initialize the new money market\"},\"initialize(address,address,uint256,string,string,uint8)\":{\"notice\":\"Initialize the money market\"},\"liquidateBorrow(address,uint256,address)\":{\"notice\":\"The sender liquidates the borrowers collateral. The collateral seized is transferred to the liquidator.\"},\"maxFlashLoan()\":{\"notice\":\"Get the max flash loan amount\"},\"mint(uint256)\":{\"notice\":\"Sender supplies assets into the market and receives jTokens in exchange\"},\"redeem(uint256)\":{\"notice\":\"Sender redeems jTokens in exchange for the underlying asset\"},\"redeemUnderlying(uint256)\":{\"notice\":\"Sender redeems jTokens in exchange for a specified amount of underlying asset\"},\"registerCollateral(address)\":{\"notice\":\"Register account collateral tokens if there is space.\"},\"repayBorrow(uint256)\":{\"notice\":\"Sender repays their own borrow\"},\"repayBorrowBehalf(address,uint256)\":{\"notice\":\"Sender repays a borrow belonging to borrower\"},\"seize(address,address,uint256)\":{\"notice\":\"Transfers collateral tokens (this market) to the liquidator.\"},\"supplyRatePerSecond()\":{\"notice\":\"Returns the current per-sec supply interest rate for this jToken\"},\"totalBorrowsCurrent()\":{\"notice\":\"Returns the current total borrows plus accrued interest\"},\"transfer(address,uint256)\":{\"notice\":\"Transfer `amount` tokens from `msg.sender` to `dst`\"},\"transferFrom(address,address,uint256)\":{\"notice\":\"Transfer `amount` tokens from `src` to `dst`\"},\"unregisterCollateral(address)\":{\"notice\":\"Unregister account collateral tokens if the account still has enough collateral.\"}},\"notice\":\"JTokens which wrap an EIP-20 underlying and are delegated to\"}},\"settings\":{\"compilationTarget\":{\"contracts/JCollateralCapErc20Delegate.sol\":\"JCollateralCapErc20Delegate\"},\"evmVersion\":\"istanbul\",\"libraries\":{\"__CACHE_BREAKER__\":\"0x00000000d41867734bbee4c6863d9255b2b06ac1\"},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\n/**\\n * @title Careful Math\\n * @author Compound\\n * @notice Derived from OpenZeppelin's SafeMath library\\n *         https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n    /**\\n     * @dev Possible error codes that we can return\\n     */\\n    enum MathError {\\n        NO_ERROR,\\n        DIVISION_BY_ZERO,\\n        INTEGER_OVERFLOW,\\n        INTEGER_UNDERFLOW\\n    }\\n\\n    /**\\n     * @dev Multiplies two numbers, returns an error on overflow.\\n     */\\n    function mulUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {\\n        if (a == 0) {\\n            return (MathError.NO_ERROR, 0);\\n        }\\n\\n        uint256 c = a * b;\\n\\n        if (c / a != b) {\\n            return (MathError.INTEGER_OVERFLOW, 0);\\n        } else {\\n            return (MathError.NO_ERROR, c);\\n        }\\n    }\\n\\n    /**\\n     * @dev Integer division of two numbers, truncating the quotient.\\n     */\\n    function divUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {\\n        if (b == 0) {\\n            return (MathError.DIVISION_BY_ZERO, 0);\\n        }\\n\\n        return (MathError.NO_ERROR, a / b);\\n    }\\n\\n    /**\\n     * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n     */\\n    function subUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {\\n        if (b <= a) {\\n            return (MathError.NO_ERROR, a - b);\\n        } else {\\n            return (MathError.INTEGER_UNDERFLOW, 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev Adds two numbers, returns an error on overflow.\\n     */\\n    function addUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {\\n        uint256 c = a + b;\\n\\n        if (c >= a) {\\n            return (MathError.NO_ERROR, c);\\n        } else {\\n            return (MathError.INTEGER_OVERFLOW, 0);\\n        }\\n    }\\n\\n    /**\\n     * @dev add a and b and then subtract c\\n     */\\n    function addThenSubUInt(\\n        uint256 a,\\n        uint256 b,\\n        uint256 c\\n    ) internal pure returns (MathError, uint256) {\\n        (MathError err0, uint256 sum) = addUInt(a, b);\\n\\n        if (err0 != MathError.NO_ERROR) {\\n            return (err0, 0);\\n        }\\n\\n        return subUInt(sum, c);\\n    }\\n}\\n\",\"keccak256\":\"0x458de49aa8c70be5b88d92d242caa5f647ee0f74570eda81a9276e969ba94f7f\"},\"contracts/EIP20Interface.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\n/**\\n * @title ERC 20 Token Standard Interface\\n *  https://eips.ethereum.org/EIPS/eip-20\\n */\\ninterface EIP20Interface {\\n    function name() external view returns (string memory);\\n\\n    function symbol() external view returns (string memory);\\n\\n    function decimals() external view returns (uint8);\\n\\n    /**\\n     * @notice Get the total number of tokens in circulation\\n     * @return The supply of tokens\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @notice Gets the balance of the specified address\\n     * @param owner The address from which the balance will be retrieved\\n     * @return The balance\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    /**\\n     * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n     * @param dst The address of the destination account\\n     * @param amount The number of tokens to transfer\\n     * @return Whether or not the transfer succeeded\\n     */\\n    function transfer(address dst, uint256 amount) external returns (bool success);\\n\\n    /**\\n     * @notice Transfer `amount` tokens from `src` to `dst`\\n     * @param src The address of the source account\\n     * @param dst The address of the destination account\\n     * @param amount The number of tokens to transfer\\n     * @return Whether or not the transfer succeeded\\n     */\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 amount\\n    ) external returns (bool success);\\n\\n    /**\\n     * @notice Approve `spender` to transfer up to `amount` from `src`\\n     * @dev This will overwrite the approval amount for `spender`\\n     *  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n     * @param spender The address of the account which may transfer tokens\\n     * @param amount The number of tokens that are approved (-1 means infinite)\\n     * @return Whether or not the approval succeeded\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool success);\\n\\n    /**\\n     * @notice Get the current allowance from `owner` for `spender`\\n     * @param owner The address of the account which owns the tokens to be spent\\n     * @param spender The address of the account which may transfer tokens\\n     * @return The number of tokens allowed to be spent (-1 means infinite)\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n    event Transfer(address indexed from, address indexed to, uint256 amount);\\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0xf0c362ddd4ebdde949af559b3d37b6c2b666773fbdc81ed864493ffa9c381bd9\"},\"contracts/EIP20NonStandardInterface.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\n/**\\n * @title EIP20NonStandardInterface\\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\\n *  See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n */\\ninterface EIP20NonStandardInterface {\\n    /**\\n     * @notice Get the total number of tokens in circulation\\n     * @return The supply of tokens\\n     */\\n    function totalSupply() external view returns (uint256);\\n\\n    /**\\n     * @notice Gets the balance of the specified address\\n     * @param owner The address from which the balance will be retrieved\\n     * @return The balance\\n     */\\n    function balanceOf(address owner) external view returns (uint256 balance);\\n\\n    ///\\n    /// !!!!!!!!!!!!!!\\n    /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\\n    /// !!!!!!!!!!!!!!\\n    ///\\n\\n    /**\\n     * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n     * @param dst The address of the destination account\\n     * @param amount The number of tokens to transfer\\n     */\\n    function transfer(address dst, uint256 amount) external;\\n\\n    ///\\n    /// !!!!!!!!!!!!!!\\n    /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\\n    /// !!!!!!!!!!!!!!\\n    ///\\n\\n    /**\\n     * @notice Transfer `amount` tokens from `src` to `dst`\\n     * @param src The address of the source account\\n     * @param dst The address of the destination account\\n     * @param amount The number of tokens to transfer\\n     */\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 amount\\n    ) external;\\n\\n    /**\\n     * @notice Approve `spender` to transfer up to `amount` from `src`\\n     * @dev This will overwrite the approval amount for `spender`\\n     *  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n     * @param spender The address of the account which may transfer tokens\\n     * @param amount The number of tokens that are approved\\n     * @return Whether or not the approval succeeded\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool success);\\n\\n    /**\\n     * @notice Get the current allowance from `owner` for `spender`\\n     * @param owner The address of the account which owns the tokens to be spent\\n     * @param spender The address of the account which may transfer tokens\\n     * @return The number of tokens allowed to be spent\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256 remaining);\\n\\n    event Transfer(address indexed from, address indexed to, uint256 amount);\\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\\n}\\n\",\"keccak256\":\"0x5046e86e5a524462517a0fc0dda5630b8cc9440f7d918c226cb8b44b1d037367\"},\"contracts/ERC3156FlashBorrowerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\ninterface ERC3156FlashBorrowerInterface {\\n    /**\\n     * @dev Receive a flash loan.\\n     * @param initiator The initiator of the loan.\\n     * @param token The loan currency.\\n     * @param amount The amount of tokens lent.\\n     * @param fee The additional amount of tokens to repay.\\n     * @param data Arbitrary data structure, intended to contain user-defined parameters.\\n     * @return The keccak256 hash of \\\"ERC3156FlashBorrower.onFlashLoan\\\"\\n     */\\n    function onFlashLoan(\\n        address initiator,\\n        address token,\\n        uint256 amount,\\n        uint256 fee,\\n        bytes calldata data\\n    ) external returns (bytes32);\\n}\\n\",\"keccak256\":\"0x999423c3ee943cf759d3187e9f1f6cbd4b8455fe0f7736f8c5b2987ef9c899f2\"},\"contracts/ERC3156FlashLenderInterface.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\nimport \\\"./ERC3156FlashBorrowerInterface.sol\\\";\\n\\ninterface ERC3156FlashLenderInterface {\\n    /**\\n     * @dev The amount of currency available to be lent.\\n     * @param token The loan currency.\\n     * @return The amount of `token` that can be borrowed.\\n     */\\n    function maxFlashLoan(address token) external view returns (uint256);\\n\\n    /**\\n     * @dev The fee to be charged for a given loan.\\n     * @param token The loan currency.\\n     * @param amount The amount of tokens lent.\\n     * @return The amount of `token` to be charged for the loan, on top of the returned principal.\\n     */\\n    function flashFee(address token, uint256 amount) external view returns (uint256);\\n\\n    /**\\n     * @dev Initiate a flash loan.\\n     * @param receiver The receiver of the tokens in the loan, and the receiver of the callback.\\n     * @param token The loan currency.\\n     * @param amount The amount of tokens lent.\\n     * @param data Arbitrary data structure, intended to contain user-defined parameters.\\n     */\\n    function flashLoan(\\n        ERC3156FlashBorrowerInterface receiver,\\n        address token,\\n        uint256 amount,\\n        bytes calldata data\\n    ) external returns (bool);\\n}\\n\",\"keccak256\":\"0xbd95fffc09f05a8e0b055731364892c29908083275a3dcad6419d22fd6da96de\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\ncontract JoetrollerErrorReporter {\\n    enum Error {\\n        NO_ERROR,\\n        UNAUTHORIZED,\\n        JOETROLLER_MISMATCH,\\n        INSUFFICIENT_SHORTFALL,\\n        INSUFFICIENT_LIQUIDITY,\\n        INVALID_CLOSE_FACTOR,\\n        INVALID_COLLATERAL_FACTOR,\\n        INVALID_LIQUIDATION_INCENTIVE,\\n        MARKET_NOT_ENTERED, // no longer possible\\n        MARKET_NOT_LISTED,\\n        MARKET_ALREADY_LISTED,\\n        MATH_ERROR,\\n        NONZERO_BORROW_BALANCE,\\n        PRICE_ERROR,\\n        REJECTION,\\n        SNAPSHOT_ERROR,\\n        TOO_MANY_ASSETS,\\n        TOO_MUCH_REPAY\\n    }\\n\\n    enum FailureInfo {\\n        ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n        ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n        EXIT_MARKET_BALANCE_OWED,\\n        EXIT_MARKET_REJECTION,\\n        SET_CLOSE_FACTOR_OWNER_CHECK,\\n        SET_CLOSE_FACTOR_VALIDATION,\\n        SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n        SET_COLLATERAL_FACTOR_NO_EXISTS,\\n        SET_COLLATERAL_FACTOR_VALIDATION,\\n        SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n        SET_IMPLEMENTATION_OWNER_CHECK,\\n        SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n        SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n        SET_MAX_ASSETS_OWNER_CHECK,\\n        SET_PENDING_ADMIN_OWNER_CHECK,\\n        SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n        SET_PRICE_ORACLE_OWNER_CHECK,\\n        SUPPORT_MARKET_EXISTS,\\n        SUPPORT_MARKET_OWNER_CHECK,\\n        SET_PAUSE_GUARDIAN_OWNER_CHECK\\n    }\\n\\n    /**\\n     * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n     * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n     **/\\n    event Failure(uint256 error, uint256 info, uint256 detail);\\n\\n    /**\\n     * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n     */\\n    function fail(Error err, FailureInfo info) internal returns (uint256) {\\n        emit Failure(uint256(err), uint256(info), 0);\\n\\n        return uint256(err);\\n    }\\n\\n    /**\\n     * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n     */\\n    function failOpaque(\\n        Error err,\\n        FailureInfo info,\\n        uint256 opaqueError\\n    ) internal returns (uint256) {\\n        emit Failure(uint256(err), uint256(info), opaqueError);\\n\\n        return uint256(err);\\n    }\\n}\\n\\ncontract TokenErrorReporter {\\n    enum Error {\\n        NO_ERROR,\\n        UNAUTHORIZED,\\n        BAD_INPUT,\\n        JOETROLLER_REJECTION,\\n        JOETROLLER_CALCULATION_ERROR,\\n        INTEREST_RATE_MODEL_ERROR,\\n        INVALID_ACCOUNT_PAIR,\\n        INVALID_CLOSE_AMOUNT_REQUESTED,\\n        INVALID_COLLATERAL_FACTOR,\\n        MATH_ERROR,\\n        MARKET_NOT_FRESH,\\n        MARKET_NOT_LISTED,\\n        TOKEN_INSUFFICIENT_ALLOWANCE,\\n        TOKEN_INSUFFICIENT_BALANCE,\\n        TOKEN_INSUFFICIENT_CASH,\\n        TOKEN_TRANSFER_IN_FAILED,\\n        TOKEN_TRANSFER_OUT_FAILED\\n    }\\n\\n    /*\\n     * Note: FailureInfo (but not Error) is kept in alphabetical order\\n     *       This is because FailureInfo grows significantly faster, and\\n     *       the order of Error has some meaning, while the order of FailureInfo\\n     *       is entirely arbitrary.\\n     */\\n    enum FailureInfo {\\n        ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n        ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n        BORROW_ACCRUE_INTEREST_FAILED,\\n        BORROW_CASH_NOT_AVAILABLE,\\n        BORROW_FRESHNESS_CHECK,\\n        BORROW_MARKET_NOT_LISTED,\\n        BORROW_JOETROLLER_REJECTION,\\n        LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n        LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n        LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n        LIQUIDATE_JOETROLLER_REJECTION,\\n        LIQUIDATE_JOETROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n        LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n        LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n        LIQUIDATE_FRESHNESS_CHECK,\\n        LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n        LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n        LIQUIDATE_SEIZE_JOETROLLER_REJECTION,\\n        LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n        LIQUIDATE_SEIZE_TOO_MUCH,\\n        MINT_ACCRUE_INTEREST_FAILED,\\n        MINT_JOETROLLER_REJECTION,\\n        MINT_FRESHNESS_CHECK,\\n        MINT_TRANSFER_IN_FAILED,\\n        MINT_TRANSFER_IN_NOT_POSSIBLE,\\n        REDEEM_ACCRUE_INTEREST_FAILED,\\n        REDEEM_JOETROLLER_REJECTION,\\n        REDEEM_FRESHNESS_CHECK,\\n        REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n        REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n        REDUCE_RESERVES_ADMIN_CHECK,\\n        REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n        REDUCE_RESERVES_FRESH_CHECK,\\n        REDUCE_RESERVES_VALIDATION,\\n        REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n        REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n        REPAY_BORROW_JOETROLLER_REJECTION,\\n        REPAY_BORROW_FRESHNESS_CHECK,\\n        REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n        SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n        SET_COLLATERAL_FACTOR_VALIDATION,\\n        SET_JOETROLLER_OWNER_CHECK,\\n        SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n        SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n        SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n        SET_MAX_ASSETS_OWNER_CHECK,\\n        SET_ORACLE_MARKET_NOT_LISTED,\\n        SET_PENDING_ADMIN_OWNER_CHECK,\\n        SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n        SET_RESERVE_FACTOR_ADMIN_CHECK,\\n        SET_RESERVE_FACTOR_FRESH_CHECK,\\n        SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n        TRANSFER_JOETROLLER_REJECTION,\\n        TRANSFER_NOT_ALLOWED,\\n        ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n        ADD_RESERVES_FRESH_CHECK,\\n        ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n        SET_PROTOCOL_SEIZE_SHARE_ACCRUE_INTEREST_FAILED,\\n        SET_PROTOCOL_SEIZE_SHARE_ADMIN_CHECK,\\n        SET_PROTOCOL_SEIZE_SHARE_FRESH_CHECK,\\n        SET_PROTOCOL_SEIZE_SHARE_BOUNDS_CHECK\\n    }\\n\\n    /**\\n     * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n     * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n     **/\\n    event Failure(uint256 error, uint256 info, uint256 detail);\\n\\n    /**\\n     * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n     */\\n    function fail(Error err, FailureInfo info) internal returns (uint256) {\\n        emit Failure(uint256(err), uint256(info), 0);\\n\\n        return uint256(err);\\n    }\\n\\n    /**\\n     * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n     */\\n    function failOpaque(\\n        Error err,\\n        FailureInfo info,\\n        uint256 opaqueError\\n    ) internal returns (uint256) {\\n        emit Failure(uint256(err), uint256(info), opaqueError);\\n\\n        return uint256(err);\\n    }\\n}\\n\",\"keccak256\":\"0x0fa3a3fc3a0e9a4f364993a54a18353b316963d8b4eb6a97b2eeffc5f8f9c77d\"},\"contracts/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./CarefulMath.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n *         Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n *         `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath {\\n    uint256 constant expScale = 1e18;\\n    uint256 constant doubleScale = 1e36;\\n    uint256 constant halfExpScale = expScale / 2;\\n    uint256 constant mantissaOne = expScale;\\n\\n    struct Exp {\\n        uint256 mantissa;\\n    }\\n\\n    struct Double {\\n        uint256 mantissa;\\n    }\\n\\n    /**\\n     * @dev Creates an exponential from numerator and denominator values.\\n     *      Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n     *            or if `denom` is zero.\\n     */\\n    function getExp(uint256 num, uint256 denom) internal pure returns (MathError, Exp memory) {\\n        (MathError err0, uint256 scaledNumerator) = mulUInt(num, expScale);\\n        if (err0 != MathError.NO_ERROR) {\\n            return (err0, Exp({mantissa: 0}));\\n        }\\n\\n        (MathError err1, uint256 rational) = divUInt(scaledNumerator, denom);\\n        if (err1 != MathError.NO_ERROR) {\\n            return (err1, Exp({mantissa: 0}));\\n        }\\n\\n        return (MathError.NO_ERROR, Exp({mantissa: rational}));\\n    }\\n\\n    /**\\n     * @dev Adds two exponentials, returning a new exponential.\\n     */\\n    function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n        (MathError error, uint256 result) = addUInt(a.mantissa, b.mantissa);\\n\\n        return (error, Exp({mantissa: result}));\\n    }\\n\\n    /**\\n     * @dev Subtracts two exponentials, returning a new exponential.\\n     */\\n    function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n        (MathError error, uint256 result) = subUInt(a.mantissa, b.mantissa);\\n\\n        return (error, Exp({mantissa: result}));\\n    }\\n\\n    /**\\n     * @dev Multiply an Exp by a scalar, returning a new Exp.\\n     */\\n    function mulScalar(Exp memory a, uint256 scalar) internal pure returns (MathError, Exp memory) {\\n        (MathError err0, uint256 scaledMantissa) = mulUInt(a.mantissa, scalar);\\n        if (err0 != MathError.NO_ERROR) {\\n            return (err0, Exp({mantissa: 0}));\\n        }\\n\\n        return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\\n    }\\n\\n    /**\\n     * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n     */\\n    function mulScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (MathError, uint256) {\\n        (MathError err, Exp memory product) = mulScalar(a, scalar);\\n        if (err != MathError.NO_ERROR) {\\n            return (err, 0);\\n        }\\n\\n        return (MathError.NO_ERROR, truncate(product));\\n    }\\n\\n    /**\\n     * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n     */\\n    function mulScalarTruncateAddUInt(\\n        Exp memory a,\\n        uint256 scalar,\\n        uint256 addend\\n    ) internal pure returns (MathError, uint256) {\\n        (MathError err, Exp memory product) = mulScalar(a, scalar);\\n        if (err != MathError.NO_ERROR) {\\n            return (err, 0);\\n        }\\n\\n        return addUInt(truncate(product), addend);\\n    }\\n\\n    /**\\n     * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n     */\\n    function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\n        Exp memory product = mul_(a, scalar);\\n        return truncate(product);\\n    }\\n\\n    /**\\n     * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n     */\\n    function mul_ScalarTruncateAddUInt(\\n        Exp memory a,\\n        uint256 scalar,\\n        uint256 addend\\n    ) internal pure returns (uint256) {\\n        Exp memory product = mul_(a, scalar);\\n        return add_(truncate(product), addend);\\n    }\\n\\n    /**\\n     * @dev Divide an Exp by a scalar, returning a new Exp.\\n     */\\n    function divScalar(Exp memory a, uint256 scalar) internal pure returns (MathError, Exp memory) {\\n        (MathError err0, uint256 descaledMantissa) = divUInt(a.mantissa, scalar);\\n        if (err0 != MathError.NO_ERROR) {\\n            return (err0, Exp({mantissa: 0}));\\n        }\\n\\n        return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\\n    }\\n\\n    /**\\n     * @dev Divide a scalar by an Exp, returning a new Exp.\\n     */\\n    function divScalarByExp(uint256 scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n        /*\\n          We are doing this as:\\n          getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n          How it works:\\n          Exp = a / b;\\n          Scalar = s;\\n          `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n        */\\n        (MathError err0, uint256 numerator) = mulUInt(expScale, scalar);\\n        if (err0 != MathError.NO_ERROR) {\\n            return (err0, Exp({mantissa: 0}));\\n        }\\n        return getExp(numerator, divisor.mantissa);\\n    }\\n\\n    /**\\n     * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n     */\\n    function divScalarByExpTruncate(uint256 scalar, Exp memory divisor) internal pure returns (MathError, uint256) {\\n        (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n        if (err != MathError.NO_ERROR) {\\n            return (err, 0);\\n        }\\n\\n        return (MathError.NO_ERROR, truncate(fraction));\\n    }\\n\\n    /**\\n     * @dev Divide a scalar by an Exp, returning a new Exp.\\n     */\\n    function div_ScalarByExp(uint256 scalar, Exp memory divisor) internal pure returns (Exp memory) {\\n        /*\\n          We are doing this as:\\n          getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n          How it works:\\n          Exp = a / b;\\n          Scalar = s;\\n          `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n        */\\n        uint256 numerator = mul_(expScale, scalar);\\n        return Exp({mantissa: div_(numerator, divisor)});\\n    }\\n\\n    /**\\n     * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n     */\\n    function div_ScalarByExpTruncate(uint256 scalar, Exp memory divisor) internal pure returns (uint256) {\\n        Exp memory fraction = div_ScalarByExp(scalar, divisor);\\n        return truncate(fraction);\\n    }\\n\\n    /**\\n     * @dev Multiplies two exponentials, returning a new exponential.\\n     */\\n    function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n        (MathError err0, uint256 doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n        if (err0 != MathError.NO_ERROR) {\\n            return (err0, Exp({mantissa: 0}));\\n        }\\n\\n        // We add half the scale before dividing so that we get rounding instead of truncation.\\n        //  See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n        // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n        (MathError err1, uint256 doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n        if (err1 != MathError.NO_ERROR) {\\n            return (err1, Exp({mantissa: 0}));\\n        }\\n\\n        (MathError err2, uint256 product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n        // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n        assert(err2 == MathError.NO_ERROR);\\n\\n        return (MathError.NO_ERROR, Exp({mantissa: product}));\\n    }\\n\\n    /**\\n     * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n     */\\n    function mulExp(uint256 a, uint256 b) internal pure returns (MathError, Exp memory) {\\n        return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\\n    }\\n\\n    /**\\n     * @dev Multiplies three exponentials, returning a new exponential.\\n     */\\n    function mulExp3(\\n        Exp memory a,\\n        Exp memory b,\\n        Exp memory c\\n    ) internal pure returns (MathError, Exp memory) {\\n        (MathError err, Exp memory ab) = mulExp(a, b);\\n        if (err != MathError.NO_ERROR) {\\n            return (err, ab);\\n        }\\n        return mulExp(ab, c);\\n    }\\n\\n    /**\\n     * @dev Divides two exponentials, returning a new exponential.\\n     *     (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n     *  which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n     */\\n    function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n        return getExp(a.mantissa, b.mantissa);\\n    }\\n\\n    /**\\n     * @dev Truncates the given exp to a whole number value.\\n     *      For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n     */\\n    function truncate(Exp memory exp) internal pure returns (uint256) {\\n        // Note: We are not using careful math here as we're performing a division that cannot fail\\n        return exp.mantissa / expScale;\\n    }\\n\\n    /**\\n     * @dev Checks if first Exp is less than second Exp.\\n     */\\n    function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n        return left.mantissa < right.mantissa;\\n    }\\n\\n    /**\\n     * @dev Checks if left Exp <= right Exp.\\n     */\\n    function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n        return left.mantissa <= right.mantissa;\\n    }\\n\\n    /**\\n     * @dev returns true if Exp is exactly zero\\n     */\\n    function isZeroExp(Exp memory value) internal pure returns (bool) {\\n        return value.mantissa == 0;\\n    }\\n\\n    function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n        require(n < 2**224, errorMessage);\\n        return uint224(n);\\n    }\\n\\n    function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n        require(n < 2**32, errorMessage);\\n        return uint32(n);\\n    }\\n\\n    function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n        return Exp({mantissa: add_(a.mantissa, b.mantissa)});\\n    }\\n\\n    function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n        return Double({mantissa: add_(a.mantissa, b.mantissa)});\\n    }\\n\\n    function add_(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return add_(a, b, \\\"addition overflow\\\");\\n    }\\n\\n    function add_(\\n        uint256 a,\\n        uint256 b,\\n        string memory errorMessage\\n    ) internal pure returns (uint256) {\\n        uint256 c = a + b;\\n        require(c >= a, errorMessage);\\n        return c;\\n    }\\n\\n    function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n        return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\\n    }\\n\\n    function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n        return Double({mantissa: sub_(a.mantissa, b.mantissa)});\\n    }\\n\\n    function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return sub_(a, b, \\\"subtraction underflow\\\");\\n    }\\n\\n    function sub_(\\n        uint256 a,\\n        uint256 b,\\n        string memory errorMessage\\n    ) internal pure returns (uint256) {\\n        require(b <= a, errorMessage);\\n        return a - b;\\n    }\\n\\n    function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n        return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\\n    }\\n\\n    function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n        return Exp({mantissa: mul_(a.mantissa, b)});\\n    }\\n\\n    function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n        return mul_(a, b.mantissa) / expScale;\\n    }\\n\\n    function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n        return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\\n    }\\n\\n    function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n        return Double({mantissa: mul_(a.mantissa, b)});\\n    }\\n\\n    function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n        return mul_(a, b.mantissa) / doubleScale;\\n    }\\n\\n    function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return mul_(a, b, \\\"multiplication overflow\\\");\\n    }\\n\\n    function mul_(\\n        uint256 a,\\n        uint256 b,\\n        string memory errorMessage\\n    ) internal pure returns (uint256) {\\n        if (a == 0 || b == 0) {\\n            return 0;\\n        }\\n        uint256 c = a * b;\\n        require(c / a == b, errorMessage);\\n        return c;\\n    }\\n\\n    function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n        return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\\n    }\\n\\n    function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n        return Exp({mantissa: div_(a.mantissa, b)});\\n    }\\n\\n    function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n        return div_(mul_(a, expScale), b.mantissa);\\n    }\\n\\n    function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n        return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\\n    }\\n\\n    function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n        return Double({mantissa: div_(a.mantissa, b)});\\n    }\\n\\n    function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n        return div_(mul_(a, doubleScale), b.mantissa);\\n    }\\n\\n    function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n        return div_(a, b, \\\"divide by zero\\\");\\n    }\\n\\n    function div_(\\n        uint256 a,\\n        uint256 b,\\n        string memory errorMessage\\n    ) internal pure returns (uint256) {\\n        require(b > 0, errorMessage);\\n        return a / b;\\n    }\\n\\n    function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n        return Double({mantissa: div_(mul_(a, doubleScale), b)});\\n    }\\n\\n    // implementation from https://github.com/Uniswap/uniswap-lib/commit/99f3f28770640ba1bb1ff460ac7c5292fb8291a0\\n    // original implementation: https://github.com/abdk-consulting/abdk-libraries-solidity/blob/master/ABDKMath64x64.sol#L687\\n    function sqrt(uint256 x) internal pure returns (uint256) {\\n        if (x == 0) return 0;\\n        uint256 xx = x;\\n        uint256 r = 1;\\n\\n        if (xx >= 0x100000000000000000000000000000000) {\\n            xx >>= 128;\\n            r <<= 64;\\n        }\\n        if (xx >= 0x10000000000000000) {\\n            xx >>= 64;\\n            r <<= 32;\\n        }\\n        if (xx >= 0x100000000) {\\n            xx >>= 32;\\n            r <<= 16;\\n        }\\n        if (xx >= 0x10000) {\\n            xx >>= 16;\\n            r <<= 8;\\n        }\\n        if (xx >= 0x100) {\\n            xx >>= 8;\\n            r <<= 4;\\n        }\\n        if (xx >= 0x10) {\\n            xx >>= 4;\\n            r <<= 2;\\n        }\\n        if (xx >= 0x8) {\\n            r <<= 1;\\n        }\\n\\n        r = (r + x / r) >> 1;\\n        r = (r + x / r) >> 1;\\n        r = (r + x / r) >> 1;\\n        r = (r + x / r) >> 1;\\n        r = (r + x / r) >> 1;\\n        r = (r + x / r) >> 1;\\n        r = (r + x / r) >> 1; // Seven iterations should be enough\\n        uint256 r1 = x / r;\\n        return (r < r1 ? r : r1);\\n    }\\n}\\n\",\"keccak256\":\"0xf8507369462982bc2fb7200d9039467851b3403afdc637adbee4b629b1927e0f\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\ncontract InterestRateModel {\\n    /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n    bool public constant isInterestRateModel = true;\\n\\n    /**\\n     * @notice Calculates the current borrow interest rate per sec\\n     * @param cash The total amount of cash the market has\\n     * @param borrows The total amount of borrows the market has outstanding\\n     * @param reserves The total amnount of reserves the market has\\n     * @return The borrow rate per sec (as a percentage, and scaled by 1e18)\\n     */\\n    function getBorrowRate(\\n        uint256 cash,\\n        uint256 borrows,\\n        uint256 reserves\\n    ) external view returns (uint256);\\n\\n    /**\\n     * @notice Calculates the current supply interest rate per sec\\n     * @param cash The total amount of cash the market has\\n     * @param borrows The total amount of borrows the market has outstanding\\n     * @param reserves The total amnount of reserves the market has\\n     * @param reserveFactorMantissa The current reserve factor the market has\\n     * @return The supply rate per sec (as a percentage, and scaled by 1e18)\\n     */\\n    function getSupplyRate(\\n        uint256 cash,\\n        uint256 borrows,\\n        uint256 reserves,\\n        uint256 reserveFactorMantissa\\n    ) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x7ca611215903c5068643656d02f87c5576f6770ced6dc5b87a49b125d7d007ae\"},\"contracts/JCollateralCapErc20.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./JToken.sol\\\";\\nimport \\\"./ERC3156FlashLenderInterface.sol\\\";\\nimport \\\"./ERC3156FlashBorrowerInterface.sol\\\";\\n\\n/**\\n * @title Cream's JCollateralCapErc20 Contract\\n * @notice JTokens which wrap an EIP-20 underlying with collateral cap\\n * @author Cream\\n */\\ncontract JCollateralCapErc20 is JToken, JCollateralCapErc20Interface, JProtocolSeizeShareStorage {\\n    /**\\n     * @notice Initialize the new money market\\n     * @param underlying_ The address of the underlying asset\\n     * @param joetroller_ The address of the Joetroller\\n     * @param interestRateModel_ The address of the interest rate model\\n     * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n     * @param name_ ERC-20 name of this token\\n     * @param symbol_ ERC-20 symbol of this token\\n     * @param decimals_ ERC-20 decimal precision of this token\\n     */\\n    function initialize(\\n        address underlying_,\\n        JoetrollerInterface joetroller_,\\n        InterestRateModel interestRateModel_,\\n        uint256 initialExchangeRateMantissa_,\\n        string memory name_,\\n        string memory symbol_,\\n        uint8 decimals_\\n    ) public {\\n        // JToken initialize does the bulk of the work\\n        super.initialize(joetroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\\n\\n        // Set underlying and sanity check it\\n        underlying = underlying_;\\n        EIP20Interface(underlying).totalSupply();\\n    }\\n\\n    /*** User Interface ***/\\n\\n    /**\\n     * @notice Sender supplies assets into the market and receives jTokens in exchange\\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n     * @param mintAmount The amount of the underlying asset to supply\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function mint(uint256 mintAmount) external returns (uint256) {\\n        (uint256 err, ) = mintInternal(mintAmount, false);\\n        return err;\\n    }\\n\\n    /**\\n     * @notice Sender redeems jTokens in exchange for the underlying asset\\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n     * @param redeemTokens The number of jTokens to redeem into underlying\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function redeem(uint256 redeemTokens) external returns (uint256) {\\n        return redeemInternal(redeemTokens, false);\\n    }\\n\\n    /**\\n     * @notice Sender redeems jTokens in exchange for a specified amount of underlying asset\\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n     * @param redeemAmount The amount of underlying to redeem\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function redeemUnderlying(uint256 redeemAmount) external returns (uint256) {\\n        return redeemUnderlyingInternal(redeemAmount, false);\\n    }\\n\\n    /**\\n     * @notice Sender borrows assets from the protocol to their own address\\n     * @param borrowAmount The amount of the underlying asset to borrow\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function borrow(uint256 borrowAmount) external returns (uint256) {\\n        return borrowInternal(borrowAmount, false);\\n    }\\n\\n    /**\\n     * @notice Sender repays their own borrow\\n     * @param repayAmount The amount to repay\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function repayBorrow(uint256 repayAmount) external returns (uint256) {\\n        (uint256 err, ) = repayBorrowInternal(repayAmount, false);\\n        return err;\\n    }\\n\\n    /**\\n     * @notice Sender repays a borrow belonging to borrower\\n     * @param borrower the account with the debt being payed off\\n     * @param repayAmount The amount to repay\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256) {\\n        (uint256 err, ) = repayBorrowBehalfInternal(borrower, repayAmount, false);\\n        return err;\\n    }\\n\\n    /**\\n     * @notice The sender liquidates the borrowers collateral.\\n     *  The collateral seized is transferred to the liquidator.\\n     * @param borrower The borrower of this jToken to be liquidated\\n     * @param repayAmount The amount of the underlying borrowed asset to repay\\n     * @param jTokenCollateral The market in which to seize collateral from the borrower\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function liquidateBorrow(\\n        address borrower,\\n        uint256 repayAmount,\\n        JTokenInterface jTokenCollateral\\n    ) external returns (uint256) {\\n        (uint256 err, ) = liquidateBorrowInternal(borrower, repayAmount, jTokenCollateral, false);\\n        return err;\\n    }\\n\\n    /**\\n     * @notice The sender adds to reserves.\\n     * @param addAmount The amount fo underlying token to add as reserves\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _addReserves(uint256 addAmount) external returns (uint256) {\\n        return _addReservesInternal(addAmount, false);\\n    }\\n\\n    /**\\n     * @notice Set the given collateral cap for the market.\\n     * @param newCollateralCap New collateral cap for this market. A value of 0 corresponds to no cap.\\n     */\\n    function _setCollateralCap(uint256 newCollateralCap) external {\\n        require(msg.sender == admin, \\\"only admin can set collateral cap\\\");\\n\\n        collateralCap = newCollateralCap;\\n        emit NewCollateralCap(address(this), newCollateralCap);\\n    }\\n\\n    /**\\n     * @notice Absorb excess cash into reserves.\\n     */\\n    function gulp() external nonReentrant {\\n        uint256 cashOnChain = getCashOnChain();\\n        uint256 cashPrior = getCashPrior();\\n\\n        uint256 excessCash = sub_(cashOnChain, cashPrior);\\n        totalReserves = add_(totalReserves, excessCash);\\n        internalCash = cashOnChain;\\n    }\\n\\n    /**\\n     * @notice Get the max flash loan amount\\n     */\\n    function maxFlashLoan() external view returns (uint256) {\\n        uint256 amount = 0;\\n        if (JoetrollerInterfaceExtension(address(joetroller)).flashloanAllowed(address(this), address(0), amount, \\\"\\\")) {\\n            amount = getCashPrior();\\n        }\\n        return amount;\\n    }\\n\\n    /**\\n     * @notice Get the flash loan fees\\n     * @param amount amount of token to borrow\\n     */\\n    function flashFee(uint256 amount) external view returns (uint256) {\\n        require(\\n            JoetrollerInterfaceExtension(address(joetroller)).flashloanAllowed(address(this), address(0), amount, \\\"\\\"),\\n            \\\"flashloan is paused\\\"\\n        );\\n        return div_(mul_(amount, flashFeeBips), 10000);\\n    }\\n\\n    /**\\n     * @notice Flash loan funds to a given account.\\n     * @param receiver The receiver address for the funds\\n     * @param initiator flash loan initiator\\n     * @param amount The amount of the funds to be loaned\\n     * @param data The other data\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function flashLoan(\\n        ERC3156FlashBorrowerInterface receiver,\\n        address initiator,\\n        uint256 amount,\\n        bytes calldata data\\n    ) external nonReentrant returns (bool) {\\n        require(amount > 0, \\\"flashLoan amount should be greater than zero\\\");\\n        require(accrueInterest() == uint256(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n        require(\\n            JoetrollerInterfaceExtension(address(joetroller)).flashloanAllowed(\\n                address(this),\\n                address(receiver),\\n                amount,\\n                data\\n            ),\\n            \\\"flashloan is paused\\\"\\n        );\\n        uint256 cashOnChainBefore = getCashOnChain();\\n        uint256 cashBefore = getCashPrior();\\n        require(cashBefore >= amount, \\\"INSUFFICIENT_LIQUIDITY\\\");\\n\\n        // 1. calculate fee, 1 bips = 1/10000\\n        uint256 totalFee = this.flashFee(amount);\\n\\n        // 2. transfer fund to receiver\\n        doTransferOut(address(uint160(address(receiver))), amount, false);\\n\\n        // 3. update totalBorrows\\n        totalBorrows = add_(totalBorrows, amount);\\n\\n        // 4. execute receiver's callback function\\n\\n        require(\\n            receiver.onFlashLoan(initiator, underlying, amount, totalFee, data) ==\\n                keccak256(\\\"ERC3156FlashBorrowerInterface.onFlashLoan\\\"),\\n            \\\"IERC3156: Callback failed\\\"\\n        );\\n\\n        // 5. take amount + fee from receiver, then check balance\\n        uint256 repaymentAmount = add_(amount, totalFee);\\n        doTransferIn(address(receiver), repaymentAmount, false);\\n\\n        uint256 cashOnChainAfter = getCashOnChain();\\n\\n        require(cashOnChainAfter == add_(cashOnChainBefore, totalFee), \\\"BALANCE_INCONSISTENT\\\");\\n\\n        // 6. update reserves and internal cash and totalBorrows\\n        uint256 reservesFee = mul_ScalarTruncate(Exp({mantissa: reserveFactorMantissa}), totalFee);\\n        totalReserves = add_(totalReserves, reservesFee);\\n        internalCash = add_(cashBefore, totalFee);\\n        totalBorrows = sub_(totalBorrows, amount);\\n\\n        emit Flashloan(address(receiver), amount, totalFee, reservesFee);\\n        return true;\\n    }\\n\\n    /**\\n     * @notice Register account collateral tokens if there is space.\\n     * @param account The account to register\\n     * @dev This function could only be called by joetroller.\\n     * @return The actual registered amount of collateral\\n     */\\n    function registerCollateral(address account) external returns (uint256) {\\n        // Make sure accountCollateralTokens of `account` is initialized.\\n        initializeAccountCollateralTokens(account);\\n\\n        require(msg.sender == address(joetroller), \\\"only joetroller may register collateral for user\\\");\\n\\n        uint256 amount = sub_(accountTokens[account], accountCollateralTokens[account]);\\n        return increaseUserCollateralInternal(account, amount);\\n    }\\n\\n    /**\\n     * @notice Unregister account collateral tokens if the account still has enough collateral.\\n     * @dev This function could only be called by joetroller.\\n     * @param account The account to unregister\\n     */\\n    function unregisterCollateral(address account) external {\\n        // Make sure accountCollateralTokens of `account` is initialized.\\n        initializeAccountCollateralTokens(account);\\n\\n        require(msg.sender == address(joetroller), \\\"only joetroller may unregister collateral for user\\\");\\n\\n        decreaseUserCollateralInternal(account, accountCollateralTokens[account]);\\n    }\\n\\n    /*** Safe Token ***/\\n\\n    /**\\n     * @notice Gets internal balance of this contract in terms of the underlying.\\n     *  It excludes balance from direct transfer.\\n     * @dev This excludes the value of the current message, if any\\n     * @return The quantity of underlying tokens owned by this contract\\n     */\\n    function getCashPrior() internal view returns (uint256) {\\n        return internalCash;\\n    }\\n\\n    /**\\n     * @notice Gets total balance of this contract in terms of the underlying\\n     * @dev This excludes the value of the current message, if any\\n     * @return The quantity of underlying tokens owned by this contract\\n     */\\n    function getCashOnChain() internal view returns (uint256) {\\n        EIP20Interface token = EIP20Interface(underlying);\\n        return token.balanceOf(address(this));\\n    }\\n\\n    /**\\n     * @notice Initialize the account's collateral tokens. This function should be called in the beginning of every function\\n     *  that accesses accountCollateralTokens or accountTokens.\\n     * @param account The account of accountCollateralTokens that needs to be updated\\n     */\\n    function initializeAccountCollateralTokens(address account) internal {\\n        /**\\n         * If isCollateralTokenInit is false, it means accountCollateralTokens was not initialized yet.\\n         * This case will only happen once and must be the very beginning. accountCollateralTokens is a new structure and its\\n         * initial value should be equal to accountTokens if user has entered the market. However, it's almost impossible to\\n         * check every user's value when the implementation becomes active. Therefore, it must rely on every action which will\\n         * access accountTokens to call this function to check if accountCollateralTokens needed to be initialized.\\n         */\\n        if (!isCollateralTokenInit[account]) {\\n            if (JoetrollerInterfaceExtension(address(joetroller)).checkMembership(account, JToken(this))) {\\n                accountCollateralTokens[account] = accountTokens[account];\\n                totalCollateralTokens = add_(totalCollateralTokens, accountTokens[account]);\\n\\n                emit UserCollateralChanged(account, accountCollateralTokens[account]);\\n            }\\n            isCollateralTokenInit[account] = true;\\n        }\\n    }\\n\\n    /**\\n     * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case.\\n     *      This will revert due to insufficient balance or insufficient allowance.\\n     *      This function returns the actual amount received,\\n     *      which may be less than `amount` if there is a fee attached to the transfer.\\n     *\\n     *      Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value.\\n     *            See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n     */\\n    function doTransferIn(\\n        address from,\\n        uint256 amount,\\n        bool isNative\\n    ) internal returns (uint256) {\\n        isNative; // unused\\n\\n        EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying);\\n        uint256 balanceBefore = EIP20Interface(underlying).balanceOf(address(this));\\n        token.transferFrom(from, address(this), amount);\\n\\n        bool success;\\n        assembly {\\n            switch returndatasize()\\n            case 0 {\\n                // This is a non-standard ERC-20\\n                success := not(0) // set success to true\\n            }\\n            case 32 {\\n                // This is a joeliant ERC-20\\n                returndatacopy(0, 0, 32)\\n                success := mload(0) // Set `success = returndata` of external call\\n            }\\n            default {\\n                // This is an excessively non-joeliant ERC-20, revert.\\n                revert(0, 0)\\n            }\\n        }\\n        require(success, \\\"TOKEN_TRANSFER_IN_FAILED\\\");\\n\\n        // Calculate the amount that was *actually* transferred\\n        uint256 balanceAfter = EIP20Interface(underlying).balanceOf(address(this));\\n        uint256 transferredIn = sub_(balanceAfter, balanceBefore);\\n        internalCash = add_(internalCash, transferredIn);\\n        return transferredIn;\\n    }\\n\\n    /**\\n     * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory\\n     *      error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to\\n     *      insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified\\n     *      it is >= amount, this should not revert in normal conditions.\\n     *\\n     *      Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value.\\n     *            See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\\n     */\\n    function doTransferOut(\\n        address payable to,\\n        uint256 amount,\\n        bool isNative\\n    ) internal {\\n        isNative; // unused\\n\\n        EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying);\\n        token.transfer(to, amount);\\n\\n        bool success;\\n        assembly {\\n            switch returndatasize()\\n            case 0 {\\n                // This is a non-standard ERC-20\\n                success := not(0) // set success to true\\n            }\\n            case 32 {\\n                // This is a joelaint ERC-20\\n                returndatacopy(0, 0, 32)\\n                success := mload(0) // Set `success = returndata` of external call\\n            }\\n            default {\\n                // This is an excessively non-joeliant ERC-20, revert.\\n                revert(0, 0)\\n            }\\n        }\\n        require(success, \\\"TOKEN_TRANSFER_OUT_FAILED\\\");\\n        internalCash = sub_(internalCash, amount);\\n    }\\n\\n    /**\\n     * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n     * @dev Called by both `transfer` and `transferFrom` internally\\n     * @param spender The address of the account performing the transfer\\n     * @param src The address of the source account\\n     * @param dst The address of the destination account\\n     * @param tokens The number of tokens to transfer\\n     * @return Whether or not the transfer succeeded\\n     */\\n    function transferTokens(\\n        address spender,\\n        address src,\\n        address dst,\\n        uint256 tokens\\n    ) internal returns (uint256) {\\n        // Make sure accountCollateralTokens of `src` and `dst` are initialized.\\n        initializeAccountCollateralTokens(src);\\n        initializeAccountCollateralTokens(dst);\\n\\n        /**\\n         * For every user, accountTokens must be greater than or equal to accountCollateralTokens.\\n         * The buffer between the two values will be transferred first.\\n         * bufferTokens = accountTokens[src] - accountCollateralTokens[src]\\n         * collateralTokens = tokens - bufferTokens\\n         */\\n        uint256 bufferTokens = sub_(accountTokens[src], accountCollateralTokens[src]);\\n        uint256 collateralTokens = 0;\\n        if (tokens > bufferTokens) {\\n            collateralTokens = tokens - bufferTokens;\\n        }\\n\\n        /**\\n         * Since bufferTokens are not collateralized and can be transferred freely, we only check with joetroller\\n         * whether collateralized tokens can be transferred.\\n         */\\n        uint256 allowed = joetroller.transferAllowed(address(this), src, dst, collateralTokens);\\n        if (allowed != 0) {\\n            return failOpaque(Error.JOETROLLER_REJECTION, FailureInfo.TRANSFER_JOETROLLER_REJECTION, allowed);\\n        }\\n\\n        /* Do not allow self-transfers */\\n        if (src == dst) {\\n            return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n        }\\n\\n        /* Get the allowance, infinite for the account owner */\\n        uint256 startingAllowance = 0;\\n        if (spender == src) {\\n            startingAllowance = uint256(-1);\\n        } else {\\n            startingAllowance = transferAllowances[src][spender];\\n        }\\n\\n        /* Do the calculations, checking for {under,over}flow */\\n        accountTokens[src] = sub_(accountTokens[src], tokens);\\n        accountTokens[dst] = add_(accountTokens[dst], tokens);\\n        if (collateralTokens > 0) {\\n            accountCollateralTokens[src] = sub_(accountCollateralTokens[src], collateralTokens);\\n            accountCollateralTokens[dst] = add_(accountCollateralTokens[dst], collateralTokens);\\n\\n            emit UserCollateralChanged(src, accountCollateralTokens[src]);\\n            emit UserCollateralChanged(dst, accountCollateralTokens[dst]);\\n        }\\n\\n        /* Eat some of the allowance (if necessary) */\\n        if (startingAllowance != uint256(-1)) {\\n            transferAllowances[src][spender] = sub_(startingAllowance, tokens);\\n        }\\n\\n        /* We emit a Transfer event */\\n        emit Transfer(src, dst, tokens);\\n\\n        // unused function\\n        // joetroller.transferVerify(address(this), src, dst, tokens);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice Get the account's jToken balances\\n     * @param account The address of the account\\n     */\\n    function getJTokenBalanceInternal(address account) internal view returns (uint256) {\\n        if (isCollateralTokenInit[account]) {\\n            return accountCollateralTokens[account];\\n        } else {\\n            /**\\n             * If the value of accountCollateralTokens was not initialized, we should return the value of accountTokens.\\n             */\\n            return accountTokens[account];\\n        }\\n    }\\n\\n    /**\\n     * @notice Increase user's collateral. Increase as much as we can.\\n     * @param account The address of the account\\n     * @param amount The amount of collateral user wants to increase\\n     * @return The actual increased amount of collateral\\n     */\\n    function increaseUserCollateralInternal(address account, uint256 amount) internal returns (uint256) {\\n        uint256 totalCollateralTokensNew = add_(totalCollateralTokens, amount);\\n        if (collateralCap == 0 || (collateralCap != 0 && totalCollateralTokensNew <= collateralCap)) {\\n            // 1. If collateral cap is not set,\\n            // 2. If collateral cap is set but has enough space for this user,\\n            // give all the user needs.\\n            totalCollateralTokens = totalCollateralTokensNew;\\n            accountCollateralTokens[account] = add_(accountCollateralTokens[account], amount);\\n\\n            emit UserCollateralChanged(account, accountCollateralTokens[account]);\\n            return amount;\\n        } else if (collateralCap > totalCollateralTokens) {\\n            // If the collateral cap is set but the remaining cap is not enough for this user,\\n            // give the remaining parts to the user.\\n            uint256 gap = sub_(collateralCap, totalCollateralTokens);\\n            totalCollateralTokens = collateralCap;\\n            accountCollateralTokens[account] = add_(accountCollateralTokens[account], gap);\\n\\n            emit UserCollateralChanged(account, accountCollateralTokens[account]);\\n            return gap;\\n        }\\n        return 0;\\n    }\\n\\n    /**\\n     * @notice Decrease user's collateral. Reject if the amount can't be fully decrease.\\n     * @param account The address of the account\\n     * @param amount The amount of collateral user wants to decrease\\n     */\\n    function decreaseUserCollateralInternal(address account, uint256 amount) internal {\\n        require(joetroller.redeemAllowed(address(this), account, amount) == 0, \\\"joetroller rejection\\\");\\n\\n        /*\\n         * Return if amount is zero.\\n         * Put behind `redeemAllowed` for accuring potential JOE rewards.\\n         */\\n        if (amount == 0) {\\n            return;\\n        }\\n\\n        totalCollateralTokens = sub_(totalCollateralTokens, amount);\\n        accountCollateralTokens[account] = sub_(accountCollateralTokens[account], amount);\\n\\n        emit UserCollateralChanged(account, accountCollateralTokens[account]);\\n    }\\n\\n    struct MintLocalVars {\\n        uint256 exchangeRateMantissa;\\n        uint256 mintTokens;\\n        uint256 actualMintAmount;\\n    }\\n\\n    /**\\n     * @notice User supplies assets into the market and receives jTokens in exchange\\n     * @dev Assumes interest has already been accrued up to the current timestamp\\n     * @param minter The address of the account which is supplying the assets\\n     * @param mintAmount The amount of the underlying asset to supply\\n     * @param isNative The amount is in native or not\\n     * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n     */\\n    function mintFresh(\\n        address minter,\\n        uint256 mintAmount,\\n        bool isNative\\n    ) internal returns (uint256, uint256) {\\n        // Make sure accountCollateralTokens of `minter` is initialized.\\n        initializeAccountCollateralTokens(minter);\\n\\n        /* Fail if mint not allowed */\\n        uint256 allowed = joetroller.mintAllowed(address(this), minter, mintAmount);\\n        if (allowed != 0) {\\n            return (failOpaque(Error.JOETROLLER_REJECTION, FailureInfo.MINT_JOETROLLER_REJECTION, allowed), 0);\\n        }\\n\\n        /*\\n         * Return if mintAmount is zero.\\n         * Put behind `mintAllowed` for accuring potential JOE rewards.\\n         */\\n        if (mintAmount == 0) {\\n            return (uint256(Error.NO_ERROR), 0);\\n        }\\n\\n        /* Verify market's block timestamp equals current block timestamp */\\n        if (accrualBlockTimestamp != getBlockTimestamp()) {\\n            return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n        }\\n\\n        MintLocalVars memory vars;\\n\\n        vars.exchangeRateMantissa = exchangeRateStoredInternal();\\n\\n        /////////////////////////\\n        // EFFECTS & INTERACTIONS\\n        // (No safe failures beyond this point)\\n\\n        /*\\n         *  We call `doTransferIn` for the minter and the mintAmount.\\n         *  Note: The jToken must handle variations between ERC-20 and ETH underlying.\\n         *  `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n         *  side-effects occurred. The function returns the amount actually transferred,\\n         *  in case of a fee. On success, the jToken holds an additional `actualMintAmount`\\n         *  of cash.\\n         */\\n        vars.actualMintAmount = doTransferIn(minter, mintAmount, isNative);\\n\\n        /*\\n         * We get the current exchange rate and calculate the number of jTokens to be minted:\\n         *  mintTokens = actualMintAmount / exchangeRate\\n         */\\n        vars.mintTokens = div_ScalarByExpTruncate(vars.actualMintAmount, Exp({mantissa: vars.exchangeRateMantissa}));\\n\\n        /*\\n         * We calculate the new total supply of jTokens and minter token balance, checking for overflow:\\n         *  totalSupply = totalSupply + mintTokens\\n         *  accountTokens[minter] = accountTokens[minter] + mintTokens\\n         */\\n        totalSupply = add_(totalSupply, vars.mintTokens);\\n        accountTokens[minter] = add_(accountTokens[minter], vars.mintTokens);\\n\\n        /*\\n         * We only allocate collateral tokens if the minter has entered the market.\\n         */\\n        if (JoetrollerInterfaceExtension(address(joetroller)).checkMembership(minter, JToken(this))) {\\n            increaseUserCollateralInternal(minter, vars.mintTokens);\\n        }\\n\\n        /* We emit a Mint event, and a Transfer event */\\n        emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\\n        emit Transfer(address(this), minter, vars.mintTokens);\\n\\n        /* We call the defense hook */\\n        // unused function\\n        // joetroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n        return (uint256(Error.NO_ERROR), vars.actualMintAmount);\\n    }\\n\\n    struct RedeemLocalVars {\\n        uint256 exchangeRateMantissa;\\n        uint256 redeemTokens;\\n        uint256 redeemAmount;\\n    }\\n\\n    /**\\n     * @notice User redeems jTokens in exchange for the underlying asset\\n     * @dev Assumes interest has already been accrued up to the current timestamp. Only one of redeemTokensIn or redeemAmountIn may be non-zero and it would do nothing if both are zero.\\n     * @param redeemer The address of the account which is redeeming the tokens\\n     * @param redeemTokensIn The number of jTokens to redeem into underlying\\n     * @param redeemAmountIn The number of underlying tokens to receive from redeeming jTokens\\n     * @param isNative The amount is in native or not\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function redeemFresh(\\n        address payable redeemer,\\n        uint256 redeemTokensIn,\\n        uint256 redeemAmountIn,\\n        bool isNative\\n    ) internal returns (uint256) {\\n        // Make sure accountCollateralTokens of `redeemer` is initialized.\\n        initializeAccountCollateralTokens(redeemer);\\n\\n        require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n        RedeemLocalVars memory vars;\\n\\n        /* exchangeRate = invoke Exchange Rate Stored() */\\n        vars.exchangeRateMantissa = exchangeRateStoredInternal();\\n\\n        /* If redeemTokensIn > 0: */\\n        if (redeemTokensIn > 0) {\\n            /*\\n             * We calculate the exchange rate and the amount of underlying to be redeemed:\\n             *  redeemTokens = redeemTokensIn\\n             *  redeemAmount = redeemTokensIn x exchangeRateCurrent\\n             */\\n            vars.redeemTokens = redeemTokensIn;\\n            vars.redeemAmount = mul_ScalarTruncate(Exp({mantissa: vars.exchangeRateMantissa}), redeemTokensIn);\\n        } else {\\n            /*\\n             * We get the current exchange rate and calculate the amount to be redeemed:\\n             *  redeemTokens = redeemAmountIn / exchangeRate\\n             *  redeemAmount = redeemAmountIn\\n             */\\n            vars.redeemTokens = div_ScalarByExpTruncate(redeemAmountIn, Exp({mantissa: vars.exchangeRateMantissa}));\\n            vars.redeemAmount = redeemAmountIn;\\n        }\\n\\n\\n        /**\\n         * For every user, accountTokens must be greater than or equal to accountCollateralTokens.\\n         * The buffer between the two values will be redeemed first.\\n         * bufferTokens = accountTokens[redeemer] - accountCollateralTokens[redeemer]\\n         * collateralTokens = redeemTokens - bufferTokens\\n         */\\n        uint256 bufferTokens = sub_(accountTokens[redeemer], accountCollateralTokens[redeemer]);\\n        uint256 collateralTokens = 0;\\n        if (vars.redeemTokens > bufferTokens) {\\n            collateralTokens = vars.redeemTokens - bufferTokens;\\n        }\\n\\n        uint256 allowed = joetroller.redeemAllowed(address(this), redeemer, collateralTokens);\\n        if (allowed != 0) {\\n            return failOpaque(Error.JOETROLLER_REJECTION, FailureInfo.REDEEM_JOETROLLER_REJECTION, allowed);\\n        }\\n\\n        /* Verify market's block timestamp equals current block timestamp */\\n        if (accrualBlockTimestamp != getBlockTimestamp()) {\\n            return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n        }\\n\\n        /* Fail gracefully if protocol has insufficient cash */\\n        if (getCashPrior() < vars.redeemAmount) {\\n            return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\\n        }\\n\\n        /////////////////////////\\n        // EFFECTS & INTERACTIONS\\n        // (No safe failures beyond this point)\\n\\n        /*\\n         * We invoke doTransferOut for the redeemer and the redeemAmount.\\n         *  Note: The jToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the jToken has redeemAmount less of cash.\\n         *  doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n         */\\n        doTransferOut(redeemer, vars.redeemAmount, isNative);\\n\\n        /*\\n         * We calculate the new total supply and redeemer balance, checking for underflow:\\n         *  totalSupplyNew = totalSupply - redeemTokens\\n         *  accountTokensNew = accountTokens[redeemer] - redeemTokens\\n         */\\n        totalSupply = sub_(totalSupply, vars.redeemTokens);\\n        accountTokens[redeemer] = sub_(accountTokens[redeemer], vars.redeemTokens);\\n\\n        /*\\n         * We only deallocate collateral tokens if the redeemer needs to redeem them.\\n         */\\n        decreaseUserCollateralInternal(redeemer, collateralTokens);\\n\\n        /* We emit a Transfer event, and a Redeem event */\\n        emit Transfer(redeemer, address(this), vars.redeemTokens);\\n        emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n        /* We call the defense hook */\\n        joetroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice Transfers collateral tokens (this market) to the liquidator.\\n     * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another JToken.\\n     *  Its absolutely critical to use msg.sender as the seizer jToken and not a parameter.\\n     * @param seizerToken The contract seizing the collateral (i.e. borrowed jToken)\\n     * @param liquidator The account receiving seized collateral\\n     * @param borrower The account having collateral seized\\n     * @param seizeTokens The number of jTokens to seize\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function seizeInternal(\\n        address seizerToken,\\n        address liquidator,\\n        address borrower,\\n        uint256 seizeTokens\\n    ) internal returns (uint256) {\\n        // Make sure accountCollateralTokens of `liquidator` and `borrower` are initialized.\\n        initializeAccountCollateralTokens(liquidator);\\n        initializeAccountCollateralTokens(borrower);\\n\\n        /* Fail if seize not allowed */\\n        uint256 allowed = joetroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n        if (allowed != 0) {\\n            return failOpaque(Error.JOETROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_JOETROLLER_REJECTION, allowed);\\n        }\\n\\n        /*\\n         * Return if seizeTokens is zero.\\n         * Put behind `seizeAllowed` for accuring potential JOE rewards.\\n         */\\n        if (seizeTokens == 0) {\\n            return uint256(Error.NO_ERROR);\\n        }\\n\\n        /* Fail if borrower = liquidator */\\n        if (borrower == liquidator) {\\n            return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n        }\\n\\n        uint256 protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\\n        uint256 liquidatorSeizeTokens = sub_(seizeTokens, protocolSeizeTokens);\\n\\n        uint256 exchangeRateMantissa = exchangeRateStoredInternal();\\n        uint256 protocolSeizeAmount = mul_ScalarTruncate(Exp({mantissa: exchangeRateMantissa}), protocolSeizeTokens);\\n\\n        /*\\n         * We calculate the new borrower and liquidator token balances and token collateral balances, failing on underflow/overflow:\\n         *  accountTokens[borrower] = accountTokens[borrower] - seizeTokens\\n         *  accountTokens[liquidator] = accountTokens[liquidator] + seizeTokens\\n         *  accountCollateralTokens[borrower] = accountCollateralTokens[borrower] - seizeTokens\\n         *  accountCollateralTokens[liquidator] = accountCollateralTokens[liquidator] + seizeTokens\\n         */\\n        accountTokens[borrower] = sub_(accountTokens[borrower], seizeTokens);\\n        accountTokens[liquidator] = add_(accountTokens[liquidator], liquidatorSeizeTokens);\\n        accountCollateralTokens[borrower] = sub_(accountCollateralTokens[borrower], seizeTokens);\\n        accountCollateralTokens[liquidator] = add_(accountCollateralTokens[liquidator], liquidatorSeizeTokens);\\n        totalReserves = add_(totalReserves, protocolSeizeAmount);\\n        totalSupply = sub_(totalSupply, protocolSeizeTokens);\\n\\n        /* Emit a Transfer, UserCollateralChanged and ReservesAdded events */\\n        emit Transfer(borrower, liquidator, seizeTokens);\\n        emit UserCollateralChanged(borrower, accountCollateralTokens[borrower]);\\n        emit UserCollateralChanged(liquidator, accountCollateralTokens[liquidator]);\\n        emit ReservesAdded(address(this), protocolSeizeAmount, totalReserves);\\n\\n        /* We call the defense hook */\\n        // unused function\\n        // joetroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /*** Admin Functions ***/\\n\\n    /**\\n     * @notice Accrues interest and sets a new collateral seize share for the protocol using _setProtocolSeizeShareFresh\\n     * @dev Admin function to accrue interest and set a new collateral seize share\\n     * @return uint256 0=success, otherwise a failure (see ErrorReport.sol for details)\\n     */\\n    function _setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa) external nonReentrant returns (uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            return fail(Error(error), FailureInfo.SET_PROTOCOL_SEIZE_SHARE_ACCRUE_INTEREST_FAILED);\\n        }\\n        return _setProtocolSeizeShareFresh(newProtocolSeizeShareMantissa);\\n    }\\n\\n    function _setProtocolSeizeShareFresh(uint256 newProtocolSeizeShareMantissa) internal returns (uint256) {\\n        // Check caller is admin\\n        if (msg.sender != admin) {\\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_PROTOCOL_SEIZE_SHARE_ADMIN_CHECK);\\n        }\\n\\n        // Verify market's block timestamp equals current block timestamp\\n        if (accrualBlockTimestamp != getBlockTimestamp()) {\\n            return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_PROTOCOL_SEIZE_SHARE_FRESH_CHECK);\\n        }\\n\\n        if (newProtocolSeizeShareMantissa > protocolSeizeShareMaxMantissa) {\\n            return fail(Error.BAD_INPUT, FailureInfo.SET_PROTOCOL_SEIZE_SHARE_BOUNDS_CHECK);\\n        }\\n\\n        uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n        protocolSeizeShareMantissa = newProtocolSeizeShareMantissa;\\n\\n        emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n}\\n\",\"keccak256\":\"0xa5351ceecb96f024f9fea971ebdf90da6d3642f1aac38fba913d015f9a172084\"},\"contracts/JCollateralCapErc20Delegate.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./JCollateralCapErc20.sol\\\";\\n\\n/**\\n * @title Cream's JCollateralCapErc20Delegate Contract\\n * @notice JTokens which wrap an EIP-20 underlying and are delegated to\\n * @author Cream\\n */\\ncontract JCollateralCapErc20Delegate is JCollateralCapErc20 {\\n    /**\\n     * @notice Construct an empty delegate\\n     */\\n    constructor() public {}\\n\\n    /**\\n     * @notice Called by the delegator on a delegate to initialize it for duty\\n     * @param data The encoded bytes data for any initialization\\n     */\\n    function _becomeImplementation(bytes memory data) public {\\n        // Shh -- currently unused\\n        data;\\n\\n        // Shh -- we don't ever want this hook to be marked pure\\n        if (false) {\\n            implementation = address(0);\\n        }\\n\\n        require(msg.sender == admin, \\\"only the admin may call _becomeImplementation\\\");\\n\\n        // Set internal cash when becoming implementation\\n        internalCash = getCashOnChain();\\n\\n        // Set JToken version in joetroller\\n        JoetrollerInterfaceExtension(address(joetroller)).updateJTokenVersion(\\n            address(this),\\n            JoetrollerV1Storage.Version.COLLATERALCAP\\n        );\\n    }\\n\\n    /**\\n     * @notice Called by the delegator on a delegate to forfeit its responsibility\\n     */\\n    function _resignImplementation() public {\\n        // Shh -- we don't ever want this hook to be marked pure\\n        if (false) {\\n            implementation = address(0);\\n        }\\n\\n        require(msg.sender == admin, \\\"only the admin may call _resignImplementation\\\");\\n    }\\n}\\n\",\"keccak256\":\"0xdf2ac2f729fac7a533a155eece6c6f2c8b378d329bee8c8d4b1855ee24568e38\"},\"contracts/JToken.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./JoetrollerInterface.sol\\\";\\nimport \\\"./JTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's JToken Contract\\n * @notice Abstract base for JTokens\\n * @author Compound\\n */\\ncontract JToken is JTokenInterface, Exponential, TokenErrorReporter {\\n    /**\\n     * @notice Initialize the money market\\n     * @param joetroller_ The address of the Joetroller\\n     * @param interestRateModel_ The address of the interest rate model\\n     * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n     * @param name_ EIP-20 name of this token\\n     * @param symbol_ EIP-20 symbol of this token\\n     * @param decimals_ EIP-20 decimal precision of this token\\n     */\\n    function initialize(\\n        JoetrollerInterface joetroller_,\\n        InterestRateModel interestRateModel_,\\n        uint256 initialExchangeRateMantissa_,\\n        string memory name_,\\n        string memory symbol_,\\n        uint8 decimals_\\n    ) public {\\n        require(msg.sender == admin, \\\"only admin may initialize the market\\\");\\n        require(accrualBlockTimestamp == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n        // Set initial exchange rate\\n        initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n        require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n        // Set the joetroller\\n        uint256 err = _setJoetroller(joetroller_);\\n        require(err == uint256(Error.NO_ERROR), \\\"setting joetroller failed\\\");\\n\\n        // Initialize block timestamp and borrow index (block timestamp mocks depend on joetroller being set)\\n        accrualBlockTimestamp = getBlockTimestamp();\\n        borrowIndex = mantissaOne;\\n\\n        // Set the interest rate model (depends on block timestamp / borrow index)\\n        err = _setInterestRateModelFresh(interestRateModel_);\\n        require(err == uint256(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n        name = name_;\\n        symbol = symbol_;\\n        decimals = decimals_;\\n\\n        // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n        _notEntered = true;\\n    }\\n\\n    /**\\n     * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n     * @param dst The address of the destination account\\n     * @param amount The number of tokens to transfer\\n     * @return Whether or not the transfer succeeded\\n     */\\n    function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\\n        return transferTokens(msg.sender, msg.sender, dst, amount) == uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice Transfer `amount` tokens from `src` to `dst`\\n     * @param src The address of the source account\\n     * @param dst The address of the destination account\\n     * @param amount The number of tokens to transfer\\n     * @return Whether or not the transfer succeeded\\n     */\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 amount\\n    ) external nonReentrant returns (bool) {\\n        return transferTokens(msg.sender, src, dst, amount) == uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice Approve `spender` to transfer up to `amount` from `src`\\n     * @dev This will overwrite the approval amount for `spender`\\n     *  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n     * @param spender The address of the account which may transfer tokens\\n     * @param amount The number of tokens that are approved (-1 means infinite)\\n     * @return Whether or not the approval succeeded\\n     */\\n    function approve(address spender, uint256 amount) external returns (bool) {\\n        address src = msg.sender;\\n        transferAllowances[src][spender] = amount;\\n        emit Approval(src, spender, amount);\\n        return true;\\n    }\\n\\n    /**\\n     * @notice Get the current allowance from `owner` for `spender`\\n     * @param owner The address of the account which owns the tokens to be spent\\n     * @param spender The address of the account which may transfer tokens\\n     * @return The number of tokens allowed to be spent (-1 means infinite)\\n     */\\n    function allowance(address owner, address spender) external view returns (uint256) {\\n        return transferAllowances[owner][spender];\\n    }\\n\\n    /**\\n     * @notice Get the token balance of the `owner`\\n     * @param owner The address of the account to query\\n     * @return The number of tokens owned by `owner`\\n     */\\n    function balanceOf(address owner) external view returns (uint256) {\\n        return accountTokens[owner];\\n    }\\n\\n    /**\\n     * @notice Get the underlying balance of the `owner`\\n     * @dev This also accrues interest in a transaction\\n     * @param owner The address of the account to query\\n     * @return The amount of underlying owned by `owner`\\n     */\\n    function balanceOfUnderlying(address owner) external returns (uint256) {\\n        Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\\n        return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n    }\\n\\n    /**\\n     * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n     * @dev This is used by joetroller to more efficiently perform liquidity checks.\\n     * @param account Address of the account to snapshot\\n     * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n     */\\n    function getAccountSnapshot(address account)\\n        external\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256,\\n            uint256\\n        )\\n    {\\n        uint256 jTokenBalance = getJTokenBalanceInternal(account);\\n        uint256 borrowBalance = borrowBalanceStoredInternal(account);\\n        uint256 exchangeRateMantissa = exchangeRateStoredInternal();\\n\\n        return (uint256(Error.NO_ERROR), jTokenBalance, borrowBalance, exchangeRateMantissa);\\n    }\\n\\n    /**\\n     * @dev Function to simply retrieve block timestamp\\n     *  This exists mainly for inheriting test contracts to stub this result.\\n     */\\n    function getBlockTimestamp() internal view returns (uint256) {\\n        return block.timestamp;\\n    }\\n\\n    /**\\n     * @notice Returns the current per-sec borrow interest rate for this jToken\\n     * @return The borrow interest rate per sec, scaled by 1e18\\n     */\\n    function borrowRatePerSecond() external view returns (uint256) {\\n        return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n    }\\n\\n    /**\\n     * @notice Returns the current per-sec supply interest rate for this jToken\\n     * @return The supply interest rate per sec, scaled by 1e18\\n     */\\n    function supplyRatePerSecond() external view returns (uint256) {\\n        return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n    }\\n\\n    /**\\n     * @notice Returns the estimated per-sec borrow interest rate for this jToken after some change\\n     * @return The borrow interest rate per sec, scaled by 1e18\\n     */\\n    function estimateBorrowRatePerSecondAfterChange(uint256 change, bool repay) external view returns (uint256) {\\n        uint256 cashPriorNew;\\n        uint256 totalBorrowsNew;\\n\\n        if (repay) {\\n            cashPriorNew = add_(getCashPrior(), change);\\n            totalBorrowsNew = sub_(totalBorrows, change);\\n        } else {\\n            cashPriorNew = sub_(getCashPrior(), change);\\n            totalBorrowsNew = add_(totalBorrows, change);\\n        }\\n        return interestRateModel.getBorrowRate(cashPriorNew, totalBorrowsNew, totalReserves);\\n    }\\n\\n    /**\\n     * @notice Returns the estimated per-sec supply interest rate for this jToken after some change\\n     * @return The supply interest rate per sec, scaled by 1e18\\n     */\\n    function estimateSupplyRatePerSecondAfterChange(uint256 change, bool repay) external view returns (uint256) {\\n        uint256 cashPriorNew;\\n        uint256 totalBorrowsNew;\\n\\n        if (repay) {\\n            cashPriorNew = add_(getCashPrior(), change);\\n            totalBorrowsNew = sub_(totalBorrows, change);\\n        } else {\\n            cashPriorNew = sub_(getCashPrior(), change);\\n            totalBorrowsNew = add_(totalBorrows, change);\\n        }\\n\\n        return interestRateModel.getSupplyRate(cashPriorNew, totalBorrowsNew, totalReserves, reserveFactorMantissa);\\n    }\\n\\n    /**\\n     * @notice Returns the current total borrows plus accrued interest\\n     * @return The total borrows with interest\\n     */\\n    function totalBorrowsCurrent() external nonReentrant returns (uint256) {\\n        require(accrueInterest() == uint256(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n        return totalBorrows;\\n    }\\n\\n    /**\\n     * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n     * @param account The address whose balance should be calculated after updating borrowIndex\\n     * @return The calculated balance\\n     */\\n    function borrowBalanceCurrent(address account) external nonReentrant returns (uint256) {\\n        require(accrueInterest() == uint256(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n        return borrowBalanceStored(account);\\n    }\\n\\n    /**\\n     * @notice Return the borrow balance of account based on stored data\\n     * @param account The address whose balance should be calculated\\n     * @return The calculated balance\\n     */\\n    function borrowBalanceStored(address account) public view returns (uint256) {\\n        return borrowBalanceStoredInternal(account);\\n    }\\n\\n    /**\\n     * @notice Return the borrow balance of account based on stored data\\n     * @param account The address whose balance should be calculated\\n     * @return the calculated balance or 0 if error code is non-zero\\n     */\\n    function borrowBalanceStoredInternal(address account) internal view returns (uint256) {\\n        /* Get borrowBalance and borrowIndex */\\n        BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n        /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n         * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n         */\\n        if (borrowSnapshot.principal == 0) {\\n            return 0;\\n        }\\n\\n        /* Calculate new borrow balance using the interest index:\\n         *  recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n         */\\n        uint256 principalTimesIndex = mul_(borrowSnapshot.principal, borrowIndex);\\n        uint256 result = div_(principalTimesIndex, borrowSnapshot.interestIndex);\\n        return result;\\n    }\\n\\n    /**\\n     * @notice Accrue interest then return the up-to-date exchange rate\\n     * @return Calculated exchange rate scaled by 1e18\\n     */\\n    function exchangeRateCurrent() public nonReentrant returns (uint256) {\\n        require(accrueInterest() == uint256(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n        return exchangeRateStored();\\n    }\\n\\n    /**\\n     * @notice Calculates the exchange rate from the underlying to the JToken\\n     * @dev This function does not accrue interest before calculating the exchange rate\\n     * @return Calculated exchange rate scaled by 1e18\\n     */\\n    function exchangeRateStored() public view returns (uint256) {\\n        return exchangeRateStoredInternal();\\n    }\\n\\n    /**\\n     * @notice Calculates the exchange rate from the underlying to the JToken\\n     * @dev This function does not accrue interest before calculating the exchange rate\\n     * @return calculated exchange rate scaled by 1e18\\n     */\\n    function exchangeRateStoredInternal() internal view returns (uint256) {\\n        uint256 _totalSupply = totalSupply;\\n        if (_totalSupply == 0) {\\n            /*\\n             * If there are no tokens minted:\\n             *  exchangeRate = initialExchangeRate\\n             */\\n            return initialExchangeRateMantissa;\\n        } else {\\n            /*\\n             * Otherwise:\\n             *  exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n             */\\n            uint256 totalCash = getCashPrior();\\n            uint256 cashPlusBorrowsMinusReserves = sub_(add_(totalCash, totalBorrows), totalReserves);\\n            uint256 exchangeRate = div_(cashPlusBorrowsMinusReserves, Exp({mantissa: _totalSupply}));\\n            return exchangeRate;\\n        }\\n    }\\n\\n    /**\\n     * @notice Get cash balance of this jToken in the underlying asset\\n     * @return The quantity of underlying asset owned by this contract\\n     */\\n    function getCash() external view returns (uint256) {\\n        return getCashPrior();\\n    }\\n\\n    /**\\n     * @notice Applies accrued interest to total borrows and reserves\\n     * @dev This calculates interest accrued from the last checkpointed timestamp\\n     *   up to the current timestamp and writes new checkpoint to storage.\\n     */\\n    function accrueInterest() public returns (uint256) {\\n        /* Remember the initial block timestamp */\\n        uint256 currentBlockTimestamp = getBlockTimestamp();\\n        uint256 accrualBlockTimestampPrior = accrualBlockTimestamp;\\n\\n        /* Short-circuit accumulating 0 interest */\\n        if (accrualBlockTimestampPrior == currentBlockTimestamp) {\\n            return uint256(Error.NO_ERROR);\\n        }\\n\\n        /* Read the previous values out of storage */\\n        uint256 cashPrior = getCashPrior();\\n        uint256 borrowsPrior = totalBorrows;\\n        uint256 reservesPrior = totalReserves;\\n        uint256 borrowIndexPrior = borrowIndex;\\n\\n        /* Calculate the current borrow interest rate */\\n        uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n        require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n        /* Calculate the number of seconds elapsed since the last accrual */\\n        uint256 timestampDelta = sub_(currentBlockTimestamp, accrualBlockTimestampPrior);\\n\\n        /*\\n         * Calculate the interest accumulated into borrows and reserves and the new index:\\n         *  simpleInterestFactor = borrowRate * timestampDelta\\n         *  interestAccumulated = simpleInterestFactor * totalBorrows\\n         *  totalBorrowsNew = interestAccumulated + totalBorrows\\n         *  totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n         *  borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n         */\\n\\n        Exp memory simpleInterestFactor = mul_(Exp({mantissa: borrowRateMantissa}), timestampDelta);\\n        uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n        uint256 totalBorrowsNew = add_(interestAccumulated, borrowsPrior);\\n        uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n            Exp({mantissa: reserveFactorMantissa}),\\n            interestAccumulated,\\n            reservesPrior\\n        );\\n        uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n        /////////////////////////\\n        // EFFECTS & INTERACTIONS\\n        // (No safe failures beyond this point)\\n\\n        /* We write the previously calculated values into storage */\\n        accrualBlockTimestamp = currentBlockTimestamp;\\n        borrowIndex = borrowIndexNew;\\n        totalBorrows = totalBorrowsNew;\\n        totalReserves = totalReservesNew;\\n\\n        /* We emit an AccrueInterest event */\\n        emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice Sender supplies assets into the market and receives jTokens in exchange\\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n     * @param mintAmount The amount of the underlying asset to supply\\n     * @param isNative The amount is in native or not\\n     * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n     */\\n    function mintInternal(uint256 mintAmount, bool isNative) internal nonReentrant returns (uint256, uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n            return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n        }\\n        // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n        return mintFresh(msg.sender, mintAmount, isNative);\\n    }\\n\\n    /**\\n     * @notice Sender redeems jTokens in exchange for the underlying asset\\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n     * @param redeemTokens The number of jTokens to redeem into underlying\\n     * @param isNative The amount is in native or not\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function redeemInternal(uint256 redeemTokens, bool isNative) internal nonReentrant returns (uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n            return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n        }\\n        // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n        return redeemFresh(msg.sender, redeemTokens, 0, isNative);\\n    }\\n\\n    /**\\n     * @notice Sender redeems jTokens in exchange for a specified amount of underlying asset\\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n     * @param redeemAmount The amount of underlying to receive from redeeming jTokens\\n     * @param isNative The amount is in native or not\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function redeemUnderlyingInternal(uint256 redeemAmount, bool isNative) internal nonReentrant returns (uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n            return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n        }\\n        // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n        return redeemFresh(msg.sender, 0, redeemAmount, isNative);\\n    }\\n\\n    /**\\n     * @notice Sender borrows assets from the protocol to their own address\\n     * @param borrowAmount The amount of the underlying asset to borrow\\n     * @param isNative The amount is in native or not\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function borrowInternal(uint256 borrowAmount, bool isNative) internal nonReentrant returns (uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n            return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n        }\\n        // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n        return borrowFresh(msg.sender, borrowAmount, isNative);\\n    }\\n\\n    struct BorrowLocalVars {\\n        MathError mathErr;\\n        uint256 accountBorrows;\\n        uint256 accountBorrowsNew;\\n        uint256 totalBorrowsNew;\\n    }\\n\\n    /**\\n     * @notice Users borrow assets from the protocol to their own address\\n     * @param borrowAmount The amount of the underlying asset to borrow\\n     * @param isNative The amount is in native or not\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function borrowFresh(\\n        address payable borrower,\\n        uint256 borrowAmount,\\n        bool isNative\\n    ) internal returns (uint256) {\\n        /* Fail if borrow not allowed */\\n        uint256 allowed = joetroller.borrowAllowed(address(this), borrower, borrowAmount);\\n        if (allowed != 0) {\\n            return failOpaque(Error.JOETROLLER_REJECTION, FailureInfo.BORROW_JOETROLLER_REJECTION, allowed);\\n        }\\n\\n        /*\\n         * Return if borrowAmount is zero.\\n         * Put behind `borrowAllowed` for accuring potential JOE rewards.\\n         */\\n        if (borrowAmount == 0) {\\n            accountBorrows[borrower].principal = borrowBalanceStoredInternal(borrower);\\n            accountBorrows[borrower].interestIndex = borrowIndex;\\n            return uint256(Error.NO_ERROR);\\n        }\\n\\n        /* Verify market's block timestamp equals current block timestamp */\\n        if (accrualBlockTimestamp != getBlockTimestamp()) {\\n            return fail(Error.MARKET_NOT_FRESH, FailureInfo.BORROW_FRESHNESS_CHECK);\\n        }\\n\\n        /* Fail gracefully if protocol has insufficient underlying cash */\\n        if (getCashPrior() < borrowAmount) {\\n            return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.BORROW_CASH_NOT_AVAILABLE);\\n        }\\n\\n        BorrowLocalVars memory vars;\\n\\n        /*\\n         * We calculate the new borrower and total borrow balances, failing on overflow:\\n         *  accountBorrowsNew = accountBorrows + borrowAmount\\n         *  totalBorrowsNew = totalBorrows + borrowAmount\\n         */\\n        vars.accountBorrows = borrowBalanceStoredInternal(borrower);\\n        vars.accountBorrowsNew = add_(vars.accountBorrows, borrowAmount);\\n        vars.totalBorrowsNew = add_(totalBorrows, borrowAmount);\\n\\n        /////////////////////////\\n        // EFFECTS & INTERACTIONS\\n        // (No safe failures beyond this point)\\n\\n        /*\\n         * We invoke doTransferOut for the borrower and the borrowAmount.\\n         *  Note: The jToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the jToken borrowAmount less of cash.\\n         *  doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n         */\\n        doTransferOut(borrower, borrowAmount, isNative);\\n\\n        /* We write the previously calculated values into storage */\\n        accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n        accountBorrows[borrower].interestIndex = borrowIndex;\\n        totalBorrows = vars.totalBorrowsNew;\\n\\n        /* We emit a Borrow event */\\n        emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n        /* We call the defense hook */\\n        // unused function\\n        // joetroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice Sender repays their own borrow\\n     * @param repayAmount The amount to repay\\n     * @param isNative The amount is in native or not\\n     * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n     */\\n    function repayBorrowInternal(uint256 repayAmount, bool isNative) internal nonReentrant returns (uint256, uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n            return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n        }\\n        // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n        return repayBorrowFresh(msg.sender, msg.sender, repayAmount, isNative);\\n    }\\n\\n    /**\\n     * @notice Sender repays a borrow belonging to borrower\\n     * @param borrower the account with the debt being payed off\\n     * @param repayAmount The amount to repay\\n     * @param isNative The amount is in native or not\\n     * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n     */\\n    function repayBorrowBehalfInternal(\\n        address borrower,\\n        uint256 repayAmount,\\n        bool isNative\\n    ) internal nonReentrant returns (uint256, uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n            return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n        }\\n        // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n        return repayBorrowFresh(msg.sender, borrower, repayAmount, isNative);\\n    }\\n\\n    struct RepayBorrowLocalVars {\\n        Error err;\\n        MathError mathErr;\\n        uint256 repayAmount;\\n        uint256 borrowerIndex;\\n        uint256 accountBorrows;\\n        uint256 accountBorrowsNew;\\n        uint256 totalBorrowsNew;\\n        uint256 actualRepayAmount;\\n    }\\n\\n    /**\\n     * @notice Borrows are repaid by another user (possibly the borrower).\\n     * @param payer the account paying off the borrow\\n     * @param borrower the account with the debt being payed off\\n     * @param repayAmount the amount of undelrying tokens being returned\\n     * @param isNative The amount is in native or not\\n     * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n     */\\n    function repayBorrowFresh(\\n        address payer,\\n        address borrower,\\n        uint256 repayAmount,\\n        bool isNative\\n    ) internal returns (uint256, uint256) {\\n        /* Fail if repayBorrow not allowed */\\n        uint256 allowed = joetroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n        if (allowed != 0) {\\n            return (failOpaque(Error.JOETROLLER_REJECTION, FailureInfo.REPAY_BORROW_JOETROLLER_REJECTION, allowed), 0);\\n        }\\n\\n        /*\\n         * Return if repayAmount is zero.\\n         * Put behind `repayBorrowAllowed` for accuring potential JOE rewards.\\n         */\\n        if (repayAmount == 0) {\\n            accountBorrows[borrower].principal = borrowBalanceStoredInternal(borrower);\\n            accountBorrows[borrower].interestIndex = borrowIndex;\\n            return (uint256(Error.NO_ERROR), 0);\\n        }\\n\\n        /* Verify market's block timestamp equals current block timestamp */\\n        if (accrualBlockTimestamp != getBlockTimestamp()) {\\n            return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n        }\\n\\n        RepayBorrowLocalVars memory vars;\\n\\n        /* We remember the original borrowerIndex for verification purposes */\\n        vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n        /* We fetch the amount the borrower owes, with accumulated interest */\\n        vars.accountBorrows = borrowBalanceStoredInternal(borrower);\\n\\n        /* If repayAmount == -1, repayAmount = accountBorrows */\\n        if (repayAmount == uint256(-1)) {\\n            vars.repayAmount = vars.accountBorrows;\\n        } else {\\n            vars.repayAmount = repayAmount;\\n        }\\n\\n        /////////////////////////\\n        // EFFECTS & INTERACTIONS\\n        // (No safe failures beyond this point)\\n\\n        /*\\n         * We call doTransferIn for the payer and the repayAmount\\n         *  Note: The jToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the jToken holds an additional repayAmount of cash.\\n         *  doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n         *   it returns the amount actually transferred, in case of a fee.\\n         */\\n        vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount, isNative);\\n\\n        /*\\n         * We calculate the new borrower and total borrow balances, failing on underflow:\\n         *  accountBorrowsNew = accountBorrows - actualRepayAmount\\n         *  totalBorrowsNew = totalBorrows - actualRepayAmount\\n         */\\n        vars.accountBorrowsNew = sub_(vars.accountBorrows, vars.actualRepayAmount);\\n        vars.totalBorrowsNew = sub_(totalBorrows, vars.actualRepayAmount);\\n\\n        /* We write the previously calculated values into storage */\\n        accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n        accountBorrows[borrower].interestIndex = borrowIndex;\\n        totalBorrows = vars.totalBorrowsNew;\\n\\n        /* We emit a RepayBorrow event */\\n        emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n        /* We call the defense hook */\\n        // unused function\\n        // joetroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n        return (uint256(Error.NO_ERROR), vars.actualRepayAmount);\\n    }\\n\\n    /**\\n     * @notice The sender liquidates the borrowers collateral.\\n     *  The collateral seized is transferred to the liquidator.\\n     * @param borrower The borrower of this jToken to be liquidated\\n     * @param repayAmount The amount of the underlying borrowed asset to repay\\n     * @param jTokenCollateral The market in which to seize collateral from the borrower\\n     * @param isNative The amount is in native or not\\n     * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n     */\\n    function liquidateBorrowInternal(\\n        address borrower,\\n        uint256 repayAmount,\\n        JTokenInterface jTokenCollateral,\\n        bool isNative\\n    ) internal nonReentrant returns (uint256, uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n            return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n        }\\n\\n        error = jTokenCollateral.accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n            return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n        }\\n\\n        // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n        return liquidateBorrowFresh(msg.sender, borrower, repayAmount, jTokenCollateral, isNative);\\n    }\\n\\n    /**\\n     * @notice The liquidator liquidates the borrowers collateral.\\n     *  The collateral seized is transferred to the liquidator.\\n     * @param borrower The borrower of this jToken to be liquidated\\n     * @param liquidator The address repaying the borrow and seizing collateral\\n     * @param jTokenCollateral The market in which to seize collateral from the borrower\\n     * @param repayAmount The amount of the underlying borrowed asset to repay\\n     * @param isNative The amount is in native or not\\n     * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n     */\\n    function liquidateBorrowFresh(\\n        address liquidator,\\n        address borrower,\\n        uint256 repayAmount,\\n        JTokenInterface jTokenCollateral,\\n        bool isNative\\n    ) internal returns (uint256, uint256) {\\n        /* Fail if liquidate not allowed */\\n        uint256 allowed = joetroller.liquidateBorrowAllowed(\\n            address(this),\\n            address(jTokenCollateral),\\n            liquidator,\\n            borrower,\\n            repayAmount\\n        );\\n        if (allowed != 0) {\\n            return (failOpaque(Error.JOETROLLER_REJECTION, FailureInfo.LIQUIDATE_JOETROLLER_REJECTION, allowed), 0);\\n        }\\n\\n        /* Verify market's block timestamp equals current block timestamp */\\n        if (accrualBlockTimestamp != getBlockTimestamp()) {\\n            return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n        }\\n\\n        /* Verify jTokenCollateral market's block timestamp equals current block timestamp */\\n        if (jTokenCollateral.accrualBlockTimestamp() != getBlockTimestamp()) {\\n            return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n        }\\n\\n        /* Fail if borrower = liquidator */\\n        if (borrower == liquidator) {\\n            return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n        }\\n\\n        /* Fail if repayAmount = 0 */\\n        if (repayAmount == 0) {\\n            return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n        }\\n\\n        /* Fail if repayAmount = -1 */\\n        if (repayAmount == uint256(-1)) {\\n            return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n        }\\n\\n        /* Fail if repayBorrow fails */\\n        (uint256 repayBorrowError, uint256 actualRepayAmount) = repayBorrowFresh(\\n            liquidator,\\n            borrower,\\n            repayAmount,\\n            isNative\\n        );\\n        if (repayBorrowError != uint256(Error.NO_ERROR)) {\\n            return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n        }\\n\\n        /////////////////////////\\n        // EFFECTS & INTERACTIONS\\n        // (No safe failures beyond this point)\\n\\n        /* We calculate the number of collateral tokens that will be seized */\\n        (uint256 amountSeizeError, uint256 seizeTokens) = joetroller.liquidateCalculateSeizeTokens(\\n            address(this),\\n            address(jTokenCollateral),\\n            actualRepayAmount\\n        );\\n        require(amountSeizeError == uint256(Error.NO_ERROR), \\\"LIQUIDATE_JOETROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n        /* Revert if borrower collateral token balance < seizeTokens */\\n        require(jTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n        // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n        uint256 seizeError;\\n        if (address(jTokenCollateral) == address(this)) {\\n            seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n        } else {\\n            seizeError = jTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n        }\\n\\n        /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n        require(seizeError == uint256(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n        /* We emit a LiquidateBorrow event */\\n        emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(jTokenCollateral), seizeTokens);\\n\\n        /* We call the defense hook */\\n        // unused function\\n        // joetroller.liquidateBorrowVerify(address(this), address(jTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\\n\\n        return (uint256(Error.NO_ERROR), actualRepayAmount);\\n    }\\n\\n    /**\\n     * @notice Transfers collateral tokens (this market) to the liquidator.\\n     * @dev Will fail unless called by another jToken during the process of liquidation.\\n     *  Its absolutely critical to use msg.sender as the borrowed jToken and not a parameter.\\n     * @param liquidator The account receiving seized collateral\\n     * @param borrower The account having collateral seized\\n     * @param seizeTokens The number of jTokens to seize\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function seize(\\n        address liquidator,\\n        address borrower,\\n        uint256 seizeTokens\\n    ) external nonReentrant returns (uint256) {\\n        return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n    }\\n\\n    /*** Admin Functions ***/\\n\\n    /**\\n     * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n     * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n     * @param newPendingAdmin New pending admin.\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _setPendingAdmin(address payable newPendingAdmin) external returns (uint256) {\\n        // Check caller = admin\\n        if (msg.sender != admin) {\\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n        }\\n\\n        // Save current value, if any, for inclusion in log\\n        address oldPendingAdmin = pendingAdmin;\\n\\n        // Store pendingAdmin with value newPendingAdmin\\n        pendingAdmin = newPendingAdmin;\\n\\n        // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n        emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n     * @dev Admin function for pending admin to accept role and update admin\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _acceptAdmin() external returns (uint256) {\\n        // Check caller is pendingAdmin and pendingAdmin \\u2260 address(0)\\n        if (msg.sender != pendingAdmin || msg.sender == address(0)) {\\n            return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n        }\\n\\n        // Save current values for inclusion in log\\n        address oldAdmin = admin;\\n        address oldPendingAdmin = pendingAdmin;\\n\\n        // Store admin with value pendingAdmin\\n        admin = pendingAdmin;\\n\\n        // Clear the pending value\\n        pendingAdmin = address(0);\\n\\n        emit NewAdmin(oldAdmin, admin);\\n        emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice Sets a new joetroller for the market\\n     * @dev Admin function to set a new joetroller\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _setJoetroller(JoetrollerInterface newJoetroller) public returns (uint256) {\\n        // Check caller is admin\\n        if (msg.sender != admin) {\\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_JOETROLLER_OWNER_CHECK);\\n        }\\n\\n        JoetrollerInterface oldJoetroller = joetroller;\\n        // Ensure invoke joetroller.isJoetroller() returns true\\n        require(newJoetroller.isJoetroller(), \\\"marker method returned false\\\");\\n\\n        // Set market's joetroller to newJoetroller\\n        joetroller = newJoetroller;\\n\\n        // Emit NewJoetroller(oldJoetroller, newJoetroller)\\n        emit NewJoetroller(oldJoetroller, newJoetroller);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice Accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\\n     * @dev Admin function to accrue interest and set a new reserve factor\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _setReserveFactor(uint256 newReserveFactorMantissa) external nonReentrant returns (uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n            return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n        }\\n        // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n        return _setReserveFactorFresh(newReserveFactorMantissa);\\n    }\\n\\n    /**\\n     * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n     * @dev Admin function to set a new reserve factor\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal returns (uint256) {\\n        // Check caller is admin\\n        if (msg.sender != admin) {\\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_RESERVE_FACTOR_ADMIN_CHECK);\\n        }\\n\\n        // Verify market's block timestamp equals current block timestamp\\n        if (accrualBlockTimestamp != getBlockTimestamp()) {\\n            return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n        }\\n\\n        // Check newReserveFactor \\u2264 maxReserveFactor\\n        if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n            return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n        }\\n\\n        uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n        reserveFactorMantissa = newReserveFactorMantissa;\\n\\n        emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice Accrues interest and reduces reserves by transferring from msg.sender\\n     * @param addAmount Amount of addition to reserves\\n     * @param isNative The amount is in native or not\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _addReservesInternal(uint256 addAmount, bool isNative) internal nonReentrant returns (uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n            return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n        }\\n\\n        // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n        (error, ) = _addReservesFresh(addAmount, isNative);\\n        return error;\\n    }\\n\\n    /**\\n     * @notice Add reserves by transferring from caller\\n     * @dev Requires fresh interest accrual\\n     * @param addAmount Amount of addition to reserves\\n     * @param isNative The amount is in native or not\\n     * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n     */\\n    function _addReservesFresh(uint256 addAmount, bool isNative) internal returns (uint256, uint256) {\\n        // totalReserves + actualAddAmount\\n        uint256 totalReservesNew;\\n        uint256 actualAddAmount;\\n\\n        // We fail gracefully unless market's block timestamp equals current block timestamp\\n        if (accrualBlockTimestamp != getBlockTimestamp()) {\\n            return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n        }\\n\\n        /////////////////////////\\n        // EFFECTS & INTERACTIONS\\n        // (No safe failures beyond this point)\\n\\n        /*\\n         * We call doTransferIn for the caller and the addAmount\\n         *  Note: The jToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the jToken holds an additional addAmount of cash.\\n         *  doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n         *  it returns the amount actually transferred, in case of a fee.\\n         */\\n\\n        actualAddAmount = doTransferIn(msg.sender, addAmount, isNative);\\n\\n        totalReservesNew = add_(totalReserves, actualAddAmount);\\n\\n        // Store reserves[n+1] = reserves[n] + actualAddAmount\\n        totalReserves = totalReservesNew;\\n\\n        /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n        emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n        /* Return (NO_ERROR, actualAddAmount) */\\n        return (uint256(Error.NO_ERROR), actualAddAmount);\\n    }\\n\\n    /**\\n     * @notice Accrues interest and reduces reserves by transferring to admin\\n     * @param reduceAmount Amount of reduction to reserves\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _reduceReserves(uint256 reduceAmount) external nonReentrant returns (uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n            return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n        }\\n        // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n        return _reduceReservesFresh(reduceAmount);\\n    }\\n\\n    /**\\n     * @notice Reduces reserves by transferring to admin\\n     * @dev Requires fresh interest accrual\\n     * @param reduceAmount Amount of reduction to reserves\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _reduceReservesFresh(uint256 reduceAmount) internal returns (uint256) {\\n        // totalReserves - reduceAmount\\n        uint256 totalReservesNew;\\n\\n        // Check caller is admin\\n        if (msg.sender != admin) {\\n            return fail(Error.UNAUTHORIZED, FailureInfo.REDUCE_RESERVES_ADMIN_CHECK);\\n        }\\n\\n        // We fail gracefully unless market's block timestamp equals current block timestamp\\n        if (accrualBlockTimestamp != getBlockTimestamp()) {\\n            return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n        }\\n\\n        // Fail gracefully if protocol has insufficient underlying cash\\n        if (getCashPrior() < reduceAmount) {\\n            return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n        }\\n\\n        // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n        if (reduceAmount > totalReserves) {\\n            return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n        }\\n\\n        /////////////////////////\\n        // EFFECTS & INTERACTIONS\\n        // (No safe failures beyond this point)\\n\\n        totalReservesNew = sub_(totalReserves, reduceAmount);\\n\\n        // Store reserves[n+1] = reserves[n] - reduceAmount\\n        totalReserves = totalReservesNew;\\n\\n        // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n        // Restrict reducing reserves in native token. Implementations except `JWrappedNative` won't use parameter `isNative`.\\n        doTransferOut(admin, reduceAmount, true);\\n\\n        emit ReservesReduced(admin, reduceAmount, totalReservesNew);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /**\\n     * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n     * @dev Admin function to accrue interest and update the interest rate model\\n     * @param newInterestRateModel the new interest rate model to use\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint256) {\\n        uint256 error = accrueInterest();\\n        if (error != uint256(Error.NO_ERROR)) {\\n            // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n            return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n        }\\n        // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n        return _setInterestRateModelFresh(newInterestRateModel);\\n    }\\n\\n    /**\\n     * @notice updates the interest rate model (*requires fresh interest accrual)\\n     * @dev Admin function to update the interest rate model\\n     * @param newInterestRateModel the new interest rate model to use\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint256) {\\n        // Used to store old model for use in the event that is emitted on success\\n        InterestRateModel oldInterestRateModel;\\n\\n        // Check caller is admin\\n        if (msg.sender != admin) {\\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_INTEREST_RATE_MODEL_OWNER_CHECK);\\n        }\\n\\n        // We fail gracefully unless market's block timestamp equals current block timestamp\\n        if (accrualBlockTimestamp != getBlockTimestamp()) {\\n            return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n        }\\n\\n        // Track the market's current interest rate model\\n        oldInterestRateModel = interestRateModel;\\n\\n        // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n        require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n        // Set the interest rate model to newInterestRateModel\\n        interestRateModel = newInterestRateModel;\\n\\n        // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n        emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n        return uint256(Error.NO_ERROR);\\n    }\\n\\n    /*** Safe Token ***/\\n\\n    /**\\n     * @notice Gets balance of this contract in terms of the underlying\\n     * @dev This excludes the value of the current message, if any\\n     * @return The quantity of underlying owned by this contract\\n     */\\n    function getCashPrior() internal view returns (uint256);\\n\\n    /**\\n     * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n     *  This may revert due to insufficient balance or insufficient allowance.\\n     */\\n    function doTransferIn(\\n        address from,\\n        uint256 amount,\\n        bool isNative\\n    ) internal returns (uint256);\\n\\n    /**\\n     * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\\n     *  If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n     *  If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n     */\\n    function doTransferOut(\\n        address payable to,\\n        uint256 amount,\\n        bool isNative\\n    ) internal;\\n\\n    /**\\n     * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\\n     * @dev Called by both `transfer` and `transferFrom` internally\\n     */\\n    function transferTokens(\\n        address spender,\\n        address src,\\n        address dst,\\n        uint256 tokens\\n    ) internal returns (uint256);\\n\\n    /**\\n     * @notice Get the account's jToken balances\\n     */\\n    function getJTokenBalanceInternal(address account) internal view returns (uint256);\\n\\n    /**\\n     * @notice User supplies assets into the market and receives jTokens in exchange\\n     * @dev Assumes interest has already been accrued up to the current timestamp\\n     */\\n    function mintFresh(\\n        address minter,\\n        uint256 mintAmount,\\n        bool isNative\\n    ) internal returns (uint256, uint256);\\n\\n    /**\\n     * @notice User redeems jTokens in exchange for the underlying asset\\n     * @dev Assumes interest has already been accrued up to the current timestamp\\n     */\\n    function redeemFresh(\\n        address payable redeemer,\\n        uint256 redeemTokensIn,\\n        uint256 redeemAmountIn,\\n        bool isNative\\n    ) internal returns (uint256);\\n\\n    /**\\n     * @notice Transfers collateral tokens (this market) to the liquidator.\\n     * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another JToken.\\n     *  Its absolutely critical to use msg.sender as the seizer jToken and not a parameter.\\n     */\\n    function seizeInternal(\\n        address seizerToken,\\n        address liquidator,\\n        address borrower,\\n        uint256 seizeTokens\\n    ) internal returns (uint256);\\n\\n    /*** Reentrancy Guard ***/\\n\\n    /**\\n     * @dev Prevents a contract from calling itself, directly or indirectly.\\n     */\\n    modifier nonReentrant() {\\n        require(_notEntered, \\\"re-entered\\\");\\n        _notEntered = false;\\n        _;\\n        _notEntered = true; // get a gas-refund post-Istanbul\\n    }\\n}\\n\",\"keccak256\":\"0x7abd886d157d328e0b79cec9db5312927f401d7a1d63a8d9f1132deda3f32766\"},\"contracts/JTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./JoetrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./ERC3156FlashBorrowerInterface.sol\\\";\\n\\ncontract JTokenStorage {\\n    /**\\n     * @dev Guard variable for re-entrancy checks\\n     */\\n    bool internal _notEntered;\\n\\n    /**\\n     * @notice EIP-20 token name for this token\\n     */\\n    string public name;\\n\\n    /**\\n     * @notice EIP-20 token symbol for this token\\n     */\\n    string public symbol;\\n\\n    /**\\n     * @notice EIP-20 token decimals for this token\\n     */\\n    uint8 public decimals;\\n\\n    /**\\n     * @notice Maximum borrow rate that can ever be applied (.0005% / sec)\\n     */\\n\\n    uint256 internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n    /**\\n     * @notice Maximum fraction of interest that can be set aside for reserves\\n     */\\n    uint256 internal constant reserveFactorMaxMantissa = 1e18;\\n\\n    /**\\n     * @notice Administrator for this contract\\n     */\\n    address payable public admin;\\n\\n    /**\\n     * @notice Pending administrator for this contract\\n     */\\n    address payable public pendingAdmin;\\n\\n    /**\\n     * @notice Contract which oversees inter-jToken operations\\n     */\\n    JoetrollerInterface public joetroller;\\n\\n    /**\\n     * @notice Model which tells what the current interest rate should be\\n     */\\n    InterestRateModel public interestRateModel;\\n\\n    /**\\n     * @notice Initial exchange rate used when minting the first JTokens (used when totalSupply = 0)\\n     */\\n    uint256 internal initialExchangeRateMantissa;\\n\\n    /**\\n     * @notice Fraction of interest currently set aside for reserves\\n     */\\n    uint256 public reserveFactorMantissa;\\n\\n    /**\\n     * @notice Block timestamp that interest was last accrued at\\n     */\\n    uint256 public accrualBlockTimestamp;\\n\\n    /**\\n     * @notice Accumulator of the total earned interest rate since the opening of the market\\n     */\\n    uint256 public borrowIndex;\\n\\n    /**\\n     * @notice Total amount of outstanding borrows of the underlying in this market\\n     */\\n    uint256 public totalBorrows;\\n\\n    /**\\n     * @notice Total amount of reserves of the underlying held in this market\\n     */\\n    uint256 public totalReserves;\\n\\n    /**\\n     * @notice Total number of tokens in circulation\\n     */\\n    uint256 public totalSupply;\\n\\n    /**\\n     * @notice Official record of token balances for each account\\n     */\\n    mapping(address => uint256) internal accountTokens;\\n\\n    /**\\n     * @notice Approved token transfer amounts on behalf of others\\n     */\\n    mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n    /**\\n     * @notice Container for borrow balance information\\n     * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n     * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n     */\\n    struct BorrowSnapshot {\\n        uint256 principal;\\n        uint256 interestIndex;\\n    }\\n\\n    /**\\n     * @notice Mapping of account addresses to outstanding borrow balances\\n     */\\n    mapping(address => BorrowSnapshot) internal accountBorrows;\\n}\\n\\ncontract JErc20Storage {\\n    /**\\n     * @notice Underlying asset for this JToken\\n     */\\n    address public underlying;\\n\\n    /**\\n     * @notice Implementation address for this contract\\n     */\\n    address public implementation;\\n}\\n\\ncontract JSupplyCapStorage {\\n    /**\\n     * @notice Internal cash counter for this JToken. Should equal underlying.balanceOf(address(this)) for CERC20.\\n     */\\n    uint256 public internalCash;\\n}\\n\\ncontract JCollateralCapStorage {\\n    /**\\n     * @notice Total number of tokens used as collateral in circulation.\\n     */\\n    uint256 public totalCollateralTokens;\\n\\n    /**\\n     * @notice Record of token balances which could be treated as collateral for each account.\\n     *         If collateral cap is not set, the value should be equal to accountTokens.\\n     */\\n    mapping(address => uint256) public accountCollateralTokens;\\n\\n    /**\\n     * @notice Check if accountCollateralTokens have been initialized.\\n     */\\n    mapping(address => bool) public isCollateralTokenInit;\\n\\n    /**\\n     * @notice Collateral cap for this JToken, zero for no cap.\\n     */\\n    uint256 public collateralCap;\\n}\\n\\n/*** Interface ***/\\n\\ncontract JTokenInterface is JTokenStorage {\\n    /**\\n     * @notice Indicator that this is a JToken contract (for inspection)\\n     */\\n    bool public constant isJToken = true;\\n\\n    /*** Market Events ***/\\n\\n    /**\\n     * @notice Event emitted when interest is accrued\\n     */\\n    event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n    /**\\n     * @notice Event emitted when tokens are minted\\n     */\\n    event Mint(address minter, uint256 mintAmount, uint256 mintTokens);\\n\\n    /**\\n     * @notice Event emitted when tokens are redeemed\\n     */\\n    event Redeem(address redeemer, uint256 redeemAmount, uint256 redeemTokens);\\n\\n    /**\\n     * @notice Event emitted when underlying is borrowed\\n     */\\n    event Borrow(address borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n    /**\\n     * @notice Event emitted when a borrow is repaid\\n     */\\n    event RepayBorrow(\\n        address payer,\\n        address borrower,\\n        uint256 repayAmount,\\n        uint256 accountBorrows,\\n        uint256 totalBorrows\\n    );\\n\\n    /**\\n     * @notice Event emitted when a borrow is liquidated\\n     */\\n    event LiquidateBorrow(\\n        address liquidator,\\n        address borrower,\\n        uint256 repayAmount,\\n        address jTokenCollateral,\\n        uint256 seizeTokens\\n    );\\n\\n    /*** Admin Events ***/\\n\\n    /**\\n     * @notice Event emitted when pendingAdmin is changed\\n     */\\n    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n    /**\\n     * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\\n     */\\n    event NewAdmin(address oldAdmin, address newAdmin);\\n\\n    /**\\n     * @notice Event emitted when joetroller is changed\\n     */\\n    event NewJoetroller(JoetrollerInterface oldJoetroller, JoetrollerInterface newJoetroller);\\n\\n    /**\\n     * @notice Event emitted when interestRateModel is changed\\n     */\\n    event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\\n\\n    /**\\n     * @notice Event emitted when the reserve factor is changed\\n     */\\n    event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n    /**\\n     * @notice Event emitted when the reserves are added\\n     */\\n    event ReservesAdded(address benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n    /**\\n     * @notice Event emitted when the reserves are reduced\\n     */\\n    event ReservesReduced(address admin, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n    /**\\n     * @notice EIP20 Transfer event\\n     */\\n    event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n    /**\\n     * @notice EIP20 Approval event\\n     */\\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n    /**\\n     * @notice Failure event\\n     */\\n    event Failure(uint256 error, uint256 info, uint256 detail);\\n\\n    /*** User Interface ***/\\n\\n    function transfer(address dst, uint256 amount) external returns (bool);\\n\\n    function transferFrom(\\n        address src,\\n        address dst,\\n        uint256 amount\\n    ) external returns (bool);\\n\\n    function approve(address spender, uint256 amount) external returns (bool);\\n\\n    function allowance(address owner, address spender) external view returns (uint256);\\n\\n    function balanceOf(address owner) external view returns (uint256);\\n\\n    function balanceOfUnderlying(address owner) external returns (uint256);\\n\\n    function getAccountSnapshot(address account)\\n        external\\n        view\\n        returns (\\n            uint256,\\n            uint256,\\n            uint256,\\n            uint256\\n        );\\n\\n    function borrowRatePerSecond() external view returns (uint256);\\n\\n    function supplyRatePerSecond() external view returns (uint256);\\n\\n    function totalBorrowsCurrent() external returns (uint256);\\n\\n    function borrowBalanceCurrent(address account) external returns (uint256);\\n\\n    function borrowBalanceStored(address account) public view returns (uint256);\\n\\n    function exchangeRateCurrent() public returns (uint256);\\n\\n    function exchangeRateStored() public view returns (uint256);\\n\\n    function getCash() external view returns (uint256);\\n\\n    function accrueInterest() public returns (uint256);\\n\\n    function seize(\\n        address liquidator,\\n        address borrower,\\n        uint256 seizeTokens\\n    ) external returns (uint256);\\n\\n    /*** Admin Functions ***/\\n\\n    function _setPendingAdmin(address payable newPendingAdmin) external returns (uint256);\\n\\n    function _acceptAdmin() external returns (uint256);\\n\\n    function _setJoetroller(JoetrollerInterface newJoetroller) public returns (uint256);\\n\\n    function _setReserveFactor(uint256 newReserveFactorMantissa) external returns (uint256);\\n\\n    function _reduceReserves(uint256 reduceAmount) external returns (uint256);\\n\\n    function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint256);\\n}\\n\\ncontract JErc20Interface is JErc20Storage {\\n    /*** User Interface ***/\\n\\n    function mint(uint256 mintAmount) external returns (uint256);\\n\\n    function redeem(uint256 redeemTokens) external returns (uint256);\\n\\n    function redeemUnderlying(uint256 redeemAmount) external returns (uint256);\\n\\n    function borrow(uint256 borrowAmount) external returns (uint256);\\n\\n    function repayBorrow(uint256 repayAmount) external returns (uint256);\\n\\n    function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256);\\n\\n    function liquidateBorrow(\\n        address borrower,\\n        uint256 repayAmount,\\n        JTokenInterface jTokenCollateral\\n    ) external returns (uint256);\\n\\n    function _addReserves(uint256 addAmount) external returns (uint256);\\n}\\n\\ncontract JWrappedNativeInterface is JErc20Interface {\\n    /**\\n     * @notice Flash loan fee ratio\\n     */\\n    uint256 public constant flashFeeBips = 8;\\n\\n    /*** Market Events ***/\\n\\n    /**\\n     * @notice Event emitted when a flashloan occured\\n     */\\n    event Flashloan(address indexed receiver, uint256 amount, uint256 totalFee, uint256 reservesFee);\\n\\n    /*** User Interface ***/\\n\\n    function mintNative() external payable returns (uint256);\\n\\n    function redeemNative(uint256 redeemTokens) external returns (uint256);\\n\\n    function redeemUnderlyingNative(uint256 redeemAmount) external returns (uint256);\\n\\n    function borrowNative(uint256 borrowAmount) external returns (uint256);\\n\\n    function repayBorrowNative() external payable returns (uint256);\\n\\n    function repayBorrowBehalfNative(address borrower) external payable returns (uint256);\\n\\n    function liquidateBorrowNative(address borrower, JTokenInterface jTokenCollateral)\\n        external\\n        payable\\n        returns (uint256);\\n\\n    function flashLoan(\\n        ERC3156FlashBorrowerInterface receiver,\\n        address initiator,\\n        uint256 amount,\\n        bytes calldata data\\n    ) external returns (bool);\\n\\n    function _addReservesNative() external payable returns (uint256);\\n}\\n\\ncontract JCapableErc20Interface is JErc20Interface, JSupplyCapStorage {\\n    /**\\n     * @notice Flash loan fee ratio\\n     */\\n    uint256 public constant flashFeeBips = 8;\\n\\n    /*** Market Events ***/\\n\\n    /**\\n     * @notice Event emitted when a flashloan occured\\n     */\\n    event Flashloan(address indexed receiver, uint256 amount, uint256 totalFee, uint256 reservesFee);\\n\\n    /*** User Interface ***/\\n\\n    function gulp() external;\\n}\\n\\ncontract JCollateralCapErc20Interface is JCapableErc20Interface, JCollateralCapStorage {\\n    /*** Admin Events ***/\\n\\n    /**\\n     * @notice Event emitted when collateral cap is set\\n     */\\n    event NewCollateralCap(address token, uint256 newCap);\\n\\n    /**\\n     * @notice Event emitted when user collateral is changed\\n     */\\n    event UserCollateralChanged(address account, uint256 newCollateralTokens);\\n\\n    /*** User Interface ***/\\n\\n    function registerCollateral(address account) external returns (uint256);\\n\\n    function unregisterCollateral(address account) external;\\n\\n    function flashLoan(\\n        ERC3156FlashBorrowerInterface receiver,\\n        address initiator,\\n        uint256 amount,\\n        bytes calldata data\\n    ) external returns (bool);\\n\\n    /*** Admin Functions ***/\\n\\n    function _setCollateralCap(uint256 newCollateralCap) external;\\n}\\n\\ncontract JDelegatorInterface {\\n    /**\\n     * @notice Emitted when implementation is changed\\n     */\\n    event NewImplementation(address oldImplementation, address newImplementation);\\n\\n    /**\\n     * @notice Called by the admin to update the implementation of the delegator\\n     * @param implementation_ The address of the new implementation for delegation\\n     * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n     * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n     */\\n    function _setImplementation(\\n        address implementation_,\\n        bool allowResign,\\n        bytes memory becomeImplementationData\\n    ) public;\\n}\\n\\ncontract JDelegateInterface {\\n    /**\\n     * @notice Called by the delegator on a delegate to initialize it for duty\\n     * @dev Should revert if any issues arise which make it unfit for delegation\\n     * @param data The encoded bytes data for any initialization\\n     */\\n    function _becomeImplementation(bytes memory data) public;\\n\\n    /**\\n     * @notice Called by the delegator on a delegate to forfeit its responsibility\\n     */\\n    function _resignImplementation() public;\\n}\\n\\n/*** External interface ***/\\n\\n/**\\n * @title Flash loan receiver interface\\n */\\ninterface IFlashloanReceiver {\\n    function executeOperation(\\n        address sender,\\n        address underlying,\\n        uint256 amount,\\n        uint256 fee,\\n        bytes calldata params\\n    ) external;\\n}\\n\\ncontract JProtocolSeizeShareStorage {\\n    /**\\n     * @notice Event emitted when the protocol share of seized collateral is changed\\n     */\\n    event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n    /**\\n     * @notice Share of seized collateral that is added to reserves\\n     */\\n    uint256 public protocolSeizeShareMantissa;\\n\\n    /**\\n     * @notice Maximum fraction of seized collateral that can be set aside for reserves\\n     */\\n    uint256 internal constant protocolSeizeShareMaxMantissa = 1e18;\\n}\\n\",\"keccak256\":\"0x4be1f0261842d023b765fda619f3acd153f8e4023f91d5cb05958b049e84ac48\"},\"contracts/JoetrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./JToken.sol\\\";\\nimport \\\"./JoetrollerStorage.sol\\\";\\n\\ncontract JoetrollerInterface {\\n    /// @notice Indicator that this is a Joetroller contract (for inspection)\\n    bool public constant isJoetroller = true;\\n\\n    /*** Assets You Are In ***/\\n\\n    function enterMarkets(address[] calldata jTokens) external returns (uint256[] memory);\\n\\n    function exitMarket(address jToken) external returns (uint256);\\n\\n    /*** Policy Hooks ***/\\n\\n    function mintAllowed(\\n        address jToken,\\n        address minter,\\n        uint256 mintAmount\\n    ) external returns (uint256);\\n\\n    function mintVerify(\\n        address jToken,\\n        address minter,\\n        uint256 mintAmount,\\n        uint256 mintTokens\\n    ) external;\\n\\n    function redeemAllowed(\\n        address jToken,\\n        address redeemer,\\n        uint256 redeemTokens\\n    ) external returns (uint256);\\n\\n    function redeemVerify(\\n        address jToken,\\n        address redeemer,\\n        uint256 redeemAmount,\\n        uint256 redeemTokens\\n    ) external;\\n\\n    function borrowAllowed(\\n        address jToken,\\n        address borrower,\\n        uint256 borrowAmount\\n    ) external returns (uint256);\\n\\n    function borrowVerify(\\n        address jToken,\\n        address borrower,\\n        uint256 borrowAmount\\n    ) external;\\n\\n    function repayBorrowAllowed(\\n        address jToken,\\n        address payer,\\n        address borrower,\\n        uint256 repayAmount\\n    ) external returns (uint256);\\n\\n    function repayBorrowVerify(\\n        address jToken,\\n        address payer,\\n        address borrower,\\n        uint256 repayAmount,\\n        uint256 borrowerIndex\\n    ) external;\\n\\n    function liquidateBorrowAllowed(\\n        address jTokenBorrowed,\\n        address jTokenCollateral,\\n        address liquidator,\\n        address borrower,\\n        uint256 repayAmount\\n    ) external returns (uint256);\\n\\n    function liquidateBorrowVerify(\\n        address jTokenBorrowed,\\n        address jTokenCollateral,\\n        address liquidator,\\n        address borrower,\\n        uint256 repayAmount,\\n        uint256 seizeTokens\\n    ) external;\\n\\n    function seizeAllowed(\\n        address jTokenCollateral,\\n        address jTokenBorrowed,\\n        address liquidator,\\n        address borrower,\\n        uint256 seizeTokens\\n    ) external returns (uint256);\\n\\n    function seizeVerify(\\n        address jTokenCollateral,\\n        address jTokenBorrowed,\\n        address liquidator,\\n        address borrower,\\n        uint256 seizeTokens\\n    ) external;\\n\\n    function transferAllowed(\\n        address jToken,\\n        address src,\\n        address dst,\\n        uint256 transferTokens\\n    ) external returns (uint256);\\n\\n    function transferVerify(\\n        address jToken,\\n        address src,\\n        address dst,\\n        uint256 transferTokens\\n    ) external;\\n\\n    /*** Liquidity/Liquidation Calculations ***/\\n\\n    function liquidateCalculateSeizeTokens(\\n        address jTokenBorrowed,\\n        address jTokenCollateral,\\n        uint256 repayAmount\\n    ) external view returns (uint256, uint256);\\n}\\n\\ninterface JoetrollerInterfaceExtension {\\n    function checkMembership(address account, JToken jToken) external view returns (bool);\\n\\n    function updateJTokenVersion(address jToken, JoetrollerV1Storage.Version version) external;\\n\\n    function flashloanAllowed(\\n        address jToken,\\n        address receiver,\\n        uint256 amount,\\n        bytes calldata params\\n    ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x769609bb58ce98c42d1101190778e5c4b71eba8386f56e0b31c218c9b4d40d6e\"},\"contracts/JoetrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./JToken.sol\\\";\\nimport \\\"./PriceOracle/PriceOracle.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n    /**\\n     * @notice Administrator for this contract\\n     */\\n    address public admin;\\n\\n    /**\\n     * @notice Pending administrator for this contract\\n     */\\n    address public pendingAdmin;\\n\\n    /**\\n     * @notice Active brains of Unitroller\\n     */\\n    address public implementation;\\n\\n    /**\\n     * @notice Pending brains of Unitroller\\n     */\\n    address public pendingImplementation;\\n}\\n\\ncontract JoetrollerV1Storage is UnitrollerAdminStorage {\\n    /**\\n     * @notice Oracle which gives the price of any given asset\\n     */\\n    PriceOracle public oracle;\\n\\n    /**\\n     * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n     */\\n    uint256 public closeFactorMantissa;\\n\\n    /**\\n     * @notice Multiplier representing the discount on collateral that a liquidator receives\\n     */\\n    uint256 public liquidationIncentiveMantissa;\\n\\n    /**\\n     * @notice Per-account mapping of \\\"assets you are in\\\"\\n     */\\n    mapping(address => JToken[]) public accountAssets;\\n\\n    enum Version {\\n        VANILLA,\\n        COLLATERALCAP,\\n        WRAPPEDNATIVE\\n    }\\n\\n    struct Market {\\n        /// @notice Whether or not this market is listed\\n        bool isListed;\\n        /**\\n         * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n         *  For instance, 0.9 to allow borrowing 90% of collateral value.\\n         *  Must be between 0 and 1, and stored as a mantissa.\\n         */\\n        uint256 collateralFactorMantissa;\\n        /// @notice Per-market mapping of \\\"accounts in this asset\\\"\\n        mapping(address => bool) accountMembership;\\n        /// @notice JToken version\\n        Version version;\\n    }\\n\\n    /**\\n     * @notice Official mapping of jTokens -> Market metadata\\n     * @dev Used e.g. to determine if a market is supported\\n     */\\n    mapping(address => Market) public markets;\\n\\n    /**\\n     * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n     *  Actions which allow users to remove their own assets cannot be paused.\\n     *  Liquidation / seizing / transfer can only be paused globally, not by market.\\n     */\\n    address public pauseGuardian;\\n    bool public _mintGuardianPaused;\\n    bool public _borrowGuardianPaused;\\n    bool public transferGuardianPaused;\\n    bool public seizeGuardianPaused;\\n    mapping(address => bool) public mintGuardianPaused;\\n    mapping(address => bool) public borrowGuardianPaused;\\n\\n    /// @notice A list of all markets\\n    JToken[] public allMarkets;\\n\\n    // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n    address public borrowCapGuardian;\\n\\n    // @notice Borrow caps enforced by borrowAllowed for each jToken address. Defaults to zero which corresponds to unlimited borrowing.\\n    mapping(address => uint256) public borrowCaps;\\n\\n    // @notice The supplyCapGuardian can set supplyCaps to any number for any market. Lowering the supply cap could disable supplying to the given market.\\n    address public supplyCapGuardian;\\n\\n    // @notice Supply caps enforced by mintAllowed for each jToken address. Defaults to zero which corresponds to unlimited supplying.\\n    mapping(address => uint256) public supplyCaps;\\n\\n    // @notice creditLimits allowed specific protocols to borrow and repay without collateral.\\n    mapping(address => uint256) public creditLimits;\\n\\n    // @notice flashloanGuardianPaused can pause flash loan as a safety mechanism.\\n    mapping(address => bool) public flashloanGuardianPaused;\\n\\n    // @notice rewardDistributor The module that handles reward distribution.\\n    address payable public rewardDistributor;\\n}\\n\",\"keccak256\":\"0xb0246b1b9de755dd19a100551d1ddf7e4def8b8dedadbdbd9694fc39177f17e2\"},\"contracts/PriceOracle/PriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"../JToken.sol\\\";\\n\\ncontract PriceOracle {\\n    /**\\n     * @notice Get the underlying price of a jToken asset\\n     * @param jToken The jToken to get the underlying price of\\n     * @return The underlying asset price mantissa (scaled by 1e18).\\n     *  Zero means the price is unavailable.\\n     */\\n    function getUnderlyingPrice(JToken jToken) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xa6007c9a8daf4fe66121b677d8bb75ba995977d664673fd72367f50460d8b99f\"}},\"version\":1}",
  "bytecode": "0x608060405234801561001057600080fd5b50615cb880620000216000396000f3fe608060405234801561001057600080fd5b50600436106103fc5760003560e01c806381cf00eb11610215578063b2a02ff111610125578063db006a75116100b8578063f2b3abbd11610087578063f2b3abbd14610de8578063f3fdb15a14610e0e578063f5e3c46214610e16578063f851a44014610e4c578063fca7820b14610e54576103fc565b8063db006a7514610d8d578063dd62ed3e14610daa578063e9c714f214610dd8578063ea11eea414610de0576103fc565b8063c5ebeaec116100f4578063c5ebeaec14610d3a578063cfa9920114610d57578063d240d64a14610d5f578063d2bb18e914610d85576103fc565b8063b2a02ff114610c8a578063b71d1a0c14610cc0578063bd6d894d14610ce6578063c37f68e214610cee576103fc565b806395d89b41116101a8578063a6afed9511610177578063a6afed9514610c29578063a7af467a14610c31578063a9059cbb14610c4e578063aa5af0fd14610c7a578063b1d3897414610c82576103fc565b806395d89b4114610a9057806395dd919314610a9857806399d8c1b414610abe578063a0712d6814610c0c576103fc565b80638897bd85116101e45780638897bd8514610a345780638b35776b14610a5a5780638f840ddd14610a8057806394909e6214610a88576103fc565b806381cf00eb146109b757806383030846146109d4578063852a12e3146109f157806385d8a2e614610a0e576103fc565b80633af9e6691161031057806356e67728116102a35780636330533c116102725780636330533c146109715780636752e702146109795780636f307dc31461098157806370a082311461098957806373acee98146109af576103fc565b806356e677281461081a5780635c60da1b146108be5780635cffe9de146108c6578063601a0bf114610954576103fc565b8063432f4b2d116102df578063432f4b2d146107bf57806347bd3718146107e557806350f6e082146107ed5780635260975014610812576103fc565b80633af9e6691461076c5780633b1d21a2146107925780633e9410101461079a578063406de0b6146107b7576103fc565b8063182df0f51161039357806323b872dd1161036257806323b872dd146106c0578063242c127c146106f65780632608f818146106fe578063267822471461072a578063313ce5671461074e576103fc565b8063182df0f51461055257806319a4dd3c1461055a5780631a31d4651461056257806322abdbf5146106b8576103fc565b8063153ab505116103cf578063153ab50514610512578063173b99041461051c57806317bfdfbc1461052457806318160ddd1461054a576103fc565b806306fdde0314610401578063095ea7b31461047e5780630e752702146104be5780630f3e4e11146104ed575b600080fd5b610409610e71565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561044357818101518382015260200161042b565b50505050905090810190601f1680156104705780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104aa6004803603604081101561049457600080fd5b506001600160a01b038135169060200135610efe565b604080519115158252519081900360200190f35b6104db600480360360208110156104d457600080fd5b5035610f6b565b60408051918252519081900360200190f35b6104db6004803603604081101561050357600080fd5b50803590602001351515610f83565b61051a611068565b005b6104db6110b8565b6104db6004803603602081101561053a57600080fd5b50356001600160a01b03166110be565b6104db61117e565b6104db611184565b6104db611194565b61051a600480360360e081101561057857600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b8111156105ba57600080fd5b8201836020820111156105cc57600080fd5b803590602001918460018302840111600160201b831117156105ed57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561063f57600080fd5b82018360208201111561065157600080fd5b803590602001918460018302840111600160201b8311171561067257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061119a9050565b6104db611239565b6104aa600480360360608110156106d657600080fd5b506001600160a01b0381358116916020810135909116906040013561123f565b6104db6112b1565b6104db6004803603604081101561071457600080fd5b506001600160a01b038135169060200135611356565b61073261136e565b604080516001600160a01b039092168252519081900360200190f35b61075661137d565b6040805160ff9092168252519081900360200190f35b6104db6004803603602081101561078257600080fd5b50356001600160a01b0316611386565b6104db6113d3565b6104db600480360360208110156107b057600080fd5b50356113dd565b6104aa6113ea565b6104db600480360360208110156107d557600080fd5b50356001600160a01b03166113ef565b6104db611543565b6104db6004803603604081101561080357600080fd5b50803590602001351515611549565b6104db6115f8565b61051a6004803603602081101561083057600080fd5b810190602081018135600160201b81111561084a57600080fd5b82018360208201111561085c57600080fd5b803590602001918460018302840111600160201b8311171561087d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061168d945050505050565b610732611754565b6104aa600480360360808110156108dc57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561091657600080fd5b82018360208201111561092857600080fd5b803590602001918460018302840111600160201b8311171561094957600080fd5b509092509050611763565b6104db6004803603602081101561096a57600080fd5b5035611ca7565b610732611d42565b6104db611d51565b610732611d57565b6104db6004803603602081101561099f57600080fd5b50356001600160a01b0316611d66565b6104db611d81565b61051a600480360360208110156109cd57600080fd5b5035611e37565b6104db600480360360208110156109ea57600080fd5b5035611ec8565b6104db60048036036020811015610a0757600080fd5b5035611f46565b6104aa60048036036020811015610a2457600080fd5b50356001600160a01b0316611f53565b6104db60048036036020811015610a4a57600080fd5b50356001600160a01b0316611f68565b61051a60048036036020811015610a7057600080fd5b50356001600160a01b0316611ff6565b6104db61206f565b61051a612075565b61040961210a565b6104db60048036036020811015610aae57600080fd5b50356001600160a01b0316612162565b61051a600480360360c0811015610ad457600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610b0e57600080fd5b820183602082011115610b2057600080fd5b803590602001918460018302840111600160201b83111715610b4157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b9357600080fd5b820183602082011115610ba557600080fd5b803590602001918460018302840111600160201b83111715610bc657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061216d9050565b6104db60048036036020811015610c2257600080fd5b5035612354565b6104db612362565b6104db60048036036020811015610c4757600080fd5b5035612572565b6104aa60048036036040811015610c6457600080fd5b506001600160a01b038135169060200135612664565b6104db6126d6565b6104db6126dc565b6104db60048036036060811015610ca057600080fd5b506001600160a01b0381358116916020810135909116906040013561274a565b6104db60048036036020811015610cd657600080fd5b50356001600160a01b03166127bb565b6104db612847565b610d1460048036036020811015610d0457600080fd5b50356001600160a01b0316612903565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6104db60048036036020811015610d5057600080fd5b503561293f565b6104db61294c565b6104db60048036036020811015610d7557600080fd5b50356001600160a01b0316612952565b6104db612964565b6104db60048036036020811015610da357600080fd5b503561296a565b6104db60048036036040811015610dc057600080fd5b506001600160a01b0381358116916020013516612977565b6104db6129a2565b6104db612aa5565b6104db60048036036020811015610dfe57600080fd5b50356001600160a01b0316612aaa565b610732612ae4565b6104db60048036036060811015610e2c57600080fd5b506001600160a01b03813581169160208101359160409091013516612af3565b610732612b0d565b6104db60048036036020811015610e6a57600080fd5b5035612b21565b60018054604080516020600284861615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610ef65780601f10610ecb57610100808354040283529160200191610ef6565b820191906000526020600020905b815481529060010190602001808311610ed957829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855290835281842086905581518681529151939493909284927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a360019150505b92915050565b600080610f79836000612b9f565b509150505b919050565b60008060008315610fb457610f9f610f99612c4b565b86612c51565b9150610fad600b5486612c87565b9050610fd6565b610fc5610fbf612c4b565b86612c87565b9150610fd3600b5486612c51565b90505b600654600c54604080516315f2405360e01b815260048101869052602481018590526044810192909252516001600160a01b03909216916315f2405391606480820192602092909190829003018186803b15801561103357600080fd5b505afa158015611047573d6000803e3d6000fd5b505050506040513d602081101561105d57600080fd5b505195945050505050565b60035461010090046001600160a01b031633146110b65760405162461bcd60e51b815260040180806020018281038252602d815260200180615b2f602d913960400191505060405180910390fd5b565b60085481565b6000805460ff16611103576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611115612362565b14611160576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b61116982612162565b90505b6000805460ff19166001179055919050565b600d5481565b600061118e612cc1565b90505b90565b60145481565b6111a886868686868661216d565b601180546001600160a01b0319166001600160a01b038981169190911791829055604080516318160ddd60e01b8152905192909116916318160ddd91600480820192602092909190829003018186803b15801561120457600080fd5b505afa158015611218573d6000803e3d6000fd5b505050506040513d602081101561122e57600080fd5b505050505050505050565b60135481565b6000805460ff16611284576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561129a33868686612d27565b1490506000805460ff191660011790559392505050565b600554604080516358d5bc7360e11b81523060048201526000602482018190526044820181905260806064830152608482018190529151919283926001600160a01b039091169163b1ab78e69160c4808301926020929190829003018186803b15801561131d57600080fd5b505afa158015611331573d6000803e3d6000fd5b505050506040513d602081101561134757600080fd5b50511561118e57610f65612c4b565b60008061136584846000613074565b50949350505050565b6004546001600160a01b031681565b60035460ff1681565b60006113906158db565b60405180602001604052806113a3612847565b90526001600160a01b0384166000908152600e60205260409020549091506113cc908290613121565b9392505050565b600061118e612c4b565b6000610f65826000613140565b600181565b60035460009061010090046001600160a01b0316331461141c57611415600160296131de565b9050610f7e565b600554604080516340e6dcc560e01b815290516001600160a01b03928316928516916340e6dcc5916004808301926020929190829003018186803b15801561146357600080fd5b505afa158015611477573d6000803e3d6000fd5b505050506040513d602081101561148d57600080fd5b50516114e0576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517f17d6db5ffe5a3d1c3d7a98194dca4f7d808d621e6ff9077ed574513d553a2a859281900390910190a160006113cc565b600b5481565b600080600083156115745761155f610f99612c4b565b915061156d600b5486612c87565b9050611590565b61157f610fbf612c4b565b915061158d600b5486612c51565b90505b600654600c5460085460408051635c0b440b60e11b8152600481018790526024810186905260448101939093526064830191909152516001600160a01b039092169163b816881691608480820192602092909190829003018186803b15801561103357600080fd5b6006546000906001600160a01b03166315f24053611614612c4b565b600b54600c546040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b15801561165c57600080fd5b505afa158015611670573d6000803e3d6000fd5b505050506040513d602081101561168657600080fd5b5051905090565b60035461010090046001600160a01b031633146116db5760405162461bcd60e51b815260040180806020018281038252602d815260200180615c0b602d913960400191505060405180910390fd5b6116e3613244565b601355600554604080516303c03f0f60e01b81523060048201526001602482015290516001600160a01b03909216916303c03f0f9160448082019260009290919082900301818387803b15801561173957600080fd5b505af115801561174d573d6000803e3d6000fd5b5050505050565b6012546001600160a01b031681565b6000805460ff166117a8576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19169055836117ee5760405162461bcd60e51b815260040180806020018281038252602c815260200180615c58602c913960400191505060405180910390fd5b60006117f8612362565b14611843576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b6005546040516358d5bc7360e11b815230600482018181526001600160a01b038a81166024850152604484018990526080606485019081526084850188905294169363b1ab78e6938b928a928a928a92919060a401848480828437600081840152601f19601f820116905080830192505050965050505050505060206040518083038186803b1580156118d557600080fd5b505afa1580156118e9573d6000803e3d6000fd5b505050506040513d60208110156118ff57600080fd5b5051611948576040805162461bcd60e51b8152602060048201526013602482015272199b185cda1b1bd85b881a5cc81c185d5cd959606a1b604482015290519081900360640190fd5b6000611952613244565b9050600061195e612c4b565b9050858110156119ae576040805162461bcd60e51b8152602060048201526016602482015275494e53554646494349454e545f4c495155494449545960501b604482015290519081900360640190fd5b6000306001600160a01b031663a7af467a886040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156119f457600080fd5b505afa158015611a08573d6000803e3d6000fd5b505050506040513d6020811015611a1e57600080fd5b50519050611a2e898860006132c4565b611a3a600b5488612c51565b600b55604051806029615b5c82396040519081900360290181206011546323e30c8b60e01b83526001600160a01b038c81166004850190815291811660248501819052604485018d90526064850187905260a06084860190815260a486018c9052939550908e16936323e30c8b938e938e9289928f928f9290919060c401848480828437600081840152601f19601f820116905080830192505050975050505050505050602060405180830381600087803b158015611af857600080fd5b505af1158015611b0c573d6000803e3d6000fd5b505050506040513d6020811015611b2257600080fd5b505114611b76576040805162461bcd60e51b815260206004820152601960248201527f49455243333135363a2043616c6c6261636b206661696c656400000000000000604482015290519081900360640190fd5b6000611b828883612c51565b9050611b908a8260006133cb565b506000611b9b613244565b9050611ba78584612c51565b8114611bf1576040805162461bcd60e51b8152602060048201526014602482015273109053105390d157d25390d3d394d254d511539560621b604482015290519081900360640190fd5b6000611c0d604051806020016040528060085481525085613121565b9050611c1b600c5482612c51565b600c55611c288585612c51565b601355600b54611c38908b612c87565b600b55604080518b81526020810186905280820183905290516001600160a01b038e16917f33c8e097c526683cbdb29adf782fac95e9d0fbe0ed635c13d8c75fdf726557d9919081900360600190a2600196505050505050506000805460ff1916600117905595945050505050565b6000805460ff16611cec576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611cfe612362565b90508015611d2457611d1c816010811115611d1557fe5b601d6131de565b91505061116c565b611d2d836135dc565b9150506000805460ff19166001179055919050565b6005546001600160a01b031681565b60185481565b6011546001600160a01b031681565b6001600160a01b03166000908152600e602052604090205490565b6000805460ff16611dc6576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611dd8612362565b14611e23576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b50600b546000805460ff1916600117905590565b60035461010090046001600160a01b03163314611e855760405162461bcd60e51b8152600401808060200182810382526021815260200180615abc6021913960400191505060405180910390fd5b6017819055604080513081526020810183905281517f01b7c780e0f385803fe80cbe0efc086d13b8eb443a2ce43e2061fd92bc0e34f1929181900390910190a150565b6000805460ff16611f0d576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611f1f612362565b90508015611f3d57611d1c816010811115611f3657fe5b60396131de565b611d2d836136da565b6000610f65826000613782565b60166020526000908152604090205460ff1681565b6000611f738261381a565b6005546001600160a01b03163314611fbc5760405162461bcd60e51b8152600401808060200182810382526030815260200180615aff6030913960400191505060405180910390fd5b6001600160a01b0382166000908152600e60209081526040808320546015909252822054611fea9190612c87565b90506113cc838261395c565b611fff8161381a565b6005546001600160a01b031633146120485760405162461bcd60e51b8152600401808060200182810382526032815260200180615ba56032913960400191505060405180910390fd5b6001600160a01b03811660009081526015602052604090205461206c908290613aa7565b50565b600c5481565b60005460ff166120b9576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556120cb613244565b905060006120d7612c4b565b905060006120e58383612c87565b90506120f3600c5482612c51565b600c5550506013556000805460ff19166001179055565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610ef65780601f10610ecb57610100808354040283529160200191610ef6565b6000610f6582613bfe565b60035461010090046001600160a01b031633146121bb5760405162461bcd60e51b8152600401808060200182810382526024815260200180615a136024913960400191505060405180910390fd5b6009541580156121cb5750600a54155b6122065760405162461bcd60e51b8152600401808060200182810382526023815260200180615a696023913960400191505060405180910390fd5b6007849055836122475760405162461bcd60e51b8152600401808060200182810382526030815260200180615a8c6030913960400191505060405180910390fd5b6000612252876113ef565b905080156122a7576040805162461bcd60e51b815260206004820152601960248201527f73657474696e67206a6f6574726f6c6c6572206661696c656400000000000000604482015290519081900360640190fd5b6122af613c53565b600955670de0b6b3a7640000600a556122c786613c57565b905080156123065760405162461bcd60e51b8152600401808060200182810382526022815260200180615add6022913960400191505060405180910390fd5b83516123199060019060208701906158ee565b50825161232d9060029060208601906158ee565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b600080610f79836000613dcc565b60008061236d613c53565b6009549091508082141561238657600092505050611191565b6000612390612c4b565b600b54600c54600a54600654604080516315f2405360e01b815260048101879052602481018690526044810185905290519596509394929391926000926001600160a01b03909216916315f24053916064808301926020929190829003018186803b1580156123fe57600080fd5b505afa158015612412573d6000803e3d6000fd5b505050506040513d602081101561242857600080fd5b5051905065048c27395000811115612487576040805162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c79206869676800000000604482015290519081900360640190fd5b60006124938888612c87565b905061249d6158db565b6124b560405180602001604052808581525083613e4e565b905060006124c38288613121565b905060006124d18289612c51565b905060006124f06040518060200160405280600854815250848a613e78565b905060006124ff85898a613e78565b60098e9055600a819055600b849055600c839055604080518d8152602081018790528082018390526060810186905290519192507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc04919081900360800190a160009d505050505050505050505050505090565b600554604080516358d5bc7360e11b8152306004820152600060248201819052604482018590526080606483015260848201819052915191926001600160a01b03169163b1ab78e69160c480820192602092909190829003018186803b1580156125db57600080fd5b505afa1580156125ef573d6000803e3d6000fd5b505050506040513d602081101561260557600080fd5b505161264e576040805162461bcd60e51b8152602060048201526013602482015272199b185cda1b1bd85b881a5cc81c185d5cd959606a1b604482015290519081900360640190fd5b610f6561265c836008613ea0565b612710613ee2565b6000805460ff166126a9576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556126bf33338686612d27565b1490505b6000805460ff1916600117905592915050565b600a5481565b6006546000906001600160a01b031663b81688166126f8612c4b565b600b54600c546008546040518563ffffffff1660e01b81526004018085815260200184815260200183815260200182815260200194505050505060206040518083038186803b15801561165c57600080fd5b6000805460ff1661278f576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191690556127a533858585613f15565b90506000805460ff191660011790559392505050565b60035460009061010090046001600160a01b031633146127e1576114156001602f6131de565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a160006113cc565b6000805460ff1661288c576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561289e612362565b146128e9576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b6128f1611184565b90506000805460ff1916600117905590565b60008060008060006129148661425c565b9050600061292187613bfe565b9050600061292d612cc1565b90506000989297509095509350915050565b6000610f658260006142bb565b60095481565b60156020526000908152604090205481565b60175481565b6000610f6582600061433b565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6004546000906001600160a01b0316331415806129bd575033155b156129d5576129ce600160006131de565b9050611191565b60038054600480546001600160a01b03818116610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401528351909391927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600454604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160009250505090565b600881565b600080612ab5612362565b90508015612adb57612ad3816010811115612acc57fe5b602a6131de565b915050610f7e565b6113cc83613c57565b6006546001600160a01b031681565b600080612b0385858560006143b6565b5095945050505050565b60035461010090046001600160a01b031681565b6000805460ff16612b66576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612b78612362565b90508015612b9657611d1c816010811115612b8f57fe5b60306131de565b611d2d836144ea565b60008054819060ff16612be6576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612bf8612362565b90508015612c2357612c16816010811115612c0f57fe5b60236131de565b925060009150612c359050565b612c2f33338787614592565b92509250505b6000805460ff1916600117905590939092509050565b60135490565b60006113cc8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250614842565b60006113cc8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b8152506148d4565b600d5460009080612cd6575050600754611191565b6000612ce0612c4b565b90506000612cfb612cf383600b54612c51565b600c54612c87565b90506000612d178260405180602001604052808781525061492e565b94506111919350505050565b5090565b6000612d328461381a565b612d3b8361381a565b6001600160a01b0384166000908152600e60209081526040808320546015909252822054612d699190612c87565b9050600081841115612d7a57508083035b600554604080516317b9b84b60e31b81523060048201526001600160a01b0389811660248301528881166044830152606482018590529151600093929092169163bdcdc2589160848082019260209290919082900301818787803b158015612de157600080fd5b505af1158015612df5573d6000803e3d6000fd5b505050506040513d6020811015612e0b57600080fd5b505190508015612e2c57612e22600360348361494c565b935050505061306c565b856001600160a01b0316876001600160a01b03161415612e5257612e22600260356131de565b60006001600160a01b038981169089161415612e715750600019612e99565b506001600160a01b038088166000908152600f60209081526040808320938c16835292905220545b6001600160a01b0388166000908152600e6020526040902054612ebc9087612c87565b6001600160a01b03808a166000908152600e60205260408082209390935590891681522054612eeb9087612c51565b6001600160a01b0388166000908152600e60205260409020558215612fef576001600160a01b038816600090815260156020526040902054612f2d9084612c87565b6001600160a01b03808a166000908152601560205260408082209390935590891681522054612f5c9084612c51565b6001600160a01b03808916600090815260156020908152604080832094909455918b1680825290839020548351918252918101919091528151600080516020615c38833981519152929181900390910190a16001600160a01b038716600081815260156020908152604091829020548251938452908301528051600080516020615c388339815191529281900390910190a15b6000198114613029576130028187612c87565b6001600160a01b03808a166000908152600f60209081526040808320938e16835292905220555b866001600160a01b0316886001600160a01b0316600080516020615b85833981519152886040518082815260200191505060405180910390a360005b9450505050505b949350505050565b60008054819060ff166130bb576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556130cd612362565b905080156130f8576130eb8160108111156130e457fe5b60226131de565b92506000915061310a9050565b61310433878787614592565b92509250505b6000805460ff191660011790559094909350915050565b600061312b6158db565b6131358484613e4e565b905061306c816149b2565b6000805460ff16613185576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155613197612362565b905080156131bd576131b58160108111156131ae57fe5b60366131de565b9150506126c3565b6131c784846149c1565b509150506000805460ff1916600117905592915050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601081111561320d57fe5b83603c81111561321957fe5b604080519283526020830191909152600082820152519081900360600190a18260108111156113cc57fe5b601154604080516370a0823160e01b815230600482015290516000926001600160a01b03169182916370a0823191602480820192602092909190829003018186803b15801561329257600080fd5b505afa1580156132a6573d6000803e3d6000fd5b505050506040513d60208110156132bc57600080fd5b505191505090565b6011546040805163a9059cbb60e01b81526001600160a01b0386811660048301526024820186905291519190921691829163a9059cbb9160448082019260009290919082900301818387803b15801561331c57600080fd5b505af1158015613330573d6000803e3d6000fd5b5050505060003d6000811461334c576020811461335657600080fd5b6000199150613362565b60206000803e60005191505b50806133b5576040805162461bcd60e51b815260206004820152601960248201527f544f4b454e5f5452414e534645525f4f55545f4641494c454400000000000000604482015290519081900360640190fd5b6133c160135485612c87565b6013555050505050565b601154604080516370a0823160e01b815230600482015290516000926001600160a01b031691839183916370a08231916024808301926020929190829003018186803b15801561341a57600080fd5b505afa15801561342e573d6000803e3d6000fd5b505050506040513d602081101561344457600080fd5b5051604080516323b872dd60e01b81526001600160a01b038981166004830152306024830152604482018990529151929350908416916323b872dd9160648082019260009290919082900301818387803b1580156134a157600080fd5b505af11580156134b5573d6000803e3d6000fd5b5050505060003d600081146134d157602081146134db57600080fd5b60001991506134e7565b60206000803e60005191505b508061353a576040805162461bcd60e51b815260206004820152601860248201527f544f4b454e5f5452414e534645525f494e5f4641494c45440000000000000000604482015290519081900360640190fd5b601154604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561358557600080fd5b505afa158015613599573d6000803e3d6000fd5b505050506040513d60208110156135af57600080fd5b5051905060006135bf8285612c87565b90506135cd60135482612c51565b60135598975050505050505050565b600354600090819061010090046001600160a01b0316331461360457612ad36001601e6131de565b61360c613c53565b6009541461362057612ad3600a60206131de565b82613629612c4b565b101561363b57612ad3600e601f6131de565b600c5483111561365157612ad3600260216131de565b61365d600c5484612c87565b600c8190556003549091506136829061010090046001600160a01b03168460016132c4565b600354604080516101009092046001600160a01b0316825260208201859052818101839052517f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e916060908290030190a160006113cc565b60035460009061010090046001600160a01b03163314613700576114156001603a6131de565b613708613c53565b6009541461371c57611415600a603b6131de565b670de0b6b3a7640000821115613738576114156002603c6131de565b6018805490839055604080518281526020810185905281517ff5815f353a60e815cce7553e4f60c533a59d26b1b5504ea4b6db8d60da3e4da2929181900390910190a160006113cc565b6000805460ff166137c7576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556137d9612362565b905080156137f7576131b58160108111156137f057fe5b60196131de565b6138043360008686614a5f565b9150506000805460ff1916600117905592915050565b6001600160a01b03811660009081526016602052604090205460ff1661206c576005546040805163929fe9a160e01b81526001600160a01b0384811660048301523060248301529151919092169163929fe9a1916044808301926020929190829003018186803b15801561388d57600080fd5b505afa1580156138a1573d6000803e3d6000fd5b505050506040513d60208110156138b757600080fd5b505115613936576001600160a01b0381166000908152600e60208181526040808420546015835293208390556014549190526138f291612c51565b6014556001600160a01b038116600081815260156020908152604091829020548251938452908301528051600080516020615c388339815191529281900390910190a15b6001600160a01b0381166000908152601660205260409020805460ff1916600117905550565b60008061396b60145484612c51565b90506017546000148061398c57506017541580159061398c57506017548111155b15613a075760148190556001600160a01b0384166000908152601560205260409020546139b99084612c51565b6001600160a01b03851660008181526015602090815260409182902084905581519283528201929092528151600080516020615c38833981519152929181900390910190a182915050610f65565b6014546017541115613a9d576000613a23601754601454612c87565b6017546014556001600160a01b038616600090815260156020526040902054909150613a4f9082612c51565b6001600160a01b03861660008181526015602090815260409182902084905581519283528201929092528151600080516020615c38833981519152929181900390910190a19150610f659050565b5060009392505050565b6005546040805163eabe7d9160e01b81523060048201526001600160a01b038581166024830152604482018590529151919092169163eabe7d919160648083019260209291908290030181600087803b158015613b0357600080fd5b505af1158015613b17573d6000803e3d6000fd5b505050506040513d6020811015613b2d57600080fd5b505115613b78576040805162461bcd60e51b81526020600482015260146024820152733537b2ba3937b63632b9103932b532b1ba34b7b760611b604482015290519081900360640190fd5b80613b8257613bfa565b613b8e60145482612c87565b6014556001600160a01b038216600090815260156020526040902054613bb49082612c87565b6001600160a01b03831660008181526015602090815260409182902084905581519283528201929092528151600080516020615c38833981519152929181900390910190a15b5050565b6001600160a01b03811660009081526010602052604081208054613c26576000915050610f7e565b6000613c388260000154600a54613ea0565b90506000613c4a828460010154613ee2565b95945050505050565b4290565b600354600090819061010090046001600160a01b03163314613c7f57612ad36001602c6131de565b613c87613c53565b60095414613c9b57612ad3600a602b6131de565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b158015613cec57600080fd5b505afa158015613d00573d6000803e3d6000fd5b505050506040513d6020811015613d1657600080fd5b5051613d69576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269281900390910190a160006113cc565b60008054819060ff16613e13576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155613e25612362565b90508015613e4357612c16816010811115613e3c57fe5b60146131de565b612c2f338686614dd8565b613e566158db565b6040518060200160405280613e6f856000015185613ea0565b90529392505050565b6000613e826158db565b613e8c8585613e4e565b9050613c4a613e9a826149b2565b84612c51565b60006113cc83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f7700000000000000000081525061507e565b60006113cc83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b8152506150f4565b6000613f208461381a565b613f298361381a565b6005546040805163d02f735160e01b81523060048201526001600160a01b03888116602483015287811660448301528681166064830152608482018690529151600093929092169163d02f73519160a48082019260209290919082900301818787803b158015613f9857600080fd5b505af1158015613fac573d6000803e3d6000fd5b505050506040513d6020811015613fc257600080fd5b505190508015613fe157613fd9600360118361494c565b91505061306c565b82613fed576000613fd9565b846001600160a01b0316846001600160a01b0316141561401357613fd9600660126131de565b600061402f846040518060200160405280601854815250615156565b9050600061403d8583612c87565b90506000614049612cc1565b9050600061406560405180602001604052808481525085613121565b6001600160a01b0389166000908152600e602052604090205490915061408b9088612c87565b6001600160a01b03808a166000908152600e602052604080822093909355908b16815220546140ba9084612c51565b6001600160a01b03808b166000908152600e6020908152604080832094909455918b168152601590915220546140f09088612c87565b6001600160a01b03808a1660009081526015602052604080822093909355908b168152205461411f9084612c51565b6001600160a01b038a16600090815260156020526040902055600c546141459082612c51565b600c55600d546141559085612c87565b600d556040805188815290516001600160a01b03808c1692908b1691600080516020615b858339815191529181900360200190a36001600160a01b038816600081815260156020908152604091829020548251938452908301528051600080516020615c388339815191529281900390910190a16001600160a01b038916600081815260156020908152604091829020548251938452908301528051600080516020615c388339815191529281900390910190a1600c54604080513081526020810184905280820192909252517fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc59181900360600190a160009a9950505050505050505050565b6001600160a01b03811660009081526016602052604081205460ff161561429c57506001600160a01b038116600090815260156020526040902054610f7e565b506001600160a01b0381166000908152600e6020526040902054610f7e565b6000805460ff16614300576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155614312612362565b90508015614330576131b581601081111561432957fe5b60026131de565b61380433858561517e565b6000805460ff16614380576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155614392612362565b905080156143a9576131b58160108111156137f057fe5b6138043385600086614a5f565b60008054819060ff166143fd576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561440f612362565b9050801561443a5761442d81601081111561442657fe5b60076131de565b9250600091506144d29050565b846001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561447557600080fd5b505af1158015614489573d6000803e3d6000fd5b505050506040513d602081101561449f57600080fd5b5051905080156144bf5761442d8160108111156144b857fe5b60086131de565b6144cc3388888888615367565b92509250505b6000805460ff19166001179055909590945092505050565b60035460009061010090046001600160a01b0316331461451057611415600160316131de565b614518613c53565b6009541461452c57611415600a60326131de565b670de0b6b3a764000082111561454857611415600260336131de565b6008805490839055604080518281526020810185905281517faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460929181900390910190a160006113cc565b60055460408051631200453160e11b81523060048201526001600160a01b0387811660248301528681166044830152606482018690529151600093849384939116916324008a629160848082019260209290919082900301818787803b1580156145fb57600080fd5b505af115801561460f573d6000803e3d6000fd5b505050506040513d602081101561462557600080fd5b5051905080156146495761463c600360248361494c565b9250600091506148399050565b846146835761465786613bfe565b6001600160a01b0387166000908152601060205260408120918255600a5460019092019190915561463c565b61468b613c53565b6009541461469f5761463c600a60256131de565b6146a7615968565b6001600160a01b03871660009081526010602052604090206001015460608201526146d187613bfe565b60808201526000198614156146ef57608081015160408201526146f7565b604081018690525b614706888260400151876133cb565b60e08201819052608082015161471b91612c87565b60a0820152600b5460e08201516147329190612c87565b8160c00181815250508060a0015160106000896001600160a01b03166001600160a01b0316815260200190815260200160002060000181905550600a5460106000896001600160a01b03166001600160a01b03168152602001908152602001600020600101819055508060c00151600b819055507f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a188888360e001518460a001518560c0015160405180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018381526020018281526020019550505050505060405180910390a160e00151600093509150505b94509492505050565b600083830182858210156113655760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614899578181015183820152602001614881565b50505050905090810190601f1680156148c65780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b600081848411156149265760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614899578181015183820152602001614881565b505050900390565b60006113cc61494584670de0b6b3a7640000613ea0565b8351613ee2565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601081111561497b57fe5b84603c81111561498757fe5b604080519283526020830191909152818101859052519081900360600190a183601081111561306c57fe5b51670de0b6b3a7640000900490565b6000806000806149cf613c53565b600954146149ee576149e3600a60376131de565b93509150614a589050565b6149f93387876133cb565b9050614a07600c5482612c51565b600c819055604080513381526020810184905280820183905290519193507fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5919081900360600190a1600093509150505b9250929050565b6000614a6a8561381a565b831580614a75575082155b614ab05760405162461bcd60e51b8152600401808060200182810382526034815260200180615bd76034913960400191505060405180910390fd5b614ab86159ae565b614ac0612cc1565b81528415614af157602080820186905260408051918201905281518152614ae79086613121565b6040820152614b1a565b614b0d846040518060200160405280846000015181525061588f565b6020820152604081018490525b6001600160a01b0386166000908152600e60209081526040808320546015909252822054614b489190612c87565b905060008090508183602001511115614b65578183602001510390505b6005546040805163eabe7d9160e01b81523060048201526001600160a01b038b81166024830152604482018590529151600093929092169163eabe7d919160648082019260209290919082900301818787803b158015614bc457600080fd5b505af1158015614bd8573d6000803e3d6000fd5b505050506040513d6020811015614bee57600080fd5b505190508015614c1057614c056003601a8361494c565b94505050505061306c565b614c18613c53565b60095414614c2c57614c05600a601b6131de565b8360400151614c39612c4b565b1015614c4b57614c05600e601c6131de565b614c5a898560400151886132c4565b614c6a600d548560200151612c87565b600d556001600160a01b0389166000908152600e602090815260409091205490850151614c979190612c87565b6001600160a01b038a166000908152600e6020526040902055614cba8983613aa7565b306001600160a01b0316896001600160a01b0316600080516020615b8583398151915286602001516040518082815260200191505060405180910390a360408085015160208087015183516001600160a01b038e168152918201929092528083019190915290517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a9299181900360600190a1600554604080860151602087015182516351dff98960e01b81523060048201526001600160a01b038e811660248301526044820193909352606481019190915291519216916351dff9899160848082019260009290919082900301818387803b158015614db757600080fd5b505af1158015614dcb573d6000803e3d6000fd5b5060009250613065915050565b600080614de48561381a565b60055460408051634ef4c3e160e01b81523060048201526001600160a01b0388811660248301526044820188905291516000939290921691634ef4c3e19160648082019260209290919082900301818787803b158015614e4357600080fd5b505af1158015614e57573d6000803e3d6000fd5b505050506040513d6020811015614e6d57600080fd5b505190508015614e9157614e84600360158361494c565b9250600091506150769050565b84614e9d576000614e84565b614ea5613c53565b60095414614eb957614e84600a60166131de565b614ec16159ae565b614ec9612cc1565b8152614ed68787876133cb565b604080830182905280516020810190915282518152614ef5919061588f565b60208201819052600d54614f0891612c51565b600d556001600160a01b0387166000908152600e602090815260409091205490820151614f359190612c51565b6001600160a01b038089166000818152600e602090815260409182902094909455600554815163929fe9a160e01b81526004810193909352306024840152905192169263929fe9a192604480840193829003018186803b158015614f9857600080fd5b505afa158015614fac573d6000803e3d6000fd5b505050506040513d6020811015614fc257600080fd5b505115614fd957614fd787826020015161395c565b505b60408082015160208084015183516001600160a01b038c168152918201929092528083019190915290517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9181900360600190a1866001600160a01b0316306001600160a01b0316600080516020615b8583398151915283602001516040518082815260200191505060405180910390a360400151600093509150505b935093915050565b600083158061508b575082155b15615098575060006113cc565b838302838582816150a557fe5b041483906113655760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614899578181015183820152602001614881565b600081836151435760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614899578181015183820152602001614881565b5082848161514d57fe5b04949350505050565b6000670de0b6b3a764000061516f848460000151613ea0565b8161517657fe5b049392505050565b6005546040805163368f515360e21b81523060048201526001600160a01b0386811660248301526044820186905291516000938493169163da3d454c91606480830192602092919082900301818787803b1580156151db57600080fd5b505af11580156151ef573d6000803e3d6000fd5b505050506040513d602081101561520557600080fd5b5051905080156152245761521c600360068361494c565b9150506113cc565b8361525e5761523285613bfe565b6001600160a01b0386166000908152601060205260408120918255600a5460019092019190915561521c565b615266613c53565b6009541461527a5761521c600a60046131de565b83615283612c4b565b10156152955761521c600e60036131de565b61529d6159cf565b6152a686613bfe565b602082018190526152b79086612c51565b6040820152600b546152c99086612c51565b60608201526152d98686866132c4565b604080820180516001600160a01b03891660008181526010602090815290859020928355600a54600190930192909255606080860151600b819055935185519283529282018a9052818501929092529081019190915290517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809181900360800190a160009695505050505050565b60055460408051632fe3f38f60e11b81523060048201526001600160a01b0385811660248301528881166044830152878116606483015260848201879052915160009384938493911691635fc7e71e9160a48082019260209290919082900301818787803b1580156153d857600080fd5b505af11580156153ec573d6000803e3d6000fd5b505050506040513d602081101561540257600080fd5b505190508015615426576154196003600a8361494c565b9250600091506158859050565b61542e613c53565b6009541461544257615419600a600e6131de565b61544a613c53565b856001600160a01b031663cfa992016040518163ffffffff1660e01b815260040160206040518083038186803b15801561548357600080fd5b505afa158015615497573d6000803e3d6000fd5b505050506040513d60208110156154ad57600080fd5b5051146154c057615419600a60096131de565b876001600160a01b0316876001600160a01b031614156154e6576154196006600f6131de565b856154f7576154196007600d6131de565b60001986141561550d576154196007600c6131de565b60008061551c8a8a8a89614592565b9092509050811561554c5761553d82601081111561553657fe5b60106131de565b94506000935061588592505050565b6005546040805163c488847b60e01b81523060048201526001600160a01b038a81166024830152604482018590528251600094859492169263c488847b926064808301939192829003018186803b1580156155a657600080fd5b505afa1580156155ba573d6000803e3d6000fd5b505050506040513d60408110156155d057600080fd5b5080516020909101519092509050811561561b5760405162461bcd60e51b8152600401808060200182810382526032815260200180615a376032913960400191505060405180910390fd5b80896001600160a01b03166370a082318d6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561567257600080fd5b505afa158015615686573d6000803e3d6000fd5b505050506040513d602081101561569c57600080fd5b505110156156f1576040805162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d5543480000000000000000604482015290519081900360640190fd5b60006001600160a01b038a1630141561571757615710308e8e85613f15565b90506157a1565b6040805163b2a02ff160e01b81526001600160a01b038f811660048301528e81166024830152604482018590529151918c169163b2a02ff1916064808201926020929091908290030181600087803b15801561577257600080fd5b505af1158015615786573d6000803e3d6000fd5b505050506040513d602081101561579c57600080fd5b505190505b80156157eb576040805162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b604482015290519081900360640190fd5b7f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb528d8d868d8660405180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001848152602001836001600160a01b03166001600160a01b031681526020018281526020019550505050505060405180910390a16000975092955050505050505b9550959350505050565b60006158996158db565b61313584846158a66158db565b60006158ba670de0b6b3a764000085613ea0565b905060405180602001604052806158d1838661492e565b9052949350505050565b6040518060200160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061592f57805160ff191683800117855561595c565b8280016001018555821561595c579182015b8281111561595c578251825591602001919060010190615941565b50612d239291506159f8565b6040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180606001604052806000815260200160008152602001600081525090565b604080516080810190915280600081526020016000815260200160008152602001600081525090565b61119191905b80821115612d2357600081556001016159fe56fe6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d61726b65744c49515549444154455f4a4f4554524f4c4c45525f43414c43554c4154455f414d4f554e545f5345495a455f4641494c45446d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6e6365696e697469616c2065786368616e67652072617465206d7573742062652067726561746572207468616e207a65726f2e6f6e6c792061646d696e2063616e2073657420636f6c6c61746572616c2063617073657474696e6720696e7465726573742072617465206d6f64656c206661696c65646f6e6c79206a6f6574726f6c6c6572206d617920726567697374657220636f6c6c61746572616c20666f7220757365726f6e6c79207468652061646d696e206d61792063616c6c205f72657369676e496d706c656d656e746174696f6e45524333313536466c617368426f72726f776572496e746572666163652e6f6e466c6173684c6f616eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6f6e6c79206a6f6574726f6c6c6572206d617920756e726567697374657220636f6c6c61746572616c20666f7220757365726f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416d6f756e74496e206d757374206265207a65726f6f6e6c79207468652061646d696e206d61792063616c6c205f6265636f6d65496d706c656d656e746174696f6e1d22042d9eb89f2620572acbf8d85b66fba5a2ca19d166d8659574440175c964666c6173684c6f616e20616d6f756e742073686f756c642062652067726561746572207468616e207a65726fa265627a7a7231582084583a06bf118bd3322820466d19539cbca8d454347d50f670478b8f1dcc210864736f6c63430005100032",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106103fc5760003560e01c806381cf00eb11610215578063b2a02ff111610125578063db006a75116100b8578063f2b3abbd11610087578063f2b3abbd14610de8578063f3fdb15a14610e0e578063f5e3c46214610e16578063f851a44014610e4c578063fca7820b14610e54576103fc565b8063db006a7514610d8d578063dd62ed3e14610daa578063e9c714f214610dd8578063ea11eea414610de0576103fc565b8063c5ebeaec116100f4578063c5ebeaec14610d3a578063cfa9920114610d57578063d240d64a14610d5f578063d2bb18e914610d85576103fc565b8063b2a02ff114610c8a578063b71d1a0c14610cc0578063bd6d894d14610ce6578063c37f68e214610cee576103fc565b806395d89b41116101a8578063a6afed9511610177578063a6afed9514610c29578063a7af467a14610c31578063a9059cbb14610c4e578063aa5af0fd14610c7a578063b1d3897414610c82576103fc565b806395d89b4114610a9057806395dd919314610a9857806399d8c1b414610abe578063a0712d6814610c0c576103fc565b80638897bd85116101e45780638897bd8514610a345780638b35776b14610a5a5780638f840ddd14610a8057806394909e6214610a88576103fc565b806381cf00eb146109b757806383030846146109d4578063852a12e3146109f157806385d8a2e614610a0e576103fc565b80633af9e6691161031057806356e67728116102a35780636330533c116102725780636330533c146109715780636752e702146109795780636f307dc31461098157806370a082311461098957806373acee98146109af576103fc565b806356e677281461081a5780635c60da1b146108be5780635cffe9de146108c6578063601a0bf114610954576103fc565b8063432f4b2d116102df578063432f4b2d146107bf57806347bd3718146107e557806350f6e082146107ed5780635260975014610812576103fc565b80633af9e6691461076c5780633b1d21a2146107925780633e9410101461079a578063406de0b6146107b7576103fc565b8063182df0f51161039357806323b872dd1161036257806323b872dd146106c0578063242c127c146106f65780632608f818146106fe578063267822471461072a578063313ce5671461074e576103fc565b8063182df0f51461055257806319a4dd3c1461055a5780631a31d4651461056257806322abdbf5146106b8576103fc565b8063153ab505116103cf578063153ab50514610512578063173b99041461051c57806317bfdfbc1461052457806318160ddd1461054a576103fc565b806306fdde0314610401578063095ea7b31461047e5780630e752702146104be5780630f3e4e11146104ed575b600080fd5b610409610e71565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561044357818101518382015260200161042b565b50505050905090810190601f1680156104705780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104aa6004803603604081101561049457600080fd5b506001600160a01b038135169060200135610efe565b604080519115158252519081900360200190f35b6104db600480360360208110156104d457600080fd5b5035610f6b565b60408051918252519081900360200190f35b6104db6004803603604081101561050357600080fd5b50803590602001351515610f83565b61051a611068565b005b6104db6110b8565b6104db6004803603602081101561053a57600080fd5b50356001600160a01b03166110be565b6104db61117e565b6104db611184565b6104db611194565b61051a600480360360e081101561057857600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b8111156105ba57600080fd5b8201836020820111156105cc57600080fd5b803590602001918460018302840111600160201b831117156105ed57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561063f57600080fd5b82018360208201111561065157600080fd5b803590602001918460018302840111600160201b8311171561067257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061119a9050565b6104db611239565b6104aa600480360360608110156106d657600080fd5b506001600160a01b0381358116916020810135909116906040013561123f565b6104db6112b1565b6104db6004803603604081101561071457600080fd5b506001600160a01b038135169060200135611356565b61073261136e565b604080516001600160a01b039092168252519081900360200190f35b61075661137d565b6040805160ff9092168252519081900360200190f35b6104db6004803603602081101561078257600080fd5b50356001600160a01b0316611386565b6104db6113d3565b6104db600480360360208110156107b057600080fd5b50356113dd565b6104aa6113ea565b6104db600480360360208110156107d557600080fd5b50356001600160a01b03166113ef565b6104db611543565b6104db6004803603604081101561080357600080fd5b50803590602001351515611549565b6104db6115f8565b61051a6004803603602081101561083057600080fd5b810190602081018135600160201b81111561084a57600080fd5b82018360208201111561085c57600080fd5b803590602001918460018302840111600160201b8311171561087d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061168d945050505050565b610732611754565b6104aa600480360360808110156108dc57600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561091657600080fd5b82018360208201111561092857600080fd5b803590602001918460018302840111600160201b8311171561094957600080fd5b509092509050611763565b6104db6004803603602081101561096a57600080fd5b5035611ca7565b610732611d42565b6104db611d51565b610732611d57565b6104db6004803603602081101561099f57600080fd5b50356001600160a01b0316611d66565b6104db611d81565b61051a600480360360208110156109cd57600080fd5b5035611e37565b6104db600480360360208110156109ea57600080fd5b5035611ec8565b6104db60048036036020811015610a0757600080fd5b5035611f46565b6104aa60048036036020811015610a2457600080fd5b50356001600160a01b0316611f53565b6104db60048036036020811015610a4a57600080fd5b50356001600160a01b0316611f68565b61051a60048036036020811015610a7057600080fd5b50356001600160a01b0316611ff6565b6104db61206f565b61051a612075565b61040961210a565b6104db60048036036020811015610aae57600080fd5b50356001600160a01b0316612162565b61051a600480360360c0811015610ad457600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610b0e57600080fd5b820183602082011115610b2057600080fd5b803590602001918460018302840111600160201b83111715610b4157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b9357600080fd5b820183602082011115610ba557600080fd5b803590602001918460018302840111600160201b83111715610bc657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061216d9050565b6104db60048036036020811015610c2257600080fd5b5035612354565b6104db612362565b6104db60048036036020811015610c4757600080fd5b5035612572565b6104aa60048036036040811015610c6457600080fd5b506001600160a01b038135169060200135612664565b6104db6126d6565b6104db6126dc565b6104db60048036036060811015610ca057600080fd5b506001600160a01b0381358116916020810135909116906040013561274a565b6104db60048036036020811015610cd657600080fd5b50356001600160a01b03166127bb565b6104db612847565b610d1460048036036020811015610d0457600080fd5b50356001600160a01b0316612903565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6104db60048036036020811015610d5057600080fd5b503561293f565b6104db61294c565b6104db60048036036020811015610d7557600080fd5b50356001600160a01b0316612952565b6104db612964565b6104db60048036036020811015610da357600080fd5b503561296a565b6104db60048036036040811015610dc057600080fd5b506001600160a01b0381358116916020013516612977565b6104db6129a2565b6104db612aa5565b6104db60048036036020811015610dfe57600080fd5b50356001600160a01b0316612aaa565b610732612ae4565b6104db60048036036060811015610e2c57600080fd5b506001600160a01b03813581169160208101359160409091013516612af3565b610732612b0d565b6104db60048036036020811015610e6a57600080fd5b5035612b21565b60018054604080516020600284861615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610ef65780601f10610ecb57610100808354040283529160200191610ef6565b820191906000526020600020905b815481529060010190602001808311610ed957829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855290835281842086905581518681529151939493909284927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a360019150505b92915050565b600080610f79836000612b9f565b509150505b919050565b60008060008315610fb457610f9f610f99612c4b565b86612c51565b9150610fad600b5486612c87565b9050610fd6565b610fc5610fbf612c4b565b86612c87565b9150610fd3600b5486612c51565b90505b600654600c54604080516315f2405360e01b815260048101869052602481018590526044810192909252516001600160a01b03909216916315f2405391606480820192602092909190829003018186803b15801561103357600080fd5b505afa158015611047573d6000803e3d6000fd5b505050506040513d602081101561105d57600080fd5b505195945050505050565b60035461010090046001600160a01b031633146110b65760405162461bcd60e51b815260040180806020018281038252602d815260200180615b2f602d913960400191505060405180910390fd5b565b60085481565b6000805460ff16611103576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611115612362565b14611160576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b61116982612162565b90505b6000805460ff19166001179055919050565b600d5481565b600061118e612cc1565b90505b90565b60145481565b6111a886868686868661216d565b601180546001600160a01b0319166001600160a01b038981169190911791829055604080516318160ddd60e01b8152905192909116916318160ddd91600480820192602092909190829003018186803b15801561120457600080fd5b505afa158015611218573d6000803e3d6000fd5b505050506040513d602081101561122e57600080fd5b505050505050505050565b60135481565b6000805460ff16611284576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561129a33868686612d27565b1490506000805460ff191660011790559392505050565b600554604080516358d5bc7360e11b81523060048201526000602482018190526044820181905260806064830152608482018190529151919283926001600160a01b039091169163b1ab78e69160c4808301926020929190829003018186803b15801561131d57600080fd5b505afa158015611331573d6000803e3d6000fd5b505050506040513d602081101561134757600080fd5b50511561118e57610f65612c4b565b60008061136584846000613074565b50949350505050565b6004546001600160a01b031681565b60035460ff1681565b60006113906158db565b60405180602001604052806113a3612847565b90526001600160a01b0384166000908152600e60205260409020549091506113cc908290613121565b9392505050565b600061118e612c4b565b6000610f65826000613140565b600181565b60035460009061010090046001600160a01b0316331461141c57611415600160296131de565b9050610f7e565b600554604080516340e6dcc560e01b815290516001600160a01b03928316928516916340e6dcc5916004808301926020929190829003018186803b15801561146357600080fd5b505afa158015611477573d6000803e3d6000fd5b505050506040513d602081101561148d57600080fd5b50516114e0576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517f17d6db5ffe5a3d1c3d7a98194dca4f7d808d621e6ff9077ed574513d553a2a859281900390910190a160006113cc565b600b5481565b600080600083156115745761155f610f99612c4b565b915061156d600b5486612c87565b9050611590565b61157f610fbf612c4b565b915061158d600b5486612c51565b90505b600654600c5460085460408051635c0b440b60e11b8152600481018790526024810186905260448101939093526064830191909152516001600160a01b039092169163b816881691608480820192602092909190829003018186803b15801561103357600080fd5b6006546000906001600160a01b03166315f24053611614612c4b565b600b54600c546040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b15801561165c57600080fd5b505afa158015611670573d6000803e3d6000fd5b505050506040513d602081101561168657600080fd5b5051905090565b60035461010090046001600160a01b031633146116db5760405162461bcd60e51b815260040180806020018281038252602d815260200180615c0b602d913960400191505060405180910390fd5b6116e3613244565b601355600554604080516303c03f0f60e01b81523060048201526001602482015290516001600160a01b03909216916303c03f0f9160448082019260009290919082900301818387803b15801561173957600080fd5b505af115801561174d573d6000803e3d6000fd5b5050505050565b6012546001600160a01b031681565b6000805460ff166117a8576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19169055836117ee5760405162461bcd60e51b815260040180806020018281038252602c815260200180615c58602c913960400191505060405180910390fd5b60006117f8612362565b14611843576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b6005546040516358d5bc7360e11b815230600482018181526001600160a01b038a81166024850152604484018990526080606485019081526084850188905294169363b1ab78e6938b928a928a928a92919060a401848480828437600081840152601f19601f820116905080830192505050965050505050505060206040518083038186803b1580156118d557600080fd5b505afa1580156118e9573d6000803e3d6000fd5b505050506040513d60208110156118ff57600080fd5b5051611948576040805162461bcd60e51b8152602060048201526013602482015272199b185cda1b1bd85b881a5cc81c185d5cd959606a1b604482015290519081900360640190fd5b6000611952613244565b9050600061195e612c4b565b9050858110156119ae576040805162461bcd60e51b8152602060048201526016602482015275494e53554646494349454e545f4c495155494449545960501b604482015290519081900360640190fd5b6000306001600160a01b031663a7af467a886040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156119f457600080fd5b505afa158015611a08573d6000803e3d6000fd5b505050506040513d6020811015611a1e57600080fd5b50519050611a2e898860006132c4565b611a3a600b5488612c51565b600b55604051806029615b5c82396040519081900360290181206011546323e30c8b60e01b83526001600160a01b038c81166004850190815291811660248501819052604485018d90526064850187905260a06084860190815260a486018c9052939550908e16936323e30c8b938e938e9289928f928f9290919060c401848480828437600081840152601f19601f820116905080830192505050975050505050505050602060405180830381600087803b158015611af857600080fd5b505af1158015611b0c573d6000803e3d6000fd5b505050506040513d6020811015611b2257600080fd5b505114611b76576040805162461bcd60e51b815260206004820152601960248201527f49455243333135363a2043616c6c6261636b206661696c656400000000000000604482015290519081900360640190fd5b6000611b828883612c51565b9050611b908a8260006133cb565b506000611b9b613244565b9050611ba78584612c51565b8114611bf1576040805162461bcd60e51b8152602060048201526014602482015273109053105390d157d25390d3d394d254d511539560621b604482015290519081900360640190fd5b6000611c0d604051806020016040528060085481525085613121565b9050611c1b600c5482612c51565b600c55611c288585612c51565b601355600b54611c38908b612c87565b600b55604080518b81526020810186905280820183905290516001600160a01b038e16917f33c8e097c526683cbdb29adf782fac95e9d0fbe0ed635c13d8c75fdf726557d9919081900360600190a2600196505050505050506000805460ff1916600117905595945050505050565b6000805460ff16611cec576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611cfe612362565b90508015611d2457611d1c816010811115611d1557fe5b601d6131de565b91505061116c565b611d2d836135dc565b9150506000805460ff19166001179055919050565b6005546001600160a01b031681565b60185481565b6011546001600160a01b031681565b6001600160a01b03166000908152600e602052604090205490565b6000805460ff16611dc6576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611dd8612362565b14611e23576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b50600b546000805460ff1916600117905590565b60035461010090046001600160a01b03163314611e855760405162461bcd60e51b8152600401808060200182810382526021815260200180615abc6021913960400191505060405180910390fd5b6017819055604080513081526020810183905281517f01b7c780e0f385803fe80cbe0efc086d13b8eb443a2ce43e2061fd92bc0e34f1929181900390910190a150565b6000805460ff16611f0d576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611f1f612362565b90508015611f3d57611d1c816010811115611f3657fe5b60396131de565b611d2d836136da565b6000610f65826000613782565b60166020526000908152604090205460ff1681565b6000611f738261381a565b6005546001600160a01b03163314611fbc5760405162461bcd60e51b8152600401808060200182810382526030815260200180615aff6030913960400191505060405180910390fd5b6001600160a01b0382166000908152600e60209081526040808320546015909252822054611fea9190612c87565b90506113cc838261395c565b611fff8161381a565b6005546001600160a01b031633146120485760405162461bcd60e51b8152600401808060200182810382526032815260200180615ba56032913960400191505060405180910390fd5b6001600160a01b03811660009081526015602052604090205461206c908290613aa7565b50565b600c5481565b60005460ff166120b9576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556120cb613244565b905060006120d7612c4b565b905060006120e58383612c87565b90506120f3600c5482612c51565b600c5550506013556000805460ff19166001179055565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610ef65780601f10610ecb57610100808354040283529160200191610ef6565b6000610f6582613bfe565b60035461010090046001600160a01b031633146121bb5760405162461bcd60e51b8152600401808060200182810382526024815260200180615a136024913960400191505060405180910390fd5b6009541580156121cb5750600a54155b6122065760405162461bcd60e51b8152600401808060200182810382526023815260200180615a696023913960400191505060405180910390fd5b6007849055836122475760405162461bcd60e51b8152600401808060200182810382526030815260200180615a8c6030913960400191505060405180910390fd5b6000612252876113ef565b905080156122a7576040805162461bcd60e51b815260206004820152601960248201527f73657474696e67206a6f6574726f6c6c6572206661696c656400000000000000604482015290519081900360640190fd5b6122af613c53565b600955670de0b6b3a7640000600a556122c786613c57565b905080156123065760405162461bcd60e51b8152600401808060200182810382526022815260200180615add6022913960400191505060405180910390fd5b83516123199060019060208701906158ee565b50825161232d9060029060208601906158ee565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b600080610f79836000613dcc565b60008061236d613c53565b6009549091508082141561238657600092505050611191565b6000612390612c4b565b600b54600c54600a54600654604080516315f2405360e01b815260048101879052602481018690526044810185905290519596509394929391926000926001600160a01b03909216916315f24053916064808301926020929190829003018186803b1580156123fe57600080fd5b505afa158015612412573d6000803e3d6000fd5b505050506040513d602081101561242857600080fd5b5051905065048c27395000811115612487576040805162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c79206869676800000000604482015290519081900360640190fd5b60006124938888612c87565b905061249d6158db565b6124b560405180602001604052808581525083613e4e565b905060006124c38288613121565b905060006124d18289612c51565b905060006124f06040518060200160405280600854815250848a613e78565b905060006124ff85898a613e78565b60098e9055600a819055600b849055600c839055604080518d8152602081018790528082018390526060810186905290519192507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc04919081900360800190a160009d505050505050505050505050505090565b600554604080516358d5bc7360e11b8152306004820152600060248201819052604482018590526080606483015260848201819052915191926001600160a01b03169163b1ab78e69160c480820192602092909190829003018186803b1580156125db57600080fd5b505afa1580156125ef573d6000803e3d6000fd5b505050506040513d602081101561260557600080fd5b505161264e576040805162461bcd60e51b8152602060048201526013602482015272199b185cda1b1bd85b881a5cc81c185d5cd959606a1b604482015290519081900360640190fd5b610f6561265c836008613ea0565b612710613ee2565b6000805460ff166126a9576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556126bf33338686612d27565b1490505b6000805460ff1916600117905592915050565b600a5481565b6006546000906001600160a01b031663b81688166126f8612c4b565b600b54600c546008546040518563ffffffff1660e01b81526004018085815260200184815260200183815260200182815260200194505050505060206040518083038186803b15801561165c57600080fd5b6000805460ff1661278f576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191690556127a533858585613f15565b90506000805460ff191660011790559392505050565b60035460009061010090046001600160a01b031633146127e1576114156001602f6131de565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a160006113cc565b6000805460ff1661288c576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561289e612362565b146128e9576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b6128f1611184565b90506000805460ff1916600117905590565b60008060008060006129148661425c565b9050600061292187613bfe565b9050600061292d612cc1565b90506000989297509095509350915050565b6000610f658260006142bb565b60095481565b60156020526000908152604090205481565b60175481565b6000610f6582600061433b565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6004546000906001600160a01b0316331415806129bd575033155b156129d5576129ce600160006131de565b9050611191565b60038054600480546001600160a01b03818116610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401528351909391927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600454604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160009250505090565b600881565b600080612ab5612362565b90508015612adb57612ad3816010811115612acc57fe5b602a6131de565b915050610f7e565b6113cc83613c57565b6006546001600160a01b031681565b600080612b0385858560006143b6565b5095945050505050565b60035461010090046001600160a01b031681565b6000805460ff16612b66576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612b78612362565b90508015612b9657611d1c816010811115612b8f57fe5b60306131de565b611d2d836144ea565b60008054819060ff16612be6576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612bf8612362565b90508015612c2357612c16816010811115612c0f57fe5b60236131de565b925060009150612c359050565b612c2f33338787614592565b92509250505b6000805460ff1916600117905590939092509050565b60135490565b60006113cc8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250614842565b60006113cc8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b8152506148d4565b600d5460009080612cd6575050600754611191565b6000612ce0612c4b565b90506000612cfb612cf383600b54612c51565b600c54612c87565b90506000612d178260405180602001604052808781525061492e565b94506111919350505050565b5090565b6000612d328461381a565b612d3b8361381a565b6001600160a01b0384166000908152600e60209081526040808320546015909252822054612d699190612c87565b9050600081841115612d7a57508083035b600554604080516317b9b84b60e31b81523060048201526001600160a01b0389811660248301528881166044830152606482018590529151600093929092169163bdcdc2589160848082019260209290919082900301818787803b158015612de157600080fd5b505af1158015612df5573d6000803e3d6000fd5b505050506040513d6020811015612e0b57600080fd5b505190508015612e2c57612e22600360348361494c565b935050505061306c565b856001600160a01b0316876001600160a01b03161415612e5257612e22600260356131de565b60006001600160a01b038981169089161415612e715750600019612e99565b506001600160a01b038088166000908152600f60209081526040808320938c16835292905220545b6001600160a01b0388166000908152600e6020526040902054612ebc9087612c87565b6001600160a01b03808a166000908152600e60205260408082209390935590891681522054612eeb9087612c51565b6001600160a01b0388166000908152600e60205260409020558215612fef576001600160a01b038816600090815260156020526040902054612f2d9084612c87565b6001600160a01b03808a166000908152601560205260408082209390935590891681522054612f5c9084612c51565b6001600160a01b03808916600090815260156020908152604080832094909455918b1680825290839020548351918252918101919091528151600080516020615c38833981519152929181900390910190a16001600160a01b038716600081815260156020908152604091829020548251938452908301528051600080516020615c388339815191529281900390910190a15b6000198114613029576130028187612c87565b6001600160a01b03808a166000908152600f60209081526040808320938e16835292905220555b866001600160a01b0316886001600160a01b0316600080516020615b85833981519152886040518082815260200191505060405180910390a360005b9450505050505b949350505050565b60008054819060ff166130bb576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556130cd612362565b905080156130f8576130eb8160108111156130e457fe5b60226131de565b92506000915061310a9050565b61310433878787614592565b92509250505b6000805460ff191660011790559094909350915050565b600061312b6158db565b6131358484613e4e565b905061306c816149b2565b6000805460ff16613185576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155613197612362565b905080156131bd576131b58160108111156131ae57fe5b60366131de565b9150506126c3565b6131c784846149c1565b509150506000805460ff1916600117905592915050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601081111561320d57fe5b83603c81111561321957fe5b604080519283526020830191909152600082820152519081900360600190a18260108111156113cc57fe5b601154604080516370a0823160e01b815230600482015290516000926001600160a01b03169182916370a0823191602480820192602092909190829003018186803b15801561329257600080fd5b505afa1580156132a6573d6000803e3d6000fd5b505050506040513d60208110156132bc57600080fd5b505191505090565b6011546040805163a9059cbb60e01b81526001600160a01b0386811660048301526024820186905291519190921691829163a9059cbb9160448082019260009290919082900301818387803b15801561331c57600080fd5b505af1158015613330573d6000803e3d6000fd5b5050505060003d6000811461334c576020811461335657600080fd5b6000199150613362565b60206000803e60005191505b50806133b5576040805162461bcd60e51b815260206004820152601960248201527f544f4b454e5f5452414e534645525f4f55545f4641494c454400000000000000604482015290519081900360640190fd5b6133c160135485612c87565b6013555050505050565b601154604080516370a0823160e01b815230600482015290516000926001600160a01b031691839183916370a08231916024808301926020929190829003018186803b15801561341a57600080fd5b505afa15801561342e573d6000803e3d6000fd5b505050506040513d602081101561344457600080fd5b5051604080516323b872dd60e01b81526001600160a01b038981166004830152306024830152604482018990529151929350908416916323b872dd9160648082019260009290919082900301818387803b1580156134a157600080fd5b505af11580156134b5573d6000803e3d6000fd5b5050505060003d600081146134d157602081146134db57600080fd5b60001991506134e7565b60206000803e60005191505b508061353a576040805162461bcd60e51b815260206004820152601860248201527f544f4b454e5f5452414e534645525f494e5f4641494c45440000000000000000604482015290519081900360640190fd5b601154604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561358557600080fd5b505afa158015613599573d6000803e3d6000fd5b505050506040513d60208110156135af57600080fd5b5051905060006135bf8285612c87565b90506135cd60135482612c51565b60135598975050505050505050565b600354600090819061010090046001600160a01b0316331461360457612ad36001601e6131de565b61360c613c53565b6009541461362057612ad3600a60206131de565b82613629612c4b565b101561363b57612ad3600e601f6131de565b600c5483111561365157612ad3600260216131de565b61365d600c5484612c87565b600c8190556003549091506136829061010090046001600160a01b03168460016132c4565b600354604080516101009092046001600160a01b0316825260208201859052818101839052517f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e916060908290030190a160006113cc565b60035460009061010090046001600160a01b03163314613700576114156001603a6131de565b613708613c53565b6009541461371c57611415600a603b6131de565b670de0b6b3a7640000821115613738576114156002603c6131de565b6018805490839055604080518281526020810185905281517ff5815f353a60e815cce7553e4f60c533a59d26b1b5504ea4b6db8d60da3e4da2929181900390910190a160006113cc565b6000805460ff166137c7576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556137d9612362565b905080156137f7576131b58160108111156137f057fe5b60196131de565b6138043360008686614a5f565b9150506000805460ff1916600117905592915050565b6001600160a01b03811660009081526016602052604090205460ff1661206c576005546040805163929fe9a160e01b81526001600160a01b0384811660048301523060248301529151919092169163929fe9a1916044808301926020929190829003018186803b15801561388d57600080fd5b505afa1580156138a1573d6000803e3d6000fd5b505050506040513d60208110156138b757600080fd5b505115613936576001600160a01b0381166000908152600e60208181526040808420546015835293208390556014549190526138f291612c51565b6014556001600160a01b038116600081815260156020908152604091829020548251938452908301528051600080516020615c388339815191529281900390910190a15b6001600160a01b0381166000908152601660205260409020805460ff1916600117905550565b60008061396b60145484612c51565b90506017546000148061398c57506017541580159061398c57506017548111155b15613a075760148190556001600160a01b0384166000908152601560205260409020546139b99084612c51565b6001600160a01b03851660008181526015602090815260409182902084905581519283528201929092528151600080516020615c38833981519152929181900390910190a182915050610f65565b6014546017541115613a9d576000613a23601754601454612c87565b6017546014556001600160a01b038616600090815260156020526040902054909150613a4f9082612c51565b6001600160a01b03861660008181526015602090815260409182902084905581519283528201929092528151600080516020615c38833981519152929181900390910190a19150610f659050565b5060009392505050565b6005546040805163eabe7d9160e01b81523060048201526001600160a01b038581166024830152604482018590529151919092169163eabe7d919160648083019260209291908290030181600087803b158015613b0357600080fd5b505af1158015613b17573d6000803e3d6000fd5b505050506040513d6020811015613b2d57600080fd5b505115613b78576040805162461bcd60e51b81526020600482015260146024820152733537b2ba3937b63632b9103932b532b1ba34b7b760611b604482015290519081900360640190fd5b80613b8257613bfa565b613b8e60145482612c87565b6014556001600160a01b038216600090815260156020526040902054613bb49082612c87565b6001600160a01b03831660008181526015602090815260409182902084905581519283528201929092528151600080516020615c38833981519152929181900390910190a15b5050565b6001600160a01b03811660009081526010602052604081208054613c26576000915050610f7e565b6000613c388260000154600a54613ea0565b90506000613c4a828460010154613ee2565b95945050505050565b4290565b600354600090819061010090046001600160a01b03163314613c7f57612ad36001602c6131de565b613c87613c53565b60095414613c9b57612ad3600a602b6131de565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b158015613cec57600080fd5b505afa158015613d00573d6000803e3d6000fd5b505050506040513d6020811015613d1657600080fd5b5051613d69576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269281900390910190a160006113cc565b60008054819060ff16613e13576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155613e25612362565b90508015613e4357612c16816010811115613e3c57fe5b60146131de565b612c2f338686614dd8565b613e566158db565b6040518060200160405280613e6f856000015185613ea0565b90529392505050565b6000613e826158db565b613e8c8585613e4e565b9050613c4a613e9a826149b2565b84612c51565b60006113cc83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f7700000000000000000081525061507e565b60006113cc83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b8152506150f4565b6000613f208461381a565b613f298361381a565b6005546040805163d02f735160e01b81523060048201526001600160a01b03888116602483015287811660448301528681166064830152608482018690529151600093929092169163d02f73519160a48082019260209290919082900301818787803b158015613f9857600080fd5b505af1158015613fac573d6000803e3d6000fd5b505050506040513d6020811015613fc257600080fd5b505190508015613fe157613fd9600360118361494c565b91505061306c565b82613fed576000613fd9565b846001600160a01b0316846001600160a01b0316141561401357613fd9600660126131de565b600061402f846040518060200160405280601854815250615156565b9050600061403d8583612c87565b90506000614049612cc1565b9050600061406560405180602001604052808481525085613121565b6001600160a01b0389166000908152600e602052604090205490915061408b9088612c87565b6001600160a01b03808a166000908152600e602052604080822093909355908b16815220546140ba9084612c51565b6001600160a01b03808b166000908152600e6020908152604080832094909455918b168152601590915220546140f09088612c87565b6001600160a01b03808a1660009081526015602052604080822093909355908b168152205461411f9084612c51565b6001600160a01b038a16600090815260156020526040902055600c546141459082612c51565b600c55600d546141559085612c87565b600d556040805188815290516001600160a01b03808c1692908b1691600080516020615b858339815191529181900360200190a36001600160a01b038816600081815260156020908152604091829020548251938452908301528051600080516020615c388339815191529281900390910190a16001600160a01b038916600081815260156020908152604091829020548251938452908301528051600080516020615c388339815191529281900390910190a1600c54604080513081526020810184905280820192909252517fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc59181900360600190a160009a9950505050505050505050565b6001600160a01b03811660009081526016602052604081205460ff161561429c57506001600160a01b038116600090815260156020526040902054610f7e565b506001600160a01b0381166000908152600e6020526040902054610f7e565b6000805460ff16614300576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155614312612362565b90508015614330576131b581601081111561432957fe5b60026131de565b61380433858561517e565b6000805460ff16614380576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155614392612362565b905080156143a9576131b58160108111156137f057fe5b6138043385600086614a5f565b60008054819060ff166143fd576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561440f612362565b9050801561443a5761442d81601081111561442657fe5b60076131de565b9250600091506144d29050565b846001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561447557600080fd5b505af1158015614489573d6000803e3d6000fd5b505050506040513d602081101561449f57600080fd5b5051905080156144bf5761442d8160108111156144b857fe5b60086131de565b6144cc3388888888615367565b92509250505b6000805460ff19166001179055909590945092505050565b60035460009061010090046001600160a01b0316331461451057611415600160316131de565b614518613c53565b6009541461452c57611415600a60326131de565b670de0b6b3a764000082111561454857611415600260336131de565b6008805490839055604080518281526020810185905281517faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460929181900390910190a160006113cc565b60055460408051631200453160e11b81523060048201526001600160a01b0387811660248301528681166044830152606482018690529151600093849384939116916324008a629160848082019260209290919082900301818787803b1580156145fb57600080fd5b505af115801561460f573d6000803e3d6000fd5b505050506040513d602081101561462557600080fd5b5051905080156146495761463c600360248361494c565b9250600091506148399050565b846146835761465786613bfe565b6001600160a01b0387166000908152601060205260408120918255600a5460019092019190915561463c565b61468b613c53565b6009541461469f5761463c600a60256131de565b6146a7615968565b6001600160a01b03871660009081526010602052604090206001015460608201526146d187613bfe565b60808201526000198614156146ef57608081015160408201526146f7565b604081018690525b614706888260400151876133cb565b60e08201819052608082015161471b91612c87565b60a0820152600b5460e08201516147329190612c87565b8160c00181815250508060a0015160106000896001600160a01b03166001600160a01b0316815260200190815260200160002060000181905550600a5460106000896001600160a01b03166001600160a01b03168152602001908152602001600020600101819055508060c00151600b819055507f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a188888360e001518460a001518560c0015160405180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018381526020018281526020019550505050505060405180910390a160e00151600093509150505b94509492505050565b600083830182858210156113655760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614899578181015183820152602001614881565b50505050905090810190601f1680156148c65780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b600081848411156149265760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614899578181015183820152602001614881565b505050900390565b60006113cc61494584670de0b6b3a7640000613ea0565b8351613ee2565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601081111561497b57fe5b84603c81111561498757fe5b604080519283526020830191909152818101859052519081900360600190a183601081111561306c57fe5b51670de0b6b3a7640000900490565b6000806000806149cf613c53565b600954146149ee576149e3600a60376131de565b93509150614a589050565b6149f93387876133cb565b9050614a07600c5482612c51565b600c819055604080513381526020810184905280820183905290519193507fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5919081900360600190a1600093509150505b9250929050565b6000614a6a8561381a565b831580614a75575082155b614ab05760405162461bcd60e51b8152600401808060200182810382526034815260200180615bd76034913960400191505060405180910390fd5b614ab86159ae565b614ac0612cc1565b81528415614af157602080820186905260408051918201905281518152614ae79086613121565b6040820152614b1a565b614b0d846040518060200160405280846000015181525061588f565b6020820152604081018490525b6001600160a01b0386166000908152600e60209081526040808320546015909252822054614b489190612c87565b905060008090508183602001511115614b65578183602001510390505b6005546040805163eabe7d9160e01b81523060048201526001600160a01b038b81166024830152604482018590529151600093929092169163eabe7d919160648082019260209290919082900301818787803b158015614bc457600080fd5b505af1158015614bd8573d6000803e3d6000fd5b505050506040513d6020811015614bee57600080fd5b505190508015614c1057614c056003601a8361494c565b94505050505061306c565b614c18613c53565b60095414614c2c57614c05600a601b6131de565b8360400151614c39612c4b565b1015614c4b57614c05600e601c6131de565b614c5a898560400151886132c4565b614c6a600d548560200151612c87565b600d556001600160a01b0389166000908152600e602090815260409091205490850151614c979190612c87565b6001600160a01b038a166000908152600e6020526040902055614cba8983613aa7565b306001600160a01b0316896001600160a01b0316600080516020615b8583398151915286602001516040518082815260200191505060405180910390a360408085015160208087015183516001600160a01b038e168152918201929092528083019190915290517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a9299181900360600190a1600554604080860151602087015182516351dff98960e01b81523060048201526001600160a01b038e811660248301526044820193909352606481019190915291519216916351dff9899160848082019260009290919082900301818387803b158015614db757600080fd5b505af1158015614dcb573d6000803e3d6000fd5b5060009250613065915050565b600080614de48561381a565b60055460408051634ef4c3e160e01b81523060048201526001600160a01b0388811660248301526044820188905291516000939290921691634ef4c3e19160648082019260209290919082900301818787803b158015614e4357600080fd5b505af1158015614e57573d6000803e3d6000fd5b505050506040513d6020811015614e6d57600080fd5b505190508015614e9157614e84600360158361494c565b9250600091506150769050565b84614e9d576000614e84565b614ea5613c53565b60095414614eb957614e84600a60166131de565b614ec16159ae565b614ec9612cc1565b8152614ed68787876133cb565b604080830182905280516020810190915282518152614ef5919061588f565b60208201819052600d54614f0891612c51565b600d556001600160a01b0387166000908152600e602090815260409091205490820151614f359190612c51565b6001600160a01b038089166000818152600e602090815260409182902094909455600554815163929fe9a160e01b81526004810193909352306024840152905192169263929fe9a192604480840193829003018186803b158015614f9857600080fd5b505afa158015614fac573d6000803e3d6000fd5b505050506040513d6020811015614fc257600080fd5b505115614fd957614fd787826020015161395c565b505b60408082015160208084015183516001600160a01b038c168152918201929092528083019190915290517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9181900360600190a1866001600160a01b0316306001600160a01b0316600080516020615b8583398151915283602001516040518082815260200191505060405180910390a360400151600093509150505b935093915050565b600083158061508b575082155b15615098575060006113cc565b838302838582816150a557fe5b041483906113655760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614899578181015183820152602001614881565b600081836151435760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614899578181015183820152602001614881565b5082848161514d57fe5b04949350505050565b6000670de0b6b3a764000061516f848460000151613ea0565b8161517657fe5b049392505050565b6005546040805163368f515360e21b81523060048201526001600160a01b0386811660248301526044820186905291516000938493169163da3d454c91606480830192602092919082900301818787803b1580156151db57600080fd5b505af11580156151ef573d6000803e3d6000fd5b505050506040513d602081101561520557600080fd5b5051905080156152245761521c600360068361494c565b9150506113cc565b8361525e5761523285613bfe565b6001600160a01b0386166000908152601060205260408120918255600a5460019092019190915561521c565b615266613c53565b6009541461527a5761521c600a60046131de565b83615283612c4b565b10156152955761521c600e60036131de565b61529d6159cf565b6152a686613bfe565b602082018190526152b79086612c51565b6040820152600b546152c99086612c51565b60608201526152d98686866132c4565b604080820180516001600160a01b03891660008181526010602090815290859020928355600a54600190930192909255606080860151600b819055935185519283529282018a9052818501929092529081019190915290517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809181900360800190a160009695505050505050565b60055460408051632fe3f38f60e11b81523060048201526001600160a01b0385811660248301528881166044830152878116606483015260848201879052915160009384938493911691635fc7e71e9160a48082019260209290919082900301818787803b1580156153d857600080fd5b505af11580156153ec573d6000803e3d6000fd5b505050506040513d602081101561540257600080fd5b505190508015615426576154196003600a8361494c565b9250600091506158859050565b61542e613c53565b6009541461544257615419600a600e6131de565b61544a613c53565b856001600160a01b031663cfa992016040518163ffffffff1660e01b815260040160206040518083038186803b15801561548357600080fd5b505afa158015615497573d6000803e3d6000fd5b505050506040513d60208110156154ad57600080fd5b5051146154c057615419600a60096131de565b876001600160a01b0316876001600160a01b031614156154e6576154196006600f6131de565b856154f7576154196007600d6131de565b60001986141561550d576154196007600c6131de565b60008061551c8a8a8a89614592565b9092509050811561554c5761553d82601081111561553657fe5b60106131de565b94506000935061588592505050565b6005546040805163c488847b60e01b81523060048201526001600160a01b038a81166024830152604482018590528251600094859492169263c488847b926064808301939192829003018186803b1580156155a657600080fd5b505afa1580156155ba573d6000803e3d6000fd5b505050506040513d60408110156155d057600080fd5b5080516020909101519092509050811561561b5760405162461bcd60e51b8152600401808060200182810382526032815260200180615a376032913960400191505060405180910390fd5b80896001600160a01b03166370a082318d6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561567257600080fd5b505afa158015615686573d6000803e3d6000fd5b505050506040513d602081101561569c57600080fd5b505110156156f1576040805162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d5543480000000000000000604482015290519081900360640190fd5b60006001600160a01b038a1630141561571757615710308e8e85613f15565b90506157a1565b6040805163b2a02ff160e01b81526001600160a01b038f811660048301528e81166024830152604482018590529151918c169163b2a02ff1916064808201926020929091908290030181600087803b15801561577257600080fd5b505af1158015615786573d6000803e3d6000fd5b505050506040513d602081101561579c57600080fd5b505190505b80156157eb576040805162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b604482015290519081900360640190fd5b7f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb528d8d868d8660405180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001848152602001836001600160a01b03166001600160a01b031681526020018281526020019550505050505060405180910390a16000975092955050505050505b9550959350505050565b60006158996158db565b61313584846158a66158db565b60006158ba670de0b6b3a764000085613ea0565b905060405180602001604052806158d1838661492e565b9052949350505050565b6040518060200160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061592f57805160ff191683800117855561595c565b8280016001018555821561595c579182015b8281111561595c578251825591602001919060010190615941565b50612d239291506159f8565b6040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180606001604052806000815260200160008152602001600081525090565b604080516080810190915280600081526020016000815260200160008152602001600081525090565b61119191905b80821115612d2357600081556001016159fe56fe6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d61726b65744c49515549444154455f4a4f4554524f4c4c45525f43414c43554c4154455f414d4f554e545f5345495a455f4641494c45446d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6e6365696e697469616c2065786368616e67652072617465206d7573742062652067726561746572207468616e207a65726f2e6f6e6c792061646d696e2063616e2073657420636f6c6c61746572616c2063617073657474696e6720696e7465726573742072617465206d6f64656c206661696c65646f6e6c79206a6f6574726f6c6c6572206d617920726567697374657220636f6c6c61746572616c20666f7220757365726f6e6c79207468652061646d696e206d61792063616c6c205f72657369676e496d706c656d656e746174696f6e45524333313536466c617368426f72726f776572496e746572666163652e6f6e466c6173684c6f616eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6f6e6c79206a6f6574726f6c6c6572206d617920756e726567697374657220636f6c6c61746572616c20666f7220757365726f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416d6f756e74496e206d757374206265207a65726f6f6e6c79207468652061646d696e206d61792063616c6c205f6265636f6d65496d706c656d656e746174696f6e1d22042d9eb89f2620572acbf8d85b66fba5a2ca19d166d8659574440175c964666c6173684c6f616e20616d6f756e742073686f756c642062652067726561746572207468616e207a65726fa265627a7a7231582084583a06bf118bd3322820466d19539cbca8d454347d50f670478b8f1dcc210864736f6c63430005100032",
  "devdoc": {
    "author": "Cream",
    "methods": {
      "_acceptAdmin()": {
        "details": "Admin function for pending admin to accept role and update admin",
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "_addReserves(uint256)": {
        "params": {
          "addAmount": "The amount fo underlying token to add as reserves"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "_becomeImplementation(bytes)": {
        "params": {
          "data": "The encoded bytes data for any initialization"
        }
      },
      "_reduceReserves(uint256)": {
        "params": {
          "reduceAmount": "Amount of reduction to reserves"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "_setCollateralCap(uint256)": {
        "params": {
          "newCollateralCap": "New collateral cap for this market. A value of 0 corresponds to no cap."
        }
      },
      "_setInterestRateModel(address)": {
        "details": "Admin function to accrue interest and update the interest rate model",
        "params": {
          "newInterestRateModel": "the new interest rate model to use"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "_setJoetroller(address)": {
        "details": "Admin function to set a new joetroller",
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "_setPendingAdmin(address)": {
        "details": "Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.",
        "params": {
          "newPendingAdmin": "New pending admin."
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "_setProtocolSeizeShare(uint256)": {
        "details": "Admin function to accrue interest and set a new collateral seize share",
        "return": "uint256 0=success, otherwise a failure (see ErrorReport.sol for details)"
      },
      "_setReserveFactor(uint256)": {
        "details": "Admin function to accrue interest and set a new reserve factor",
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "accrueInterest()": {
        "details": "This calculates interest accrued from the last checkpointed timestamp  up to the current timestamp and writes new checkpoint to storage."
      },
      "allowance(address,address)": {
        "params": {
          "owner": "The address of the account which owns the tokens to be spent",
          "spender": "The address of the account which may transfer tokens"
        },
        "return": "The number of tokens allowed to be spent (-1 means infinite)"
      },
      "approve(address,uint256)": {
        "details": "This will overwrite the approval amount for `spender` and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)",
        "params": {
          "amount": "The number of tokens that are approved (-1 means infinite)",
          "spender": "The address of the account which may transfer tokens"
        },
        "return": "Whether or not the approval succeeded"
      },
      "balanceOf(address)": {
        "params": {
          "owner": "The address of the account to query"
        },
        "return": "The number of tokens owned by `owner`"
      },
      "balanceOfUnderlying(address)": {
        "details": "This also accrues interest in a transaction",
        "params": {
          "owner": "The address of the account to query"
        },
        "return": "The amount of underlying owned by `owner`"
      },
      "borrow(uint256)": {
        "params": {
          "borrowAmount": "The amount of the underlying asset to borrow"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "borrowBalanceCurrent(address)": {
        "params": {
          "account": "The address whose balance should be calculated after updating borrowIndex"
        },
        "return": "The calculated balance"
      },
      "borrowBalanceStored(address)": {
        "params": {
          "account": "The address whose balance should be calculated"
        },
        "return": "The calculated balance"
      },
      "borrowRatePerSecond()": {
        "return": "The borrow interest rate per sec, scaled by 1e18"
      },
      "estimateBorrowRatePerSecondAfterChange(uint256,bool)": {
        "return": "The borrow interest rate per sec, scaled by 1e18"
      },
      "estimateSupplyRatePerSecondAfterChange(uint256,bool)": {
        "return": "The supply interest rate per sec, scaled by 1e18"
      },
      "exchangeRateCurrent()": {
        "return": "Calculated exchange rate scaled by 1e18"
      },
      "exchangeRateStored()": {
        "details": "This function does not accrue interest before calculating the exchange rate",
        "return": "Calculated exchange rate scaled by 1e18"
      },
      "flashFee(uint256)": {
        "params": {
          "amount": "amount of token to borrow"
        }
      },
      "flashLoan(address,address,uint256,bytes)": {
        "params": {
          "amount": "The amount of the funds to be loaned",
          "data": "The other data",
          "initiator": "flash loan initiator",
          "receiver": "The receiver address for the funds"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "getAccountSnapshot(address)": {
        "details": "This is used by joetroller to more efficiently perform liquidity checks.",
        "params": {
          "account": "Address of the account to snapshot"
        },
        "return": "(possible error, token balance, borrow balance, exchange rate mantissa)"
      },
      "getCash()": {
        "return": "The quantity of underlying asset owned by this contract"
      },
      "initialize(address,address,address,uint256,string,string,uint8)": {
        "params": {
          "decimals_": "ERC-20 decimal precision of this token",
          "initialExchangeRateMantissa_": "The initial exchange rate, scaled by 1e18",
          "interestRateModel_": "The address of the interest rate model",
          "joetroller_": "The address of the Joetroller",
          "name_": "ERC-20 name of this token",
          "symbol_": "ERC-20 symbol of this token",
          "underlying_": "The address of the underlying asset"
        }
      },
      "initialize(address,address,uint256,string,string,uint8)": {
        "params": {
          "decimals_": "EIP-20 decimal precision of this token",
          "initialExchangeRateMantissa_": "The initial exchange rate, scaled by 1e18",
          "interestRateModel_": "The address of the interest rate model",
          "joetroller_": "The address of the Joetroller",
          "name_": "EIP-20 name of this token",
          "symbol_": "EIP-20 symbol of this token"
        }
      },
      "liquidateBorrow(address,uint256,address)": {
        "params": {
          "borrower": "The borrower of this jToken to be liquidated",
          "jTokenCollateral": "The market in which to seize collateral from the borrower",
          "repayAmount": "The amount of the underlying borrowed asset to repay"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "mint(uint256)": {
        "details": "Accrues interest whether or not the operation succeeds, unless reverted",
        "params": {
          "mintAmount": "The amount of the underlying asset to supply"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "redeem(uint256)": {
        "details": "Accrues interest whether or not the operation succeeds, unless reverted",
        "params": {
          "redeemTokens": "The number of jTokens to redeem into underlying"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "redeemUnderlying(uint256)": {
        "details": "Accrues interest whether or not the operation succeeds, unless reverted",
        "params": {
          "redeemAmount": "The amount of underlying to redeem"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "registerCollateral(address)": {
        "details": "This function could only be called by joetroller.",
        "params": {
          "account": "The account to register"
        },
        "return": "The actual registered amount of collateral"
      },
      "repayBorrow(uint256)": {
        "params": {
          "repayAmount": "The amount to repay"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "repayBorrowBehalf(address,uint256)": {
        "params": {
          "borrower": "the account with the debt being payed off",
          "repayAmount": "The amount to repay"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "seize(address,address,uint256)": {
        "details": "Will fail unless called by another jToken during the process of liquidation. Its absolutely critical to use msg.sender as the borrowed jToken and not a parameter.",
        "params": {
          "borrower": "The account having collateral seized",
          "liquidator": "The account receiving seized collateral",
          "seizeTokens": "The number of jTokens to seize"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "supplyRatePerSecond()": {
        "return": "The supply interest rate per sec, scaled by 1e18"
      },
      "totalBorrowsCurrent()": {
        "return": "The total borrows with interest"
      },
      "transfer(address,uint256)": {
        "params": {
          "amount": "The number of tokens to transfer",
          "dst": "The address of the destination account"
        },
        "return": "Whether or not the transfer succeeded"
      },
      "transferFrom(address,address,uint256)": {
        "params": {
          "amount": "The number of tokens to transfer",
          "dst": "The address of the destination account",
          "src": "The address of the source account"
        },
        "return": "Whether or not the transfer succeeded"
      },
      "unregisterCollateral(address)": {
        "details": "This function could only be called by joetroller.",
        "params": {
          "account": "The account to unregister"
        }
      }
    },
    "title": "Cream's JCollateralCapErc20Delegate Contract"
  },
  "userdoc": {
    "methods": {
      "_acceptAdmin()": {
        "notice": "Accepts transfer of admin rights. msg.sender must be pendingAdmin"
      },
      "_addReserves(uint256)": {
        "notice": "The sender adds to reserves."
      },
      "_becomeImplementation(bytes)": {
        "notice": "Called by the delegator on a delegate to initialize it for duty"
      },
      "_reduceReserves(uint256)": {
        "notice": "Accrues interest and reduces reserves by transferring to admin"
      },
      "_resignImplementation()": {
        "notice": "Called by the delegator on a delegate to forfeit its responsibility"
      },
      "_setCollateralCap(uint256)": {
        "notice": "Set the given collateral cap for the market."
      },
      "_setInterestRateModel(address)": {
        "notice": "accrues interest and updates the interest rate model using _setInterestRateModelFresh"
      },
      "_setJoetroller(address)": {
        "notice": "Sets a new joetroller for the market"
      },
      "_setPendingAdmin(address)": {
        "notice": "Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer."
      },
      "_setProtocolSeizeShare(uint256)": {
        "notice": "Accrues interest and sets a new collateral seize share for the protocol using _setProtocolSeizeShareFresh"
      },
      "_setReserveFactor(uint256)": {
        "notice": "Accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh"
      },
      "accrueInterest()": {
        "notice": "Applies accrued interest to total borrows and reserves"
      },
      "allowance(address,address)": {
        "notice": "Get the current allowance from `owner` for `spender`"
      },
      "approve(address,uint256)": {
        "notice": "Approve `spender` to transfer up to `amount` from `src`"
      },
      "balanceOf(address)": {
        "notice": "Get the token balance of the `owner`"
      },
      "balanceOfUnderlying(address)": {
        "notice": "Get the underlying balance of the `owner`"
      },
      "borrow(uint256)": {
        "notice": "Sender borrows assets from the protocol to their own address"
      },
      "borrowBalanceCurrent(address)": {
        "notice": "Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex"
      },
      "borrowBalanceStored(address)": {
        "notice": "Return the borrow balance of account based on stored data"
      },
      "borrowRatePerSecond()": {
        "notice": "Returns the current per-sec borrow interest rate for this jToken"
      },
      "constructor": "Construct an empty delegate",
      "estimateBorrowRatePerSecondAfterChange(uint256,bool)": {
        "notice": "Returns the estimated per-sec borrow interest rate for this jToken after some change"
      },
      "estimateSupplyRatePerSecondAfterChange(uint256,bool)": {
        "notice": "Returns the estimated per-sec supply interest rate for this jToken after some change"
      },
      "exchangeRateCurrent()": {
        "notice": "Accrue interest then return the up-to-date exchange rate"
      },
      "exchangeRateStored()": {
        "notice": "Calculates the exchange rate from the underlying to the JToken"
      },
      "flashFee(uint256)": {
        "notice": "Get the flash loan fees"
      },
      "flashLoan(address,address,uint256,bytes)": {
        "notice": "Flash loan funds to a given account."
      },
      "getAccountSnapshot(address)": {
        "notice": "Get a snapshot of the account's balances, and the cached exchange rate"
      },
      "getCash()": {
        "notice": "Get cash balance of this jToken in the underlying asset"
      },
      "gulp()": {
        "notice": "Absorb excess cash into reserves."
      },
      "initialize(address,address,address,uint256,string,string,uint8)": {
        "notice": "Initialize the new money market"
      },
      "initialize(address,address,uint256,string,string,uint8)": {
        "notice": "Initialize the money market"
      },
      "liquidateBorrow(address,uint256,address)": {
        "notice": "The sender liquidates the borrowers collateral. The collateral seized is transferred to the liquidator."
      },
      "maxFlashLoan()": {
        "notice": "Get the max flash loan amount"
      },
      "mint(uint256)": {
        "notice": "Sender supplies assets into the market and receives jTokens in exchange"
      },
      "redeem(uint256)": {
        "notice": "Sender redeems jTokens in exchange for the underlying asset"
      },
      "redeemUnderlying(uint256)": {
        "notice": "Sender redeems jTokens in exchange for a specified amount of underlying asset"
      },
      "registerCollateral(address)": {
        "notice": "Register account collateral tokens if there is space."
      },
      "repayBorrow(uint256)": {
        "notice": "Sender repays their own borrow"
      },
      "repayBorrowBehalf(address,uint256)": {
        "notice": "Sender repays a borrow belonging to borrower"
      },
      "seize(address,address,uint256)": {
        "notice": "Transfers collateral tokens (this market) to the liquidator."
      },
      "supplyRatePerSecond()": {
        "notice": "Returns the current per-sec supply interest rate for this jToken"
      },
      "totalBorrowsCurrent()": {
        "notice": "Returns the current total borrows plus accrued interest"
      },
      "transfer(address,uint256)": {
        "notice": "Transfer `amount` tokens from `msg.sender` to `dst`"
      },
      "transferFrom(address,address,uint256)": {
        "notice": "Transfer `amount` tokens from `src` to `dst`"
      },
      "unregisterCollateral(address)": {
        "notice": "Unregister account collateral tokens if the account still has enough collateral."
      }
    },
    "notice": "JTokens which wrap an EIP-20 underlying and are delegated to"
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 15048,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "_notEntered",
        "offset": 0,
        "slot": "0",
        "type": "t_bool"
      },
      {
        "astId": 15050,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "name",
        "offset": 0,
        "slot": "1",
        "type": "t_string_storage"
      },
      {
        "astId": 15052,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "symbol",
        "offset": 0,
        "slot": "2",
        "type": "t_string_storage"
      },
      {
        "astId": 15054,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "decimals",
        "offset": 0,
        "slot": "3",
        "type": "t_uint8"
      },
      {
        "astId": 15062,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "admin",
        "offset": 1,
        "slot": "3",
        "type": "t_address_payable"
      },
      {
        "astId": 15064,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "pendingAdmin",
        "offset": 0,
        "slot": "4",
        "type": "t_address_payable"
      },
      {
        "astId": 15066,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "joetroller",
        "offset": 0,
        "slot": "5",
        "type": "t_contract(JoetrollerInterface)21490"
      },
      {
        "astId": 15068,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "interestRateModel",
        "offset": 0,
        "slot": "6",
        "type": "t_contract(InterestRateModel)2453"
      },
      {
        "astId": 15070,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "initialExchangeRateMantissa",
        "offset": 0,
        "slot": "7",
        "type": "t_uint256"
      },
      {
        "astId": 15072,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "reserveFactorMantissa",
        "offset": 0,
        "slot": "8",
        "type": "t_uint256"
      },
      {
        "astId": 15074,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "accrualBlockTimestamp",
        "offset": 0,
        "slot": "9",
        "type": "t_uint256"
      },
      {
        "astId": 15076,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "borrowIndex",
        "offset": 0,
        "slot": "10",
        "type": "t_uint256"
      },
      {
        "astId": 15078,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "totalBorrows",
        "offset": 0,
        "slot": "11",
        "type": "t_uint256"
      },
      {
        "astId": 15080,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "totalReserves",
        "offset": 0,
        "slot": "12",
        "type": "t_uint256"
      },
      {
        "astId": 15082,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "totalSupply",
        "offset": 0,
        "slot": "13",
        "type": "t_uint256"
      },
      {
        "astId": 15086,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "accountTokens",
        "offset": 0,
        "slot": "14",
        "type": "t_mapping(t_address,t_uint256)"
      },
      {
        "astId": 15092,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "transferAllowances",
        "offset": 0,
        "slot": "15",
        "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))"
      },
      {
        "astId": 15101,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "accountBorrows",
        "offset": 0,
        "slot": "16",
        "type": "t_mapping(t_address,t_struct(BorrowSnapshot)15097_storage)"
      },
      {
        "astId": 15104,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "underlying",
        "offset": 0,
        "slot": "17",
        "type": "t_address"
      },
      {
        "astId": 15106,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "implementation",
        "offset": 0,
        "slot": "18",
        "type": "t_address"
      },
      {
        "astId": 15109,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "internalCash",
        "offset": 0,
        "slot": "19",
        "type": "t_uint256"
      },
      {
        "astId": 15112,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "totalCollateralTokens",
        "offset": 0,
        "slot": "20",
        "type": "t_uint256"
      },
      {
        "astId": 15116,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "accountCollateralTokens",
        "offset": 0,
        "slot": "21",
        "type": "t_mapping(t_address,t_uint256)"
      },
      {
        "astId": 15120,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "isCollateralTokenInit",
        "offset": 0,
        "slot": "22",
        "type": "t_mapping(t_address,t_bool)"
      },
      {
        "astId": 15122,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "collateralCap",
        "offset": 0,
        "slot": "23",
        "type": "t_uint256"
      },
      {
        "astId": 15685,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "protocolSeizeShareMantissa",
        "offset": 0,
        "slot": "24",
        "type": "t_uint256"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_address_payable": {
        "encoding": "inplace",
        "label": "address payable",
        "numberOfBytes": "20"
      },
      "t_bool": {
        "encoding": "inplace",
        "label": "bool",
        "numberOfBytes": "1"
      },
      "t_contract(InterestRateModel)2453": {
        "encoding": "inplace",
        "label": "contract InterestRateModel",
        "numberOfBytes": "20"
      },
      "t_contract(JoetrollerInterface)21490": {
        "encoding": "inplace",
        "label": "contract JoetrollerInterface",
        "numberOfBytes": "20"
      },
      "t_mapping(t_address,t_bool)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => bool)",
        "numberOfBytes": "32",
        "value": "t_bool"
      },
      "t_mapping(t_address,t_mapping(t_address,t_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(BorrowSnapshot)15097_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct JTokenStorage.BorrowSnapshot)",
        "numberOfBytes": "32",
        "value": "t_struct(BorrowSnapshot)15097_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(BorrowSnapshot)15097_storage": {
        "encoding": "inplace",
        "label": "struct JTokenStorage.BorrowSnapshot",
        "members": [
          {
            "astId": 15094,
            "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
            "label": "principal",
            "offset": 0,
            "slot": "0",
            "type": "t_uint256"
          },
          {
            "astId": 15096,
            "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
            "label": "interestIndex",
            "offset": 0,
            "slot": "1",
            "type": "t_uint256"
          }
        ],
        "numberOfBytes": "64"
      },
      "t_uint256": {
        "encoding": "inplace",
        "label": "uint256",
        "numberOfBytes": "32"
      },
      "t_uint8": {
        "encoding": "inplace",
        "label": "uint8",
        "numberOfBytes": "1"
      }
    }
  }
}