{
  "address": "0x737Fdfb2365973474beFA244953954c5B6Fddf34",
  "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": "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": "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": 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": "0x3664e63fa753658820f8240730375299a3abb6f8ae15aec5c41d9ff02bf87967",
  "receipt": {
    "to": null,
    "from": "0x5D3e4C0FE11e0aE4c32F0FF74B4544C49538AC61",
    "contractAddress": "0x737Fdfb2365973474beFA244953954c5B6Fddf34",
    "transactionIndex": 0,
    "gasUsed": "5011305",
    "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0xec7f08fda515a2526446686cab3e986445de355bd0c584baa7968ecce32f9e2e",
    "transactionHash": "0x3664e63fa753658820f8240730375299a3abb6f8ae15aec5c41d9ff02bf87967",
    "logs": [],
    "blockNumber": 5450039,
    "cumulativeGasUsed": "5011305",
    "status": 1,
    "byzantium": true
  },
  "args": [],
  "solcInputHash": "c440a949314987df51e16ffd601dd0e9",
  "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\":\"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\":\"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\":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)\"},\"_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.\"},\"_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    }\\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\":\"0xfd925241bedc5827af65ee2b0bc1fd7dfffde643de26d55164a442e0ef538f32\"},\"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 {\\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         * 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        /* 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        if (collateralTokens > 0) {\\n            decreaseUserCollateralInternal(redeemer, collateralTokens);\\n        }\\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        /*\\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], seizeTokens);\\n        accountCollateralTokens[borrower] = sub_(accountCollateralTokens[borrower], seizeTokens);\\n        accountCollateralTokens[liquidator] = add_(accountCollateralTokens[liquidator], seizeTokens);\\n\\n        /* Emit a Transfer, UserCollateralChanged events */\\n        emit Transfer(borrower, liquidator, seizeTokens);\\n        emit UserCollateralChanged(borrower, accountCollateralTokens[borrower]);\\n        emit UserCollateralChanged(liquidator, accountCollateralTokens[liquidator]);\\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\",\"keccak256\":\"0x05d7f9dfc6a1edac18a3ab303778e88a4a5d1e7cdfcf75768d5fb535c4d142e0\"},\"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].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].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\":\"0xadb7beb794059473975fb5d68c360089cef7ad528dfc38ed8190fc84f75251e1\"},\"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\",\"keccak256\":\"0xccc6ce54828a1d47cc7db8468358a68964e4f69983c6824ef60b7eb95fc380d1\"},\"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": "0x608060405234801561001057600080fd5b506159b280620000216000396000f3fe608060405234801561001057600080fd5b50600436106103e65760003560e01c806381cf00eb1161020a578063b2a02ff111610125578063db006a75116100b8578063f2b3abbd11610087578063f2b3abbd14610dad578063f3fdb15a14610dd3578063f5e3c46214610ddb578063f851a44014610e11578063fca7820b14610e19576103e6565b8063db006a7514610d52578063dd62ed3e14610d6f578063e9c714f214610d9d578063ea11eea414610da5576103e6565b8063c5ebeaec116100f4578063c5ebeaec14610cff578063cfa9920114610d1c578063d240d64a14610d24578063d2bb18e914610d4a576103e6565b8063b2a02ff114610c4f578063b71d1a0c14610c85578063bd6d894d14610cab578063c37f68e214610cb3576103e6565b806395dd91931161019d578063a7af467a1161016c578063a7af467a14610bf6578063a9059cbb14610c13578063aa5af0fd14610c3f578063b1d3897414610c47576103e6565b806395dd919314610a5d57806399d8c1b414610a83578063a0712d6814610bd1578063a6afed9514610bee576103e6565b80638b35776b116101d95780638b35776b14610a1f5780638f840ddd14610a4557806394909e6214610a4d57806395d89b4114610a55576103e6565b806381cf00eb14610999578063852a12e3146109b657806385d8a2e6146109d35780638897bd85146109f9576103e6565b8063313ce567116103055780635260975011610298578063601a0bf111610267578063601a0bf11461093e5780636330533c1461095b5780636f307dc31461096357806370a082311461096b57806373acee9814610991576103e6565b806352609750146107fc57806356e67728146108045780635c60da1b146108a85780635cffe9de146108b0576103e6565b8063406de0b6116102d4578063406de0b6146107a1578063432f4b2d146107a957806347bd3718146107cf57806350f6e082146107d7576103e6565b8063313ce567146107385780633af9e669146107565780633b1d21a21461077c5780633e94101014610784576103e6565b8063182df0f51161037d57806323b872dd1161034c57806323b872dd146106aa578063242c127c146106e05780632608f818146106e85780632678224714610714576103e6565b8063182df0f51461053c57806319a4dd3c146105445780631a31d4651461054c57806322abdbf5146106a2576103e6565b8063153ab505116103b9578063153ab505146104fc578063173b99041461050657806317bfdfbc1461050e57806318160ddd14610534576103e6565b806306fdde03146103eb578063095ea7b3146104685780630e752702146104a85780630f3e4e11146104d7575b600080fd5b6103f3610e36565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561042d578181015183820152602001610415565b50505050905090810190601f16801561045a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104946004803603604081101561047e57600080fd5b506001600160a01b038135169060200135610ec3565b604080519115158252519081900360200190f35b6104c5600480360360208110156104be57600080fd5b5035610f30565b60408051918252519081900360200190f35b6104c5600480360360408110156104ed57600080fd5b50803590602001351515610f48565b61050461102d565b005b6104c561107d565b6104c56004803603602081101561052457600080fd5b50356001600160a01b0316611083565b6104c5611143565b6104c5611149565b6104c5611159565b610504600480360360e081101561056257600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b8111156105a457600080fd5b8201836020820111156105b657600080fd5b803590602001918460018302840111600160201b831117156105d757600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561062957600080fd5b82018360208201111561063b57600080fd5b803590602001918460018302840111600160201b8311171561065c57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061115f9050565b6104c56111fe565b610494600480360360608110156106c057600080fd5b506001600160a01b03813581169160208101359091169060400135611204565b6104c5611276565b6104c5600480360360408110156106fe57600080fd5b506001600160a01b03813516906020013561131b565b61071c611333565b604080516001600160a01b039092168252519081900360200190f35b610740611342565b6040805160ff9092168252519081900360200190f35b6104c56004803603602081101561076c57600080fd5b50356001600160a01b031661134b565b6104c5611398565b6104c56004803603602081101561079a57600080fd5b50356113a2565b6104946113af565b6104c5600480360360208110156107bf57600080fd5b50356001600160a01b03166113b4565b6104c5611508565b6104c5600480360360408110156107ed57600080fd5b5080359060200135151561150e565b6104c56115bd565b6105046004803603602081101561081a57600080fd5b810190602081018135600160201b81111561083457600080fd5b82018360208201111561084657600080fd5b803590602001918460018302840111600160201b8311171561086757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611652945050505050565b61071c611719565b610494600480360360808110156108c657600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561090057600080fd5b82018360208201111561091257600080fd5b803590602001918460018302840111600160201b8311171561093357600080fd5b509092509050611728565b6104c56004803603602081101561095457600080fd5b5035611c6c565b61071c611d07565b61071c611d16565b6104c56004803603602081101561098157600080fd5b50356001600160a01b0316611d25565b6104c5611d40565b610504600480360360208110156109af57600080fd5b5035611df6565b6104c5600480360360208110156109cc57600080fd5b5035611e87565b610494600480360360208110156109e957600080fd5b50356001600160a01b0316611e94565b6104c560048036036020811015610a0f57600080fd5b50356001600160a01b0316611ea9565b61050460048036036020811015610a3557600080fd5b50356001600160a01b0316611f37565b6104c5611fb0565b610504611fb6565b6103f361204b565b6104c560048036036020811015610a7357600080fd5b50356001600160a01b03166120a3565b610504600480360360c0811015610a9957600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610ad357600080fd5b820183602082011115610ae557600080fd5b803590602001918460018302840111600160201b83111715610b0657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b5857600080fd5b820183602082011115610b6a57600080fd5b803590602001918460018302840111600160201b83111715610b8b57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff1691506120ae9050565b6104c560048036036020811015610be757600080fd5b5035612295565b6104c56122a3565b6104c560048036036020811015610c0c57600080fd5b50356124b3565b61049460048036036040811015610c2957600080fd5b506001600160a01b0381351690602001356125a5565b6104c5612617565b6104c561261d565b6104c560048036036060811015610c6557600080fd5b506001600160a01b0381358116916020810135909116906040013561268b565b6104c560048036036020811015610c9b57600080fd5b50356001600160a01b03166126fc565b6104c5612788565b610cd960048036036020811015610cc957600080fd5b50356001600160a01b0316612844565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6104c560048036036020811015610d1557600080fd5b5035612880565b6104c561288d565b6104c560048036036020811015610d3a57600080fd5b50356001600160a01b0316612893565b6104c56128a5565b6104c560048036036020811015610d6857600080fd5b50356128ab565b6104c560048036036040811015610d8557600080fd5b506001600160a01b03813581169160200135166128b8565b6104c56128e3565b6104c56129e6565b6104c560048036036020811015610dc357600080fd5b50356001600160a01b03166129eb565b61071c612a25565b6104c560048036036060811015610df157600080fd5b506001600160a01b03813581169160208101359160409091013516612a34565b61071c612a4e565b6104c560048036036020811015610e2f57600080fd5b5035612a62565b60018054604080516020600284861615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610ebb5780601f10610e9057610100808354040283529160200191610ebb565b820191906000526020600020905b815481529060010190602001808311610e9e57829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855290835281842086905581518681529151939493909284927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a360019150505b92915050565b600080610f3e836000612ae0565b509150505b919050565b60008060008315610f7957610f64610f5e612b8c565b86612b92565b9150610f72600b5486612bc8565b9050610f9b565b610f8a610f84612b8c565b86612bc8565b9150610f98600b5486612b92565b90505b600654600c54604080516315f2405360e01b815260048101869052602481018590526044810192909252516001600160a01b03909216916315f2405391606480820192602092909190829003018186803b158015610ff857600080fd5b505afa15801561100c573d6000803e3d6000fd5b505050506040513d602081101561102257600080fd5b505195945050505050565b60035461010090046001600160a01b0316331461107b5760405162461bcd60e51b815260040180806020018281038252602d815260200180615829602d913960400191505060405180910390fd5b565b60085481565b6000805460ff166110c8576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556110da6122a3565b14611125576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b61112e826120a3565b90505b6000805460ff19166001179055919050565b600d5481565b6000611153612c02565b90505b90565b60145481565b61116d8686868686866120ae565b601180546001600160a01b0319166001600160a01b038981169190911791829055604080516318160ddd60e01b8152905192909116916318160ddd91600480820192602092909190829003018186803b1580156111c957600080fd5b505afa1580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b505050505050505050565b60135481565b6000805460ff16611249576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561125f33868686612c68565b1490506000805460ff191660011790559392505050565b600554604080516358d5bc7360e11b81523060048201526000602482018190526044820181905260806064830152608482018190529151919283926001600160a01b039091169163b1ab78e69160c4808301926020929190829003018186803b1580156112e257600080fd5b505afa1580156112f6573d6000803e3d6000fd5b505050506040513d602081101561130c57600080fd5b50511561115357610f2a612b8c565b60008061132a84846000612fb4565b50949350505050565b6004546001600160a01b031681565b60035460ff1681565b60006113556155d5565b6040518060200160405280611368612788565b90526001600160a01b0384166000908152600e6020526040902054909150611391908290613061565b9392505050565b6000611153612b8c565b6000610f2a826000613080565b600181565b60035460009061010090046001600160a01b031633146113e1576113da6001602961311e565b9050610f43565b600554604080516340e6dcc560e01b815290516001600160a01b03928316928516916340e6dcc5916004808301926020929190829003018186803b15801561142857600080fd5b505afa15801561143c573d6000803e3d6000fd5b505050506040513d602081101561145257600080fd5b50516114a5576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517f17d6db5ffe5a3d1c3d7a98194dca4f7d808d621e6ff9077ed574513d553a2a859281900390910190a16000611391565b600b5481565b6000806000831561153957611524610f5e612b8c565b9150611532600b5486612bc8565b9050611555565b611544610f84612b8c565b9150611552600b5486612b92565b90505b600654600c5460085460408051635c0b440b60e11b8152600481018790526024810186905260448101939093526064830191909152516001600160a01b039092169163b816881691608480820192602092909190829003018186803b158015610ff857600080fd5b6006546000906001600160a01b03166315f240536115d9612b8c565b600b54600c546040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b15801561162157600080fd5b505afa158015611635573d6000803e3d6000fd5b505050506040513d602081101561164b57600080fd5b5051905090565b60035461010090046001600160a01b031633146116a05760405162461bcd60e51b815260040180806020018281038252602d815260200180615905602d913960400191505060405180910390fd5b6116a8613184565b601355600554604080516303c03f0f60e01b81523060048201526001602482015290516001600160a01b03909216916303c03f0f9160448082019260009290919082900301818387803b1580156116fe57600080fd5b505af1158015611712573d6000803e3d6000fd5b5050505050565b6012546001600160a01b031681565b6000805460ff1661176d576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19169055836117b35760405162461bcd60e51b815260040180806020018281038252602c815260200180615952602c913960400191505060405180910390fd5b60006117bd6122a3565b14611808576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b6005546040516358d5bc7360e11b815230600482018181526001600160a01b038a81166024850152604484018990526080606485019081526084850188905294169363b1ab78e6938b928a928a928a92919060a401848480828437600081840152601f19601f820116905080830192505050965050505050505060206040518083038186803b15801561189a57600080fd5b505afa1580156118ae573d6000803e3d6000fd5b505050506040513d60208110156118c457600080fd5b505161190d576040805162461bcd60e51b8152602060048201526013602482015272199b185cda1b1bd85b881a5cc81c185d5cd959606a1b604482015290519081900360640190fd5b6000611917613184565b90506000611923612b8c565b905085811015611973576040805162461bcd60e51b8152602060048201526016602482015275494e53554646494349454e545f4c495155494449545960501b604482015290519081900360640190fd5b6000306001600160a01b031663a7af467a886040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156119b957600080fd5b505afa1580156119cd573d6000803e3d6000fd5b505050506040513d60208110156119e357600080fd5b505190506119f389886000613204565b6119ff600b5488612b92565b600b5560405180602961585682396040519081900360290181206011546323e30c8b60e01b83526001600160a01b038c81166004850190815291811660248501819052604485018d90526064850187905260a06084860190815260a486018c9052939550908e16936323e30c8b938e938e9289928f928f9290919060c401848480828437600081840152601f19601f820116905080830192505050975050505050505050602060405180830381600087803b158015611abd57600080fd5b505af1158015611ad1573d6000803e3d6000fd5b505050506040513d6020811015611ae757600080fd5b505114611b3b576040805162461bcd60e51b815260206004820152601960248201527f49455243333135363a2043616c6c6261636b206661696c656400000000000000604482015290519081900360640190fd5b6000611b478883612b92565b9050611b558a82600061330b565b506000611b60613184565b9050611b6c8584612b92565b8114611bb6576040805162461bcd60e51b8152602060048201526014602482015273109053105390d157d25390d3d394d254d511539560621b604482015290519081900360640190fd5b6000611bd2604051806020016040528060085481525085613061565b9050611be0600c5482612b92565b600c55611bed8585612b92565b601355600b54611bfd908b612bc8565b600b55604080518b81526020810186905280820183905290516001600160a01b038e16917f33c8e097c526683cbdb29adf782fac95e9d0fbe0ed635c13d8c75fdf726557d9919081900360600190a2600196505050505050506000805460ff1916600117905595945050505050565b6000805460ff16611cb1576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611cc36122a3565b90508015611ce957611ce1816010811115611cda57fe5b601d61311e565b915050611131565b611cf28361351c565b9150506000805460ff19166001179055919050565b6005546001600160a01b031681565b6011546001600160a01b031681565b6001600160a01b03166000908152600e602052604090205490565b6000805460ff16611d85576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611d976122a3565b14611de2576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b50600b546000805460ff1916600117905590565b60035461010090046001600160a01b03163314611e445760405162461bcd60e51b81526004018080602001828103825260218152602001806157b66021913960400191505060405180910390fd5b6017819055604080513081526020810183905281517f01b7c780e0f385803fe80cbe0efc086d13b8eb443a2ce43e2061fd92bc0e34f1929181900390910190a150565b6000610f2a82600061361a565b60166020526000908152604090205460ff1681565b6000611eb4826136b2565b6005546001600160a01b03163314611efd5760405162461bcd60e51b81526004018080602001828103825260308152602001806157f96030913960400191505060405180910390fd5b6001600160a01b0382166000908152600e60209081526040808320546015909252822054611f2b9190612bc8565b905061139183826137f4565b611f40816136b2565b6005546001600160a01b03163314611f895760405162461bcd60e51b815260040180806020018281038252603281526020018061589f6032913960400191505060405180910390fd5b6001600160a01b038116600090815260156020526040902054611fad90829061393f565b50565b600c5481565b60005460ff16611ffa576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561200c613184565b90506000612018612b8c565b905060006120268383612bc8565b9050612034600c5482612b92565b600c5550506013556000805460ff19166001179055565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610ebb5780601f10610e9057610100808354040283529160200191610ebb565b6000610f2a82613a96565b60035461010090046001600160a01b031633146120fc5760405162461bcd60e51b815260040180806020018281038252602481526020018061570d6024913960400191505060405180910390fd5b60095415801561210c5750600a54155b6121475760405162461bcd60e51b81526004018080602001828103825260238152602001806157636023913960400191505060405180910390fd5b6007849055836121885760405162461bcd60e51b81526004018080602001828103825260308152602001806157866030913960400191505060405180910390fd5b6000612193876113b4565b905080156121e8576040805162461bcd60e51b815260206004820152601960248201527f73657474696e67206a6f6574726f6c6c6572206661696c656400000000000000604482015290519081900360640190fd5b6121f0613aeb565b600955670de0b6b3a7640000600a5561220886613aef565b905080156122475760405162461bcd60e51b81526004018080602001828103825260228152602001806157d76022913960400191505060405180910390fd5b835161225a9060019060208701906155e8565b50825161226e9060029060208601906155e8565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b600080610f3e836000613c64565b6000806122ae613aeb565b600954909150808214156122c757600092505050611156565b60006122d1612b8c565b600b54600c54600a54600654604080516315f2405360e01b815260048101879052602481018690526044810185905290519596509394929391926000926001600160a01b03909216916315f24053916064808301926020929190829003018186803b15801561233f57600080fd5b505afa158015612353573d6000803e3d6000fd5b505050506040513d602081101561236957600080fd5b5051905065048c273950008111156123c8576040805162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c79206869676800000000604482015290519081900360640190fd5b60006123d48888612bc8565b90506123de6155d5565b6123f660405180602001604052808581525083613ce6565b905060006124048288613061565b905060006124128289612b92565b905060006124316040518060200160405280600854815250848a613d10565b9050600061244085898a613d10565b60098e9055600a819055600b849055600c839055604080518d8152602081018790528082018390526060810186905290519192507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc04919081900360800190a160009d505050505050505050505050505090565b600554604080516358d5bc7360e11b8152306004820152600060248201819052604482018590526080606483015260848201819052915191926001600160a01b03169163b1ab78e69160c480820192602092909190829003018186803b15801561251c57600080fd5b505afa158015612530573d6000803e3d6000fd5b505050506040513d602081101561254657600080fd5b505161258f576040805162461bcd60e51b8152602060048201526013602482015272199b185cda1b1bd85b881a5cc81c185d5cd959606a1b604482015290519081900360640190fd5b610f2a61259d836008613d38565b612710613d7a565b6000805460ff166125ea576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561260033338686612c68565b1490505b6000805460ff1916600117905592915050565b600a5481565b6006546000906001600160a01b031663b8168816612639612b8c565b600b54600c546008546040518563ffffffff1660e01b81526004018085815260200184815260200183815260200182815260200194505050505060206040518083038186803b15801561162157600080fd5b6000805460ff166126d0576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191690556126e633858585613dad565b90506000805460ff191660011790559392505050565b60035460009061010090046001600160a01b03163314612722576113da6001602f61311e565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a16000611391565b6000805460ff166127cd576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556127df6122a3565b1461282a576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b612832611149565b90506000805460ff1916600117905590565b600080600080600061285586614033565b9050600061286287613a96565b9050600061286e612c02565b90506000989297509095509350915050565b6000610f2a826000614092565b60095481565b60156020526000908152604090205481565b60175481565b6000610f2a826000614112565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6004546000906001600160a01b0316331415806128fe575033155b156129165761290f6001600061311e565b9050611156565b60038054600480546001600160a01b03818116610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401528351909391927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600454604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160009250505090565b600881565b6000806129f66122a3565b90508015612a1c57612a14816010811115612a0d57fe5b602a61311e565b915050610f43565b61139183613aef565b6006546001600160a01b031681565b600080612a44858585600061418d565b5095945050505050565b60035461010090046001600160a01b031681565b6000805460ff16612aa7576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612ab96122a3565b90508015612ad757611ce1816010811115612ad057fe5b603061311e565b611cf2836142c1565b60008054819060ff16612b27576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612b396122a3565b90508015612b6457612b57816010811115612b5057fe5b602361311e565b925060009150612b769050565b612b7033338787614369565b92509250505b6000805460ff1916600117905590939092509050565b60135490565b60006113918383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b81525061460b565b60006113918383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061469d565b600d5460009080612c17575050600754611156565b6000612c21612b8c565b90506000612c3c612c3483600b54612b92565b600c54612bc8565b90506000612c58826040518060200160405280878152506146f7565b94506111569350505050565b5090565b6000612c73846136b2565b612c7c836136b2565b6001600160a01b0384166000908152600e60209081526040808320546015909252822054612caa9190612bc8565b9050600081841115612cbb57508083035b600554604080516317b9b84b60e31b81523060048201526001600160a01b0389811660248301528881166044830152606482018590529151600093929092169163bdcdc2589160848082019260209290919082900301818787803b158015612d2257600080fd5b505af1158015612d36573d6000803e3d6000fd5b505050506040513d6020811015612d4c57600080fd5b505190508015612d6d57612d636003603483614715565b9350505050612fac565b856001600160a01b0316876001600160a01b03161415612d9357612d636002603561311e565b60006001600160a01b038981169089161415612db25750600019612dda565b506001600160a01b038088166000908152600f60209081526040808320938c16835292905220545b6001600160a01b0388166000908152600e6020526040902054612dfd9087612bc8565b6001600160a01b03808a166000908152600e60205260408082209390935590891681522054612e2c9087612b92565b6001600160a01b0388166000908152600e60205260409020558215612f30576001600160a01b038816600090815260156020526040902054612e6e9084612bc8565b6001600160a01b03808a166000908152601560205260408082209390935590891681522054612e9d9084612b92565b6001600160a01b03808916600090815260156020908152604080832094909455918b1680825290839020548351918252918101919091528151600080516020615932833981519152929181900390910190a16001600160a01b0387166000818152601560209081526040918290205482519384529083015280516000805160206159328339815191529281900390910190a15b6000198114612f6a57612f438187612bc8565b6001600160a01b03808a166000908152600f60209081526040808320938e16835292905220555b866001600160a01b0316886001600160a01b031660008051602061587f833981519152886040518082815260200191505060405180910390a360009450505050505b949350505050565b60008054819060ff16612ffb576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561300d6122a3565b905080156130385761302b81601081111561302457fe5b602261311e565b92506000915061304a9050565b61304433878787614369565b92509250505b6000805460ff191660011790559094909350915050565b600061306b6155d5565b6130758484613ce6565b9050612fac8161477b565b6000805460ff166130c5576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556130d76122a3565b905080156130fd576130f58160108111156130ee57fe5b603661311e565b915050612604565b613107848461478a565b509150506000805460ff1916600117905592915050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601081111561314d57fe5b83603881111561315957fe5b604080519283526020830191909152600082820152519081900360600190a182601081111561139157fe5b601154604080516370a0823160e01b815230600482015290516000926001600160a01b03169182916370a0823191602480820192602092909190829003018186803b1580156131d257600080fd5b505afa1580156131e6573d6000803e3d6000fd5b505050506040513d60208110156131fc57600080fd5b505191505090565b6011546040805163a9059cbb60e01b81526001600160a01b0386811660048301526024820186905291519190921691829163a9059cbb9160448082019260009290919082900301818387803b15801561325c57600080fd5b505af1158015613270573d6000803e3d6000fd5b5050505060003d6000811461328c576020811461329657600080fd5b60001991506132a2565b60206000803e60005191505b50806132f5576040805162461bcd60e51b815260206004820152601960248201527f544f4b454e5f5452414e534645525f4f55545f4641494c454400000000000000604482015290519081900360640190fd5b61330160135485612bc8565b6013555050505050565b601154604080516370a0823160e01b815230600482015290516000926001600160a01b031691839183916370a08231916024808301926020929190829003018186803b15801561335a57600080fd5b505afa15801561336e573d6000803e3d6000fd5b505050506040513d602081101561338457600080fd5b5051604080516323b872dd60e01b81526001600160a01b038981166004830152306024830152604482018990529151929350908416916323b872dd9160648082019260009290919082900301818387803b1580156133e157600080fd5b505af11580156133f5573d6000803e3d6000fd5b5050505060003d60008114613411576020811461341b57600080fd5b6000199150613427565b60206000803e60005191505b508061347a576040805162461bcd60e51b815260206004820152601860248201527f544f4b454e5f5452414e534645525f494e5f4641494c45440000000000000000604482015290519081900360640190fd5b601154604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156134c557600080fd5b505afa1580156134d9573d6000803e3d6000fd5b505050506040513d60208110156134ef57600080fd5b5051905060006134ff8285612bc8565b905061350d60135482612b92565b60135598975050505050505050565b600354600090819061010090046001600160a01b0316331461354457612a146001601e61311e565b61354c613aeb565b6009541461356057612a14600a602061311e565b82613569612b8c565b101561357b57612a14600e601f61311e565b600c5483111561359157612a146002602161311e565b61359d600c5484612bc8565b600c8190556003549091506135c29061010090046001600160a01b0316846001613204565b600354604080516101009092046001600160a01b0316825260208201859052818101839052517f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e916060908290030190a16000611391565b6000805460ff1661365f576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556136716122a3565b9050801561368f576130f581601081111561368857fe5b601961311e565b61369c3360008686614828565b9150506000805460ff1916600117905592915050565b6001600160a01b03811660009081526016602052604090205460ff16611fad576005546040805163929fe9a160e01b81526001600160a01b0384811660048301523060248301529151919092169163929fe9a1916044808301926020929190829003018186803b15801561372557600080fd5b505afa158015613739573d6000803e3d6000fd5b505050506040513d602081101561374f57600080fd5b5051156137ce576001600160a01b0381166000908152600e602081815260408084205460158352932083905560145491905261378a91612b92565b6014556001600160a01b0381166000818152601560209081526040918290205482519384529083015280516000805160206159328339815191529281900390910190a15b6001600160a01b0381166000908152601660205260409020805460ff1916600117905550565b60008061380360145484612b92565b90506017546000148061382457506017541580159061382457506017548111155b1561389f5760148190556001600160a01b0384166000908152601560205260409020546138519084612b92565b6001600160a01b03851660008181526015602090815260409182902084905581519283528201929092528151600080516020615932833981519152929181900390910190a182915050610f2a565b60145460175411156139355760006138bb601754601454612bc8565b6017546014556001600160a01b0386166000908152601560205260409020549091506138e79082612b92565b6001600160a01b03861660008181526015602090815260409182902084905581519283528201929092528151600080516020615932833981519152929181900390910190a19150610f2a9050565b5060009392505050565b6005546040805163eabe7d9160e01b81523060048201526001600160a01b038581166024830152604482018590529151919092169163eabe7d919160648083019260209291908290030181600087803b15801561399b57600080fd5b505af11580156139af573d6000803e3d6000fd5b505050506040513d60208110156139c557600080fd5b505115613a10576040805162461bcd60e51b81526020600482015260146024820152733537b2ba3937b63632b9103932b532b1ba34b7b760611b604482015290519081900360640190fd5b80613a1a57613a92565b613a2660145482612bc8565b6014556001600160a01b038216600090815260156020526040902054613a4c9082612bc8565b6001600160a01b03831660008181526015602090815260409182902084905581519283528201929092528151600080516020615932833981519152929181900390910190a15b5050565b6001600160a01b03811660009081526010602052604081208054613abe576000915050610f43565b6000613ad08260000154600a54613d38565b90506000613ae2828460010154613d7a565b95945050505050565b4290565b600354600090819061010090046001600160a01b03163314613b1757612a146001602c61311e565b613b1f613aeb565b60095414613b3357612a14600a602b61311e565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b158015613b8457600080fd5b505afa158015613b98573d6000803e3d6000fd5b505050506040513d6020811015613bae57600080fd5b5051613c01576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269281900390910190a16000611391565b60008054819060ff16613cab576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155613cbd6122a3565b90508015613cdb57612b57816010811115613cd457fe5b601461311e565b612b70338686614b08565b613cee6155d5565b6040518060200160405280613d07856000015185613d38565b90529392505050565b6000613d1a6155d5565b613d248585613ce6565b9050613ae2613d328261477b565b84612b92565b600061139183836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250614dae565b600061139183836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250614e24565b6000613db8846136b2565b613dc1836136b2565b6005546040805163d02f735160e01b81523060048201526001600160a01b03888116602483015287811660448301528681166064830152608482018690529151600093929092169163d02f73519160a48082019260209290919082900301818787803b158015613e3057600080fd5b505af1158015613e44573d6000803e3d6000fd5b505050506040513d6020811015613e5a57600080fd5b505190508015613e7957613e716003601183614715565b915050612fac565b82613e85576000613e71565b846001600160a01b0316846001600160a01b03161415613eab57613e716006601261311e565b6001600160a01b0384166000908152600e6020526040902054613ece9084612bc8565b6001600160a01b038086166000908152600e60205260408082209390935590871681522054613efd9084612b92565b6001600160a01b038087166000908152600e6020908152604080832094909455918716815260159091522054613f339084612bc8565b6001600160a01b038086166000908152601560205260408082209390935590871681522054613f629084612b92565b6001600160a01b03808716600081815260156020908152604091829020949094558051878152905191939288169260008051602061587f83398151915292918290030190a36001600160a01b0384166000818152601560209081526040918290205482519384529083015280516000805160206159328339815191529281900390910190a16001600160a01b0385166000818152601560209081526040918290205482519384529083015280516000805160206159328339815191529281900390910190a160009695505050505050565b6001600160a01b03811660009081526016602052604081205460ff161561407357506001600160a01b038116600090815260156020526040902054610f43565b506001600160a01b0381166000908152600e6020526040902054610f43565b6000805460ff166140d7576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556140e96122a3565b90508015614107576130f581601081111561410057fe5b600261311e565b61369c338585614e86565b6000805460ff16614157576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556141696122a3565b90508015614180576130f581601081111561368857fe5b61369c3385600086614828565b60008054819060ff166141d4576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556141e66122a3565b90508015614211576142048160108111156141fd57fe5b600761311e565b9250600091506142a99050565b846001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561424c57600080fd5b505af1158015614260573d6000803e3d6000fd5b505050506040513d602081101561427657600080fd5b5051905080156142965761420481601081111561428f57fe5b600861311e565b6142a33388888888615061565b92509250505b6000805460ff19166001179055909590945092505050565b60035460009061010090046001600160a01b031633146142e7576113da6001603161311e565b6142ef613aeb565b60095414614303576113da600a603261311e565b670de0b6b3a764000082111561431f576113da6002603361311e565b6008805490839055604080518281526020810185905281517faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460929181900390910190a16000611391565b60055460408051631200453160e11b81523060048201526001600160a01b0387811660248301528681166044830152606482018690529151600093849384939116916324008a629160848082019260209290919082900301818787803b1580156143d257600080fd5b505af11580156143e6573d6000803e3d6000fd5b505050506040513d60208110156143fc57600080fd5b505190508015614420576144136003602483614715565b9250600091506146029050565b8461444c57600a546001600160a01b038716600090815260106020526040812060010191909155614413565b614454613aeb565b6009541461446857614413600a602561311e565b614470615662565b6001600160a01b038716600090815260106020526040902060010154606082015261449a87613a96565b60808201526000198614156144b857608081015160408201526144c0565b604081018690525b6144cf8882604001518761330b565b60e0820181905260808201516144e491612bc8565b60a0820152600b5460e08201516144fb9190612bc8565b8160c00181815250508060a0015160106000896001600160a01b03166001600160a01b0316815260200190815260200160002060000181905550600a5460106000896001600160a01b03166001600160a01b03168152602001908152602001600020600101819055508060c00151600b819055507f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a188888360e001518460a001518560c0015160405180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018381526020018281526020019550505050505060405180910390a160e00151600093509150505b94509492505050565b6000838301828582101561132a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561466257818101518382015260200161464a565b50505050905090810190601f16801561468f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b600081848411156146ef5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561466257818101518382015260200161464a565b505050900390565b600061139161470e84670de0b6b3a7640000613d38565b8351613d7a565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601081111561474457fe5b84603881111561475057fe5b604080519283526020830191909152818101859052519081900360600190a1836010811115612fac57fe5b51670de0b6b3a7640000900490565b600080600080614798613aeb565b600954146147b7576147ac600a603761311e565b935091506148219050565b6147c233878761330b565b90506147d0600c5482612b92565b600c819055604080513381526020810184905280820183905290519193507fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5919081900360600190a1600093509150505b9250929050565b6000614833856136b2565b83158061483e575082155b6148795760405162461bcd60e51b81526004018080602001828103825260348152602001806158d16034913960400191505060405180910390fd5b6148816156a8565b614889612c02565b815284156148ba576020808201869052604080519182019052815181526148b09086613061565b60408201526148e3565b6148d68460405180602001604052808460000151815250615589565b6020820152604081018490525b6001600160a01b0386166000908152600e602090815260408083205460159092528220546149119190612bc8565b90506000809050818360200151111561492e578183602001510390505b614936613aeb565b6009541461494a57612d63600a601b61311e565b8260400151614957612b8c565b101561496957612d63600e601c61311e565b61497888846040015187613204565b614988600d548460200151612bc8565b600d556001600160a01b0388166000908152600e6020908152604090912054908401516149b59190612bc8565b6001600160a01b0389166000908152600e602052604090205580156149de576149de888261393f565b306001600160a01b0316886001600160a01b031660008051602061587f83398151915285602001516040518082815260200191505060405180910390a360408084015160208086015183516001600160a01b038d168152918201929092528083019190915290517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a9299181900360600190a1600554604080850151602086015182516351dff98960e01b81523060048201526001600160a01b038d811660248301526044820193909352606481019190915291519216916351dff9899160848082019260009290919082900301818387803b158015614adb57600080fd5b505af1158015614aef573d6000803e3d6000fd5b5060009250614afc915050565b98975050505050505050565b600080614b14856136b2565b60055460408051634ef4c3e160e01b81523060048201526001600160a01b0388811660248301526044820188905291516000939290921691634ef4c3e19160648082019260209290919082900301818787803b158015614b7357600080fd5b505af1158015614b87573d6000803e3d6000fd5b505050506040513d6020811015614b9d57600080fd5b505190508015614bc157614bb46003601583614715565b925060009150614da69050565b84614bcd576000614bb4565b614bd5613aeb565b60095414614be957614bb4600a601661311e565b614bf16156a8565b614bf9612c02565b8152614c0687878761330b565b604080830182905280516020810190915282518152614c259190615589565b60208201819052600d54614c3891612b92565b600d556001600160a01b0387166000908152600e602090815260409091205490820151614c659190612b92565b6001600160a01b038089166000818152600e602090815260409182902094909455600554815163929fe9a160e01b81526004810193909352306024840152905192169263929fe9a192604480840193829003018186803b158015614cc857600080fd5b505afa158015614cdc573d6000803e3d6000fd5b505050506040513d6020811015614cf257600080fd5b505115614d0957614d078782602001516137f4565b505b60408082015160208084015183516001600160a01b038c168152918201929092528083019190915290517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9181900360600190a1866001600160a01b0316306001600160a01b031660008051602061587f83398151915283602001516040518082815260200191505060405180910390a360400151600093509150505b935093915050565b6000831580614dbb575082155b15614dc857506000611391565b83830283858281614dd557fe5b0414839061132a5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561466257818101518382015260200161464a565b60008183614e735760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561466257818101518382015260200161464a565b50828481614e7d57fe5b04949350505050565b6005546040805163368f515360e21b81523060048201526001600160a01b0386811660248301526044820186905291516000938493169163da3d454c91606480830192602092919082900301818787803b158015614ee357600080fd5b505af1158015614ef7573d6000803e3d6000fd5b505050506040513d6020811015614f0d57600080fd5b505190508015614f2c57614f246003600683614715565b915050611391565b83614f5857600a546001600160a01b038616600090815260106020526040812060010191909155614f24565b614f60613aeb565b60095414614f7457614f24600a600461311e565b83614f7d612b8c565b1015614f8f57614f24600e600361311e565b614f976156c9565b614fa086613a96565b60208201819052614fb19086612b92565b6040820152600b54614fc39086612b92565b6060820152614fd3868686613204565b604080820180516001600160a01b03891660008181526010602090815290859020928355600a54600190930192909255606080860151600b819055935185519283529282018a9052818501929092529081019190915290517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809181900360800190a160009695505050505050565b60055460408051632fe3f38f60e11b81523060048201526001600160a01b0385811660248301528881166044830152878116606483015260848201879052915160009384938493911691635fc7e71e9160a48082019260209290919082900301818787803b1580156150d257600080fd5b505af11580156150e6573d6000803e3d6000fd5b505050506040513d60208110156150fc57600080fd5b505190508015615120576151136003600a83614715565b92506000915061557f9050565b615128613aeb565b6009541461513c57615113600a600e61311e565b615144613aeb565b856001600160a01b031663cfa992016040518163ffffffff1660e01b815260040160206040518083038186803b15801561517d57600080fd5b505afa158015615191573d6000803e3d6000fd5b505050506040513d60208110156151a757600080fd5b5051146151ba57615113600a600961311e565b876001600160a01b0316876001600160a01b031614156151e0576151136006600f61311e565b856151f1576151136007600d61311e565b600019861415615207576151136007600c61311e565b6000806152168a8a8a89614369565b909250905081156152465761523782601081111561523057fe5b601061311e565b94506000935061557f92505050565b6005546040805163c488847b60e01b81523060048201526001600160a01b038a81166024830152604482018590528251600094859492169263c488847b926064808301939192829003018186803b1580156152a057600080fd5b505afa1580156152b4573d6000803e3d6000fd5b505050506040513d60408110156152ca57600080fd5b508051602090910151909250905081156153155760405162461bcd60e51b81526004018080602001828103825260328152602001806157316032913960400191505060405180910390fd5b80896001600160a01b03166370a082318d6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561536c57600080fd5b505afa158015615380573d6000803e3d6000fd5b505050506040513d602081101561539657600080fd5b505110156153eb576040805162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d5543480000000000000000604482015290519081900360640190fd5b60006001600160a01b038a163014156154115761540a308e8e85613dad565b905061549b565b6040805163b2a02ff160e01b81526001600160a01b038f811660048301528e81166024830152604482018590529151918c169163b2a02ff1916064808201926020929091908290030181600087803b15801561546c57600080fd5b505af1158015615480573d6000803e3d6000fd5b505050506040513d602081101561549657600080fd5b505190505b80156154e5576040805162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b604482015290519081900360640190fd5b7f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb528d8d868d8660405180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001848152602001836001600160a01b03166001600160a01b031681526020018281526020019550505050505060405180910390a16000975092955050505050505b9550959350505050565b60006155936155d5565b61307584846155a06155d5565b60006155b4670de0b6b3a764000085613d38565b905060405180602001604052806155cb83866146f7565b9052949350505050565b6040518060200160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061562957805160ff1916838001178555615656565b82800160010185558215615656579182015b8281111561565657825182559160200191906001019061563b565b50612c649291506156f2565b6040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180606001604052806000815260200160008152602001600081525090565b604080516080810190915280600081526020016000815260200160008152602001600081525090565b61115691905b80821115612c6457600081556001016156f856fe6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d61726b65744c49515549444154455f4a4f4554524f4c4c45525f43414c43554c4154455f414d4f554e545f5345495a455f4641494c45446d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6e6365696e697469616c2065786368616e67652072617465206d7573742062652067726561746572207468616e207a65726f2e6f6e6c792061646d696e2063616e2073657420636f6c6c61746572616c2063617073657474696e6720696e7465726573742072617465206d6f64656c206661696c65646f6e6c79206a6f6574726f6c6c6572206d617920726567697374657220636f6c6c61746572616c20666f7220757365726f6e6c79207468652061646d696e206d61792063616c6c205f72657369676e496d706c656d656e746174696f6e45524333313536466c617368426f72726f776572496e746572666163652e6f6e466c6173684c6f616eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6f6e6c79206a6f6574726f6c6c6572206d617920756e726567697374657220636f6c6c61746572616c20666f7220757365726f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416d6f756e74496e206d757374206265207a65726f6f6e6c79207468652061646d696e206d61792063616c6c205f6265636f6d65496d706c656d656e746174696f6e1d22042d9eb89f2620572acbf8d85b66fba5a2ca19d166d8659574440175c964666c6173684c6f616e20616d6f756e742073686f756c642062652067726561746572207468616e207a65726fa265627a7a723158204ccaf3ef2efe2de5576d7a82c9c2d5d23b21bfeff7d084485e25459c3c61e6f064736f6c63430005100032",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106103e65760003560e01c806381cf00eb1161020a578063b2a02ff111610125578063db006a75116100b8578063f2b3abbd11610087578063f2b3abbd14610dad578063f3fdb15a14610dd3578063f5e3c46214610ddb578063f851a44014610e11578063fca7820b14610e19576103e6565b8063db006a7514610d52578063dd62ed3e14610d6f578063e9c714f214610d9d578063ea11eea414610da5576103e6565b8063c5ebeaec116100f4578063c5ebeaec14610cff578063cfa9920114610d1c578063d240d64a14610d24578063d2bb18e914610d4a576103e6565b8063b2a02ff114610c4f578063b71d1a0c14610c85578063bd6d894d14610cab578063c37f68e214610cb3576103e6565b806395dd91931161019d578063a7af467a1161016c578063a7af467a14610bf6578063a9059cbb14610c13578063aa5af0fd14610c3f578063b1d3897414610c47576103e6565b806395dd919314610a5d57806399d8c1b414610a83578063a0712d6814610bd1578063a6afed9514610bee576103e6565b80638b35776b116101d95780638b35776b14610a1f5780638f840ddd14610a4557806394909e6214610a4d57806395d89b4114610a55576103e6565b806381cf00eb14610999578063852a12e3146109b657806385d8a2e6146109d35780638897bd85146109f9576103e6565b8063313ce567116103055780635260975011610298578063601a0bf111610267578063601a0bf11461093e5780636330533c1461095b5780636f307dc31461096357806370a082311461096b57806373acee9814610991576103e6565b806352609750146107fc57806356e67728146108045780635c60da1b146108a85780635cffe9de146108b0576103e6565b8063406de0b6116102d4578063406de0b6146107a1578063432f4b2d146107a957806347bd3718146107cf57806350f6e082146107d7576103e6565b8063313ce567146107385780633af9e669146107565780633b1d21a21461077c5780633e94101014610784576103e6565b8063182df0f51161037d57806323b872dd1161034c57806323b872dd146106aa578063242c127c146106e05780632608f818146106e85780632678224714610714576103e6565b8063182df0f51461053c57806319a4dd3c146105445780631a31d4651461054c57806322abdbf5146106a2576103e6565b8063153ab505116103b9578063153ab505146104fc578063173b99041461050657806317bfdfbc1461050e57806318160ddd14610534576103e6565b806306fdde03146103eb578063095ea7b3146104685780630e752702146104a85780630f3e4e11146104d7575b600080fd5b6103f3610e36565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561042d578181015183820152602001610415565b50505050905090810190601f16801561045a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104946004803603604081101561047e57600080fd5b506001600160a01b038135169060200135610ec3565b604080519115158252519081900360200190f35b6104c5600480360360208110156104be57600080fd5b5035610f30565b60408051918252519081900360200190f35b6104c5600480360360408110156104ed57600080fd5b50803590602001351515610f48565b61050461102d565b005b6104c561107d565b6104c56004803603602081101561052457600080fd5b50356001600160a01b0316611083565b6104c5611143565b6104c5611149565b6104c5611159565b610504600480360360e081101561056257600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b8111156105a457600080fd5b8201836020820111156105b657600080fd5b803590602001918460018302840111600160201b831117156105d757600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561062957600080fd5b82018360208201111561063b57600080fd5b803590602001918460018302840111600160201b8311171561065c57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061115f9050565b6104c56111fe565b610494600480360360608110156106c057600080fd5b506001600160a01b03813581169160208101359091169060400135611204565b6104c5611276565b6104c5600480360360408110156106fe57600080fd5b506001600160a01b03813516906020013561131b565b61071c611333565b604080516001600160a01b039092168252519081900360200190f35b610740611342565b6040805160ff9092168252519081900360200190f35b6104c56004803603602081101561076c57600080fd5b50356001600160a01b031661134b565b6104c5611398565b6104c56004803603602081101561079a57600080fd5b50356113a2565b6104946113af565b6104c5600480360360208110156107bf57600080fd5b50356001600160a01b03166113b4565b6104c5611508565b6104c5600480360360408110156107ed57600080fd5b5080359060200135151561150e565b6104c56115bd565b6105046004803603602081101561081a57600080fd5b810190602081018135600160201b81111561083457600080fd5b82018360208201111561084657600080fd5b803590602001918460018302840111600160201b8311171561086757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611652945050505050565b61071c611719565b610494600480360360808110156108c657600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561090057600080fd5b82018360208201111561091257600080fd5b803590602001918460018302840111600160201b8311171561093357600080fd5b509092509050611728565b6104c56004803603602081101561095457600080fd5b5035611c6c565b61071c611d07565b61071c611d16565b6104c56004803603602081101561098157600080fd5b50356001600160a01b0316611d25565b6104c5611d40565b610504600480360360208110156109af57600080fd5b5035611df6565b6104c5600480360360208110156109cc57600080fd5b5035611e87565b610494600480360360208110156109e957600080fd5b50356001600160a01b0316611e94565b6104c560048036036020811015610a0f57600080fd5b50356001600160a01b0316611ea9565b61050460048036036020811015610a3557600080fd5b50356001600160a01b0316611f37565b6104c5611fb0565b610504611fb6565b6103f361204b565b6104c560048036036020811015610a7357600080fd5b50356001600160a01b03166120a3565b610504600480360360c0811015610a9957600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b811115610ad357600080fd5b820183602082011115610ae557600080fd5b803590602001918460018302840111600160201b83111715610b0657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610b5857600080fd5b820183602082011115610b6a57600080fd5b803590602001918460018302840111600160201b83111715610b8b57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff1691506120ae9050565b6104c560048036036020811015610be757600080fd5b5035612295565b6104c56122a3565b6104c560048036036020811015610c0c57600080fd5b50356124b3565b61049460048036036040811015610c2957600080fd5b506001600160a01b0381351690602001356125a5565b6104c5612617565b6104c561261d565b6104c560048036036060811015610c6557600080fd5b506001600160a01b0381358116916020810135909116906040013561268b565b6104c560048036036020811015610c9b57600080fd5b50356001600160a01b03166126fc565b6104c5612788565b610cd960048036036020811015610cc957600080fd5b50356001600160a01b0316612844565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6104c560048036036020811015610d1557600080fd5b5035612880565b6104c561288d565b6104c560048036036020811015610d3a57600080fd5b50356001600160a01b0316612893565b6104c56128a5565b6104c560048036036020811015610d6857600080fd5b50356128ab565b6104c560048036036040811015610d8557600080fd5b506001600160a01b03813581169160200135166128b8565b6104c56128e3565b6104c56129e6565b6104c560048036036020811015610dc357600080fd5b50356001600160a01b03166129eb565b61071c612a25565b6104c560048036036060811015610df157600080fd5b506001600160a01b03813581169160208101359160409091013516612a34565b61071c612a4e565b6104c560048036036020811015610e2f57600080fd5b5035612a62565b60018054604080516020600284861615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610ebb5780601f10610e9057610100808354040283529160200191610ebb565b820191906000526020600020905b815481529060010190602001808311610e9e57829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855290835281842086905581518681529151939493909284927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a360019150505b92915050565b600080610f3e836000612ae0565b509150505b919050565b60008060008315610f7957610f64610f5e612b8c565b86612b92565b9150610f72600b5486612bc8565b9050610f9b565b610f8a610f84612b8c565b86612bc8565b9150610f98600b5486612b92565b90505b600654600c54604080516315f2405360e01b815260048101869052602481018590526044810192909252516001600160a01b03909216916315f2405391606480820192602092909190829003018186803b158015610ff857600080fd5b505afa15801561100c573d6000803e3d6000fd5b505050506040513d602081101561102257600080fd5b505195945050505050565b60035461010090046001600160a01b0316331461107b5760405162461bcd60e51b815260040180806020018281038252602d815260200180615829602d913960400191505060405180910390fd5b565b60085481565b6000805460ff166110c8576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556110da6122a3565b14611125576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b61112e826120a3565b90505b6000805460ff19166001179055919050565b600d5481565b6000611153612c02565b90505b90565b60145481565b61116d8686868686866120ae565b601180546001600160a01b0319166001600160a01b038981169190911791829055604080516318160ddd60e01b8152905192909116916318160ddd91600480820192602092909190829003018186803b1580156111c957600080fd5b505afa1580156111dd573d6000803e3d6000fd5b505050506040513d60208110156111f357600080fd5b505050505050505050565b60135481565b6000805460ff16611249576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561125f33868686612c68565b1490506000805460ff191660011790559392505050565b600554604080516358d5bc7360e11b81523060048201526000602482018190526044820181905260806064830152608482018190529151919283926001600160a01b039091169163b1ab78e69160c4808301926020929190829003018186803b1580156112e257600080fd5b505afa1580156112f6573d6000803e3d6000fd5b505050506040513d602081101561130c57600080fd5b50511561115357610f2a612b8c565b60008061132a84846000612fb4565b50949350505050565b6004546001600160a01b031681565b60035460ff1681565b60006113556155d5565b6040518060200160405280611368612788565b90526001600160a01b0384166000908152600e6020526040902054909150611391908290613061565b9392505050565b6000611153612b8c565b6000610f2a826000613080565b600181565b60035460009061010090046001600160a01b031633146113e1576113da6001602961311e565b9050610f43565b600554604080516340e6dcc560e01b815290516001600160a01b03928316928516916340e6dcc5916004808301926020929190829003018186803b15801561142857600080fd5b505afa15801561143c573d6000803e3d6000fd5b505050506040513d602081101561145257600080fd5b50516114a5576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517f17d6db5ffe5a3d1c3d7a98194dca4f7d808d621e6ff9077ed574513d553a2a859281900390910190a16000611391565b600b5481565b6000806000831561153957611524610f5e612b8c565b9150611532600b5486612bc8565b9050611555565b611544610f84612b8c565b9150611552600b5486612b92565b90505b600654600c5460085460408051635c0b440b60e11b8152600481018790526024810186905260448101939093526064830191909152516001600160a01b039092169163b816881691608480820192602092909190829003018186803b158015610ff857600080fd5b6006546000906001600160a01b03166315f240536115d9612b8c565b600b54600c546040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b15801561162157600080fd5b505afa158015611635573d6000803e3d6000fd5b505050506040513d602081101561164b57600080fd5b5051905090565b60035461010090046001600160a01b031633146116a05760405162461bcd60e51b815260040180806020018281038252602d815260200180615905602d913960400191505060405180910390fd5b6116a8613184565b601355600554604080516303c03f0f60e01b81523060048201526001602482015290516001600160a01b03909216916303c03f0f9160448082019260009290919082900301818387803b1580156116fe57600080fd5b505af1158015611712573d6000803e3d6000fd5b5050505050565b6012546001600160a01b031681565b6000805460ff1661176d576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19169055836117b35760405162461bcd60e51b815260040180806020018281038252602c815260200180615952602c913960400191505060405180910390fd5b60006117bd6122a3565b14611808576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b6005546040516358d5bc7360e11b815230600482018181526001600160a01b038a81166024850152604484018990526080606485019081526084850188905294169363b1ab78e6938b928a928a928a92919060a401848480828437600081840152601f19601f820116905080830192505050965050505050505060206040518083038186803b15801561189a57600080fd5b505afa1580156118ae573d6000803e3d6000fd5b505050506040513d60208110156118c457600080fd5b505161190d576040805162461bcd60e51b8152602060048201526013602482015272199b185cda1b1bd85b881a5cc81c185d5cd959606a1b604482015290519081900360640190fd5b6000611917613184565b90506000611923612b8c565b905085811015611973576040805162461bcd60e51b8152602060048201526016602482015275494e53554646494349454e545f4c495155494449545960501b604482015290519081900360640190fd5b6000306001600160a01b031663a7af467a886040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156119b957600080fd5b505afa1580156119cd573d6000803e3d6000fd5b505050506040513d60208110156119e357600080fd5b505190506119f389886000613204565b6119ff600b5488612b92565b600b5560405180602961585682396040519081900360290181206011546323e30c8b60e01b83526001600160a01b038c81166004850190815291811660248501819052604485018d90526064850187905260a06084860190815260a486018c9052939550908e16936323e30c8b938e938e9289928f928f9290919060c401848480828437600081840152601f19601f820116905080830192505050975050505050505050602060405180830381600087803b158015611abd57600080fd5b505af1158015611ad1573d6000803e3d6000fd5b505050506040513d6020811015611ae757600080fd5b505114611b3b576040805162461bcd60e51b815260206004820152601960248201527f49455243333135363a2043616c6c6261636b206661696c656400000000000000604482015290519081900360640190fd5b6000611b478883612b92565b9050611b558a82600061330b565b506000611b60613184565b9050611b6c8584612b92565b8114611bb6576040805162461bcd60e51b8152602060048201526014602482015273109053105390d157d25390d3d394d254d511539560621b604482015290519081900360640190fd5b6000611bd2604051806020016040528060085481525085613061565b9050611be0600c5482612b92565b600c55611bed8585612b92565b601355600b54611bfd908b612bc8565b600b55604080518b81526020810186905280820183905290516001600160a01b038e16917f33c8e097c526683cbdb29adf782fac95e9d0fbe0ed635c13d8c75fdf726557d9919081900360600190a2600196505050505050506000805460ff1916600117905595945050505050565b6000805460ff16611cb1576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611cc36122a3565b90508015611ce957611ce1816010811115611cda57fe5b601d61311e565b915050611131565b611cf28361351c565b9150506000805460ff19166001179055919050565b6005546001600160a01b031681565b6011546001600160a01b031681565b6001600160a01b03166000908152600e602052604090205490565b6000805460ff16611d85576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611d976122a3565b14611de2576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b50600b546000805460ff1916600117905590565b60035461010090046001600160a01b03163314611e445760405162461bcd60e51b81526004018080602001828103825260218152602001806157b66021913960400191505060405180910390fd5b6017819055604080513081526020810183905281517f01b7c780e0f385803fe80cbe0efc086d13b8eb443a2ce43e2061fd92bc0e34f1929181900390910190a150565b6000610f2a82600061361a565b60166020526000908152604090205460ff1681565b6000611eb4826136b2565b6005546001600160a01b03163314611efd5760405162461bcd60e51b81526004018080602001828103825260308152602001806157f96030913960400191505060405180910390fd5b6001600160a01b0382166000908152600e60209081526040808320546015909252822054611f2b9190612bc8565b905061139183826137f4565b611f40816136b2565b6005546001600160a01b03163314611f895760405162461bcd60e51b815260040180806020018281038252603281526020018061589f6032913960400191505060405180910390fd5b6001600160a01b038116600090815260156020526040902054611fad90829061393f565b50565b600c5481565b60005460ff16611ffa576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561200c613184565b90506000612018612b8c565b905060006120268383612bc8565b9050612034600c5482612b92565b600c5550506013556000805460ff19166001179055565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610ebb5780601f10610e9057610100808354040283529160200191610ebb565b6000610f2a82613a96565b60035461010090046001600160a01b031633146120fc5760405162461bcd60e51b815260040180806020018281038252602481526020018061570d6024913960400191505060405180910390fd5b60095415801561210c5750600a54155b6121475760405162461bcd60e51b81526004018080602001828103825260238152602001806157636023913960400191505060405180910390fd5b6007849055836121885760405162461bcd60e51b81526004018080602001828103825260308152602001806157866030913960400191505060405180910390fd5b6000612193876113b4565b905080156121e8576040805162461bcd60e51b815260206004820152601960248201527f73657474696e67206a6f6574726f6c6c6572206661696c656400000000000000604482015290519081900360640190fd5b6121f0613aeb565b600955670de0b6b3a7640000600a5561220886613aef565b905080156122475760405162461bcd60e51b81526004018080602001828103825260228152602001806157d76022913960400191505060405180910390fd5b835161225a9060019060208701906155e8565b50825161226e9060029060208601906155e8565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b600080610f3e836000613c64565b6000806122ae613aeb565b600954909150808214156122c757600092505050611156565b60006122d1612b8c565b600b54600c54600a54600654604080516315f2405360e01b815260048101879052602481018690526044810185905290519596509394929391926000926001600160a01b03909216916315f24053916064808301926020929190829003018186803b15801561233f57600080fd5b505afa158015612353573d6000803e3d6000fd5b505050506040513d602081101561236957600080fd5b5051905065048c273950008111156123c8576040805162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c79206869676800000000604482015290519081900360640190fd5b60006123d48888612bc8565b90506123de6155d5565b6123f660405180602001604052808581525083613ce6565b905060006124048288613061565b905060006124128289612b92565b905060006124316040518060200160405280600854815250848a613d10565b9050600061244085898a613d10565b60098e9055600a819055600b849055600c839055604080518d8152602081018790528082018390526060810186905290519192507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc04919081900360800190a160009d505050505050505050505050505090565b600554604080516358d5bc7360e11b8152306004820152600060248201819052604482018590526080606483015260848201819052915191926001600160a01b03169163b1ab78e69160c480820192602092909190829003018186803b15801561251c57600080fd5b505afa158015612530573d6000803e3d6000fd5b505050506040513d602081101561254657600080fd5b505161258f576040805162461bcd60e51b8152602060048201526013602482015272199b185cda1b1bd85b881a5cc81c185d5cd959606a1b604482015290519081900360640190fd5b610f2a61259d836008613d38565b612710613d7a565b6000805460ff166125ea576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561260033338686612c68565b1490505b6000805460ff1916600117905592915050565b600a5481565b6006546000906001600160a01b031663b8168816612639612b8c565b600b54600c546008546040518563ffffffff1660e01b81526004018085815260200184815260200183815260200182815260200194505050505060206040518083038186803b15801561162157600080fd5b6000805460ff166126d0576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191690556126e633858585613dad565b90506000805460ff191660011790559392505050565b60035460009061010090046001600160a01b03163314612722576113da6001602f61311e565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a16000611391565b6000805460ff166127cd576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556127df6122a3565b1461282a576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b612832611149565b90506000805460ff1916600117905590565b600080600080600061285586614033565b9050600061286287613a96565b9050600061286e612c02565b90506000989297509095509350915050565b6000610f2a826000614092565b60095481565b60156020526000908152604090205481565b60175481565b6000610f2a826000614112565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6004546000906001600160a01b0316331415806128fe575033155b156129165761290f6001600061311e565b9050611156565b60038054600480546001600160a01b03818116610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401528351909391927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600454604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160009250505090565b600881565b6000806129f66122a3565b90508015612a1c57612a14816010811115612a0d57fe5b602a61311e565b915050610f43565b61139183613aef565b6006546001600160a01b031681565b600080612a44858585600061418d565b5095945050505050565b60035461010090046001600160a01b031681565b6000805460ff16612aa7576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612ab96122a3565b90508015612ad757611ce1816010811115612ad057fe5b603061311e565b611cf2836142c1565b60008054819060ff16612b27576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612b396122a3565b90508015612b6457612b57816010811115612b5057fe5b602361311e565b925060009150612b769050565b612b7033338787614369565b92509250505b6000805460ff1916600117905590939092509050565b60135490565b60006113918383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b81525061460b565b60006113918383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061469d565b600d5460009080612c17575050600754611156565b6000612c21612b8c565b90506000612c3c612c3483600b54612b92565b600c54612bc8565b90506000612c58826040518060200160405280878152506146f7565b94506111569350505050565b5090565b6000612c73846136b2565b612c7c836136b2565b6001600160a01b0384166000908152600e60209081526040808320546015909252822054612caa9190612bc8565b9050600081841115612cbb57508083035b600554604080516317b9b84b60e31b81523060048201526001600160a01b0389811660248301528881166044830152606482018590529151600093929092169163bdcdc2589160848082019260209290919082900301818787803b158015612d2257600080fd5b505af1158015612d36573d6000803e3d6000fd5b505050506040513d6020811015612d4c57600080fd5b505190508015612d6d57612d636003603483614715565b9350505050612fac565b856001600160a01b0316876001600160a01b03161415612d9357612d636002603561311e565b60006001600160a01b038981169089161415612db25750600019612dda565b506001600160a01b038088166000908152600f60209081526040808320938c16835292905220545b6001600160a01b0388166000908152600e6020526040902054612dfd9087612bc8565b6001600160a01b03808a166000908152600e60205260408082209390935590891681522054612e2c9087612b92565b6001600160a01b0388166000908152600e60205260409020558215612f30576001600160a01b038816600090815260156020526040902054612e6e9084612bc8565b6001600160a01b03808a166000908152601560205260408082209390935590891681522054612e9d9084612b92565b6001600160a01b03808916600090815260156020908152604080832094909455918b1680825290839020548351918252918101919091528151600080516020615932833981519152929181900390910190a16001600160a01b0387166000818152601560209081526040918290205482519384529083015280516000805160206159328339815191529281900390910190a15b6000198114612f6a57612f438187612bc8565b6001600160a01b03808a166000908152600f60209081526040808320938e16835292905220555b866001600160a01b0316886001600160a01b031660008051602061587f833981519152886040518082815260200191505060405180910390a360009450505050505b949350505050565b60008054819060ff16612ffb576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff1916815561300d6122a3565b905080156130385761302b81601081111561302457fe5b602261311e565b92506000915061304a9050565b61304433878787614369565b92509250505b6000805460ff191660011790559094909350915050565b600061306b6155d5565b6130758484613ce6565b9050612fac8161477b565b6000805460ff166130c5576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556130d76122a3565b905080156130fd576130f58160108111156130ee57fe5b603661311e565b915050612604565b613107848461478a565b509150506000805460ff1916600117905592915050565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083601081111561314d57fe5b83603881111561315957fe5b604080519283526020830191909152600082820152519081900360600190a182601081111561139157fe5b601154604080516370a0823160e01b815230600482015290516000926001600160a01b03169182916370a0823191602480820192602092909190829003018186803b1580156131d257600080fd5b505afa1580156131e6573d6000803e3d6000fd5b505050506040513d60208110156131fc57600080fd5b505191505090565b6011546040805163a9059cbb60e01b81526001600160a01b0386811660048301526024820186905291519190921691829163a9059cbb9160448082019260009290919082900301818387803b15801561325c57600080fd5b505af1158015613270573d6000803e3d6000fd5b5050505060003d6000811461328c576020811461329657600080fd5b60001991506132a2565b60206000803e60005191505b50806132f5576040805162461bcd60e51b815260206004820152601960248201527f544f4b454e5f5452414e534645525f4f55545f4641494c454400000000000000604482015290519081900360640190fd5b61330160135485612bc8565b6013555050505050565b601154604080516370a0823160e01b815230600482015290516000926001600160a01b031691839183916370a08231916024808301926020929190829003018186803b15801561335a57600080fd5b505afa15801561336e573d6000803e3d6000fd5b505050506040513d602081101561338457600080fd5b5051604080516323b872dd60e01b81526001600160a01b038981166004830152306024830152604482018990529151929350908416916323b872dd9160648082019260009290919082900301818387803b1580156133e157600080fd5b505af11580156133f5573d6000803e3d6000fd5b5050505060003d60008114613411576020811461341b57600080fd5b6000199150613427565b60206000803e60005191505b508061347a576040805162461bcd60e51b815260206004820152601860248201527f544f4b454e5f5452414e534645525f494e5f4641494c45440000000000000000604482015290519081900360640190fd5b601154604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156134c557600080fd5b505afa1580156134d9573d6000803e3d6000fd5b505050506040513d60208110156134ef57600080fd5b5051905060006134ff8285612bc8565b905061350d60135482612b92565b60135598975050505050505050565b600354600090819061010090046001600160a01b0316331461354457612a146001601e61311e565b61354c613aeb565b6009541461356057612a14600a602061311e565b82613569612b8c565b101561357b57612a14600e601f61311e565b600c5483111561359157612a146002602161311e565b61359d600c5484612bc8565b600c8190556003549091506135c29061010090046001600160a01b0316846001613204565b600354604080516101009092046001600160a01b0316825260208201859052818101839052517f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e916060908290030190a16000611391565b6000805460ff1661365f576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556136716122a3565b9050801561368f576130f581601081111561368857fe5b601961311e565b61369c3360008686614828565b9150506000805460ff1916600117905592915050565b6001600160a01b03811660009081526016602052604090205460ff16611fad576005546040805163929fe9a160e01b81526001600160a01b0384811660048301523060248301529151919092169163929fe9a1916044808301926020929190829003018186803b15801561372557600080fd5b505afa158015613739573d6000803e3d6000fd5b505050506040513d602081101561374f57600080fd5b5051156137ce576001600160a01b0381166000908152600e602081815260408084205460158352932083905560145491905261378a91612b92565b6014556001600160a01b0381166000818152601560209081526040918290205482519384529083015280516000805160206159328339815191529281900390910190a15b6001600160a01b0381166000908152601660205260409020805460ff1916600117905550565b60008061380360145484612b92565b90506017546000148061382457506017541580159061382457506017548111155b1561389f5760148190556001600160a01b0384166000908152601560205260409020546138519084612b92565b6001600160a01b03851660008181526015602090815260409182902084905581519283528201929092528151600080516020615932833981519152929181900390910190a182915050610f2a565b60145460175411156139355760006138bb601754601454612bc8565b6017546014556001600160a01b0386166000908152601560205260409020549091506138e79082612b92565b6001600160a01b03861660008181526015602090815260409182902084905581519283528201929092528151600080516020615932833981519152929181900390910190a19150610f2a9050565b5060009392505050565b6005546040805163eabe7d9160e01b81523060048201526001600160a01b038581166024830152604482018590529151919092169163eabe7d919160648083019260209291908290030181600087803b15801561399b57600080fd5b505af11580156139af573d6000803e3d6000fd5b505050506040513d60208110156139c557600080fd5b505115613a10576040805162461bcd60e51b81526020600482015260146024820152733537b2ba3937b63632b9103932b532b1ba34b7b760611b604482015290519081900360640190fd5b80613a1a57613a92565b613a2660145482612bc8565b6014556001600160a01b038216600090815260156020526040902054613a4c9082612bc8565b6001600160a01b03831660008181526015602090815260409182902084905581519283528201929092528151600080516020615932833981519152929181900390910190a15b5050565b6001600160a01b03811660009081526010602052604081208054613abe576000915050610f43565b6000613ad08260000154600a54613d38565b90506000613ae2828460010154613d7a565b95945050505050565b4290565b600354600090819061010090046001600160a01b03163314613b1757612a146001602c61311e565b613b1f613aeb565b60095414613b3357612a14600a602b61311e565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b158015613b8457600080fd5b505afa158015613b98573d6000803e3d6000fd5b505050506040513d6020811015613bae57600080fd5b5051613c01576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269281900390910190a16000611391565b60008054819060ff16613cab576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155613cbd6122a3565b90508015613cdb57612b57816010811115613cd457fe5b601461311e565b612b70338686614b08565b613cee6155d5565b6040518060200160405280613d07856000015185613d38565b90529392505050565b6000613d1a6155d5565b613d248585613ce6565b9050613ae2613d328261477b565b84612b92565b600061139183836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250614dae565b600061139183836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250614e24565b6000613db8846136b2565b613dc1836136b2565b6005546040805163d02f735160e01b81523060048201526001600160a01b03888116602483015287811660448301528681166064830152608482018690529151600093929092169163d02f73519160a48082019260209290919082900301818787803b158015613e3057600080fd5b505af1158015613e44573d6000803e3d6000fd5b505050506040513d6020811015613e5a57600080fd5b505190508015613e7957613e716003601183614715565b915050612fac565b82613e85576000613e71565b846001600160a01b0316846001600160a01b03161415613eab57613e716006601261311e565b6001600160a01b0384166000908152600e6020526040902054613ece9084612bc8565b6001600160a01b038086166000908152600e60205260408082209390935590871681522054613efd9084612b92565b6001600160a01b038087166000908152600e6020908152604080832094909455918716815260159091522054613f339084612bc8565b6001600160a01b038086166000908152601560205260408082209390935590871681522054613f629084612b92565b6001600160a01b03808716600081815260156020908152604091829020949094558051878152905191939288169260008051602061587f83398151915292918290030190a36001600160a01b0384166000818152601560209081526040918290205482519384529083015280516000805160206159328339815191529281900390910190a16001600160a01b0385166000818152601560209081526040918290205482519384529083015280516000805160206159328339815191529281900390910190a160009695505050505050565b6001600160a01b03811660009081526016602052604081205460ff161561407357506001600160a01b038116600090815260156020526040902054610f43565b506001600160a01b0381166000908152600e6020526040902054610f43565b6000805460ff166140d7576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556140e96122a3565b90508015614107576130f581601081111561410057fe5b600261311e565b61369c338585614e86565b6000805460ff16614157576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556141696122a3565b90508015614180576130f581601081111561368857fe5b61369c3385600086614828565b60008054819060ff166141d4576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556141e66122a3565b90508015614211576142048160108111156141fd57fe5b600761311e565b9250600091506142a99050565b846001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561424c57600080fd5b505af1158015614260573d6000803e3d6000fd5b505050506040513d602081101561427657600080fd5b5051905080156142965761420481601081111561428f57fe5b600861311e565b6142a33388888888615061565b92509250505b6000805460ff19166001179055909590945092505050565b60035460009061010090046001600160a01b031633146142e7576113da6001603161311e565b6142ef613aeb565b60095414614303576113da600a603261311e565b670de0b6b3a764000082111561431f576113da6002603361311e565b6008805490839055604080518281526020810185905281517faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460929181900390910190a16000611391565b60055460408051631200453160e11b81523060048201526001600160a01b0387811660248301528681166044830152606482018690529151600093849384939116916324008a629160848082019260209290919082900301818787803b1580156143d257600080fd5b505af11580156143e6573d6000803e3d6000fd5b505050506040513d60208110156143fc57600080fd5b505190508015614420576144136003602483614715565b9250600091506146029050565b8461444c57600a546001600160a01b038716600090815260106020526040812060010191909155614413565b614454613aeb565b6009541461446857614413600a602561311e565b614470615662565b6001600160a01b038716600090815260106020526040902060010154606082015261449a87613a96565b60808201526000198614156144b857608081015160408201526144c0565b604081018690525b6144cf8882604001518761330b565b60e0820181905260808201516144e491612bc8565b60a0820152600b5460e08201516144fb9190612bc8565b8160c00181815250508060a0015160106000896001600160a01b03166001600160a01b0316815260200190815260200160002060000181905550600a5460106000896001600160a01b03166001600160a01b03168152602001908152602001600020600101819055508060c00151600b819055507f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a188888360e001518460a001518560c0015160405180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018381526020018281526020019550505050505060405180910390a160e00151600093509150505b94509492505050565b6000838301828582101561132a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561466257818101518382015260200161464a565b50505050905090810190601f16801561468f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b600081848411156146ef5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561466257818101518382015260200161464a565b505050900390565b600061139161470e84670de0b6b3a7640000613d38565b8351613d7a565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084601081111561474457fe5b84603881111561475057fe5b604080519283526020830191909152818101859052519081900360600190a1836010811115612fac57fe5b51670de0b6b3a7640000900490565b600080600080614798613aeb565b600954146147b7576147ac600a603761311e565b935091506148219050565b6147c233878761330b565b90506147d0600c5482612b92565b600c819055604080513381526020810184905280820183905290519193507fa91e67c5ea634cd43a12c5a482724b03de01e85ca68702a53d0c2f45cb7c1dc5919081900360600190a1600093509150505b9250929050565b6000614833856136b2565b83158061483e575082155b6148795760405162461bcd60e51b81526004018080602001828103825260348152602001806158d16034913960400191505060405180910390fd5b6148816156a8565b614889612c02565b815284156148ba576020808201869052604080519182019052815181526148b09086613061565b60408201526148e3565b6148d68460405180602001604052808460000151815250615589565b6020820152604081018490525b6001600160a01b0386166000908152600e602090815260408083205460159092528220546149119190612bc8565b90506000809050818360200151111561492e578183602001510390505b614936613aeb565b6009541461494a57612d63600a601b61311e565b8260400151614957612b8c565b101561496957612d63600e601c61311e565b61497888846040015187613204565b614988600d548460200151612bc8565b600d556001600160a01b0388166000908152600e6020908152604090912054908401516149b59190612bc8565b6001600160a01b0389166000908152600e602052604090205580156149de576149de888261393f565b306001600160a01b0316886001600160a01b031660008051602061587f83398151915285602001516040518082815260200191505060405180910390a360408084015160208086015183516001600160a01b038d168152918201929092528083019190915290517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a9299181900360600190a1600554604080850151602086015182516351dff98960e01b81523060048201526001600160a01b038d811660248301526044820193909352606481019190915291519216916351dff9899160848082019260009290919082900301818387803b158015614adb57600080fd5b505af1158015614aef573d6000803e3d6000fd5b5060009250614afc915050565b98975050505050505050565b600080614b14856136b2565b60055460408051634ef4c3e160e01b81523060048201526001600160a01b0388811660248301526044820188905291516000939290921691634ef4c3e19160648082019260209290919082900301818787803b158015614b7357600080fd5b505af1158015614b87573d6000803e3d6000fd5b505050506040513d6020811015614b9d57600080fd5b505190508015614bc157614bb46003601583614715565b925060009150614da69050565b84614bcd576000614bb4565b614bd5613aeb565b60095414614be957614bb4600a601661311e565b614bf16156a8565b614bf9612c02565b8152614c0687878761330b565b604080830182905280516020810190915282518152614c259190615589565b60208201819052600d54614c3891612b92565b600d556001600160a01b0387166000908152600e602090815260409091205490820151614c659190612b92565b6001600160a01b038089166000818152600e602090815260409182902094909455600554815163929fe9a160e01b81526004810193909352306024840152905192169263929fe9a192604480840193829003018186803b158015614cc857600080fd5b505afa158015614cdc573d6000803e3d6000fd5b505050506040513d6020811015614cf257600080fd5b505115614d0957614d078782602001516137f4565b505b60408082015160208084015183516001600160a01b038c168152918201929092528083019190915290517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f9181900360600190a1866001600160a01b0316306001600160a01b031660008051602061587f83398151915283602001516040518082815260200191505060405180910390a360400151600093509150505b935093915050565b6000831580614dbb575082155b15614dc857506000611391565b83830283858281614dd557fe5b0414839061132a5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561466257818101518382015260200161464a565b60008183614e735760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561466257818101518382015260200161464a565b50828481614e7d57fe5b04949350505050565b6005546040805163368f515360e21b81523060048201526001600160a01b0386811660248301526044820186905291516000938493169163da3d454c91606480830192602092919082900301818787803b158015614ee357600080fd5b505af1158015614ef7573d6000803e3d6000fd5b505050506040513d6020811015614f0d57600080fd5b505190508015614f2c57614f246003600683614715565b915050611391565b83614f5857600a546001600160a01b038616600090815260106020526040812060010191909155614f24565b614f60613aeb565b60095414614f7457614f24600a600461311e565b83614f7d612b8c565b1015614f8f57614f24600e600361311e565b614f976156c9565b614fa086613a96565b60208201819052614fb19086612b92565b6040820152600b54614fc39086612b92565b6060820152614fd3868686613204565b604080820180516001600160a01b03891660008181526010602090815290859020928355600a54600190930192909255606080860151600b819055935185519283529282018a9052818501929092529081019190915290517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809181900360800190a160009695505050505050565b60055460408051632fe3f38f60e11b81523060048201526001600160a01b0385811660248301528881166044830152878116606483015260848201879052915160009384938493911691635fc7e71e9160a48082019260209290919082900301818787803b1580156150d257600080fd5b505af11580156150e6573d6000803e3d6000fd5b505050506040513d60208110156150fc57600080fd5b505190508015615120576151136003600a83614715565b92506000915061557f9050565b615128613aeb565b6009541461513c57615113600a600e61311e565b615144613aeb565b856001600160a01b031663cfa992016040518163ffffffff1660e01b815260040160206040518083038186803b15801561517d57600080fd5b505afa158015615191573d6000803e3d6000fd5b505050506040513d60208110156151a757600080fd5b5051146151ba57615113600a600961311e565b876001600160a01b0316876001600160a01b031614156151e0576151136006600f61311e565b856151f1576151136007600d61311e565b600019861415615207576151136007600c61311e565b6000806152168a8a8a89614369565b909250905081156152465761523782601081111561523057fe5b601061311e565b94506000935061557f92505050565b6005546040805163c488847b60e01b81523060048201526001600160a01b038a81166024830152604482018590528251600094859492169263c488847b926064808301939192829003018186803b1580156152a057600080fd5b505afa1580156152b4573d6000803e3d6000fd5b505050506040513d60408110156152ca57600080fd5b508051602090910151909250905081156153155760405162461bcd60e51b81526004018080602001828103825260328152602001806157316032913960400191505060405180910390fd5b80896001600160a01b03166370a082318d6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561536c57600080fd5b505afa158015615380573d6000803e3d6000fd5b505050506040513d602081101561539657600080fd5b505110156153eb576040805162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d5543480000000000000000604482015290519081900360640190fd5b60006001600160a01b038a163014156154115761540a308e8e85613dad565b905061549b565b6040805163b2a02ff160e01b81526001600160a01b038f811660048301528e81166024830152604482018590529151918c169163b2a02ff1916064808201926020929091908290030181600087803b15801561546c57600080fd5b505af1158015615480573d6000803e3d6000fd5b505050506040513d602081101561549657600080fd5b505190505b80156154e5576040805162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b604482015290519081900360640190fd5b7f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb528d8d868d8660405180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001848152602001836001600160a01b03166001600160a01b031681526020018281526020019550505050505060405180910390a16000975092955050505050505b9550959350505050565b60006155936155d5565b61307584846155a06155d5565b60006155b4670de0b6b3a764000085613d38565b905060405180602001604052806155cb83866146f7565b9052949350505050565b6040518060200160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061562957805160ff1916838001178555615656565b82800160010185558215615656579182015b8281111561565657825182559160200191906001019061563b565b50612c649291506156f2565b6040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180606001604052806000815260200160008152602001600081525090565b604080516080810190915280600081526020016000815260200160008152602001600081525090565b61115691905b80821115612c6457600081556001016156f856fe6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d61726b65744c49515549444154455f4a4f4554524f4c4c45525f43414c43554c4154455f414d4f554e545f5345495a455f4641494c45446d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6e6365696e697469616c2065786368616e67652072617465206d7573742062652067726561746572207468616e207a65726f2e6f6e6c792061646d696e2063616e2073657420636f6c6c61746572616c2063617073657474696e6720696e7465726573742072617465206d6f64656c206661696c65646f6e6c79206a6f6574726f6c6c6572206d617920726567697374657220636f6c6c61746572616c20666f7220757365726f6e6c79207468652061646d696e206d61792063616c6c205f72657369676e496d706c656d656e746174696f6e45524333313536466c617368426f72726f776572496e746572666163652e6f6e466c6173684c6f616eddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6f6e6c79206a6f6574726f6c6c6572206d617920756e726567697374657220636f6c6c61746572616c20666f7220757365726f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416d6f756e74496e206d757374206265207a65726f6f6e6c79207468652061646d696e206d61792063616c6c205f6265636f6d65496d706c656d656e746174696f6e1d22042d9eb89f2620572acbf8d85b66fba5a2ca19d166d8659574440175c964666c6173684c6f616e20616d6f756e742073686f756c642062652067726561746572207468616e207a65726fa265627a7a723158204ccaf3ef2efe2de5576d7a82c9c2d5d23b21bfeff7d084485e25459c3c61e6f064736f6c63430005100032",
  "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)"
      },
      "_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."
      },
      "_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": 14746,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "_notEntered",
        "offset": 0,
        "slot": "0",
        "type": "t_bool"
      },
      {
        "astId": 14748,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "name",
        "offset": 0,
        "slot": "1",
        "type": "t_string_storage"
      },
      {
        "astId": 14750,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "symbol",
        "offset": 0,
        "slot": "2",
        "type": "t_string_storage"
      },
      {
        "astId": 14752,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "decimals",
        "offset": 0,
        "slot": "3",
        "type": "t_uint8"
      },
      {
        "astId": 14760,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "admin",
        "offset": 1,
        "slot": "3",
        "type": "t_address_payable"
      },
      {
        "astId": 14762,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "pendingAdmin",
        "offset": 0,
        "slot": "4",
        "type": "t_address_payable"
      },
      {
        "astId": 14764,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "joetroller",
        "offset": 0,
        "slot": "5",
        "type": "t_contract(JoetrollerInterface)21023"
      },
      {
        "astId": 14766,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "interestRateModel",
        "offset": 0,
        "slot": "6",
        "type": "t_contract(InterestRateModel)2449"
      },
      {
        "astId": 14768,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "initialExchangeRateMantissa",
        "offset": 0,
        "slot": "7",
        "type": "t_uint256"
      },
      {
        "astId": 14770,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "reserveFactorMantissa",
        "offset": 0,
        "slot": "8",
        "type": "t_uint256"
      },
      {
        "astId": 14772,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "accrualBlockTimestamp",
        "offset": 0,
        "slot": "9",
        "type": "t_uint256"
      },
      {
        "astId": 14774,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "borrowIndex",
        "offset": 0,
        "slot": "10",
        "type": "t_uint256"
      },
      {
        "astId": 14776,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "totalBorrows",
        "offset": 0,
        "slot": "11",
        "type": "t_uint256"
      },
      {
        "astId": 14778,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "totalReserves",
        "offset": 0,
        "slot": "12",
        "type": "t_uint256"
      },
      {
        "astId": 14780,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "totalSupply",
        "offset": 0,
        "slot": "13",
        "type": "t_uint256"
      },
      {
        "astId": 14784,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "accountTokens",
        "offset": 0,
        "slot": "14",
        "type": "t_mapping(t_address,t_uint256)"
      },
      {
        "astId": 14790,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "transferAllowances",
        "offset": 0,
        "slot": "15",
        "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))"
      },
      {
        "astId": 14799,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "accountBorrows",
        "offset": 0,
        "slot": "16",
        "type": "t_mapping(t_address,t_struct(BorrowSnapshot)14795_storage)"
      },
      {
        "astId": 14802,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "underlying",
        "offset": 0,
        "slot": "17",
        "type": "t_address"
      },
      {
        "astId": 14804,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "implementation",
        "offset": 0,
        "slot": "18",
        "type": "t_address"
      },
      {
        "astId": 14807,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "internalCash",
        "offset": 0,
        "slot": "19",
        "type": "t_uint256"
      },
      {
        "astId": 14810,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "totalCollateralTokens",
        "offset": 0,
        "slot": "20",
        "type": "t_uint256"
      },
      {
        "astId": 14814,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "accountCollateralTokens",
        "offset": 0,
        "slot": "21",
        "type": "t_mapping(t_address,t_uint256)"
      },
      {
        "astId": 14818,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "isCollateralTokenInit",
        "offset": 0,
        "slot": "22",
        "type": "t_mapping(t_address,t_bool)"
      },
      {
        "astId": 14820,
        "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
        "label": "collateralCap",
        "offset": 0,
        "slot": "23",
        "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)2449": {
        "encoding": "inplace",
        "label": "contract InterestRateModel",
        "numberOfBytes": "20"
      },
      "t_contract(JoetrollerInterface)21023": {
        "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)14795_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct JTokenStorage.BorrowSnapshot)",
        "numberOfBytes": "32",
        "value": "t_struct(BorrowSnapshot)14795_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)14795_storage": {
        "encoding": "inplace",
        "label": "struct JTokenStorage.BorrowSnapshot",
        "members": [
          {
            "astId": 14792,
            "contract": "contracts/JCollateralCapErc20Delegate.sol:JCollateralCapErc20Delegate",
            "label": "principal",
            "offset": 0,
            "slot": "0",
            "type": "t_uint256"
          },
          {
            "astId": 14794,
            "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"
      }
    }
  }
}
