{
  "address": "0xc896C699d147e511B0e9AA11F99ef366bf3aa96f",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "contract ComptrollerInterface",
          "name": "comptroller_",
          "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"
        },
        {
          "internalType": "address payable",
          "name": "admin_",
          "type": "address"
        }
      ],
      "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": 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": "cTokenCollateral",
          "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": "contract ComptrollerInterface",
          "name": "oldComptroller",
          "type": "address"
        },
        {
          "indexed": false,
          "internalType": "contract ComptrollerInterface",
          "name": "newComptroller",
          "type": "address"
        }
      ],
      "name": "NewComptroller",
      "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"
    },
    {
      "payable": true,
      "stateMutability": "payable",
      "type": "fallback"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "_acceptAdmin",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "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": [
        {
          "internalType": "contract ComptrollerInterface",
          "name": "newComptroller",
          "type": "address"
        }
      ],
      "name": "_setComptroller",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "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": "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": [],
      "name": "accrualBlockNumber",
      "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": "borrowRatePerBlock",
      "outputs": [
        {
          "internalType": "uint256",
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "comptroller",
      "outputs": [
        {
          "internalType": "contract ComptrollerInterface",
          "name": "",
          "type": "address"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "decimals",
      "outputs": [
        {
          "internalType": "uint8",
          "name": "",
          "type": "uint8"
        }
      ],
      "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": "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": [
        {
          "internalType": "contract ComptrollerInterface",
          "name": "comptroller_",
          "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": "isCToken",
      "outputs": [
        {
          "internalType": "bool",
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "internalType": "address",
          "name": "borrower",
          "type": "address"
        },
        {
          "internalType": "contract CTokenDeprecated",
          "name": "cTokenCollateral",
          "type": "address"
        }
      ],
      "name": "liquidateBorrow",
      "outputs": [],
      "payable": true,
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "mint",
      "outputs": [],
      "payable": true,
      "stateMutability": "payable",
      "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": [],
      "name": "repayBorrow",
      "outputs": [],
      "payable": true,
      "stateMutability": "payable",
      "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": "supplyRatePerBlock",
      "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": "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"
    }
  ],
  "transactionHash": "0xc009d58e874978262c1706ded6647ce7d9ce18d4627f50c1bf90706c66ac77bd",
  "receipt": {
    "to": null,
    "from": "0x5D3e4C0FE11e0aE4c32F0FF74B4544C49538AC61",
    "contractAddress": "0xc896C699d147e511B0e9AA11F99ef366bf3aa96f",
    "transactionIndex": 1,
    "gasUsed": "3924543",
    "logsBloom": "0x00000000000000000000000000000000000000100000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000102000000000000000000000000000000000000000000000000000004000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000",
    "blockHash": "0xab8f7a1747fb0511c087e44fcbbcc2c06fe2d46268ef47292a6fbe920130fa44",
    "transactionHash": "0xc009d58e874978262c1706ded6647ce7d9ce18d4627f50c1bf90706c66ac77bd",
    "logs": [
      {
        "transactionIndex": 1,
        "blockNumber": 9192561,
        "transactionHash": "0xc009d58e874978262c1706ded6647ce7d9ce18d4627f50c1bf90706c66ac77bd",
        "address": "0xc896C699d147e511B0e9AA11F99ef366bf3aa96f",
        "topics": [
          "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d"
        ],
        "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a2b1195508400c958b6a67587f6f4498bf0c400",
        "logIndex": 1,
        "blockHash": "0xab8f7a1747fb0511c087e44fcbbcc2c06fe2d46268ef47292a6fbe920130fa44"
      },
      {
        "transactionIndex": 1,
        "blockNumber": 9192561,
        "transactionHash": "0xc009d58e874978262c1706ded6647ce7d9ce18d4627f50c1bf90706c66ac77bd",
        "address": "0xc896C699d147e511B0e9AA11F99ef366bf3aa96f",
        "topics": [
          "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926"
        ],
        "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000098539e7fa4c8929a618ad1d55d2dde51580e2199",
        "logIndex": 2,
        "blockHash": "0xab8f7a1747fb0511c087e44fcbbcc2c06fe2d46268ef47292a6fbe920130fa44"
      }
    ],
    "blockNumber": 9192561,
    "cumulativeGasUsed": "3971026",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0x6a2b1195508400C958b6a67587F6f4498bF0c400",
    "0x98539E7fa4C8929a618ad1D55D2DDE51580E2199",
    "200000000000000000000000000",
    "Compound Ether Token",
    "cEther",
    "8",
    "0x5D3e4C0FE11e0aE4c32F0FF74B4544C49538AC61"
  ],
  "solcInputHash": "af94273bfeb935476334f847f3412514",
  "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"comptroller_\",\"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\"},{\"internalType\":\"address payable\",\"name\":\"admin_\",\"type\":\"address\"}],\"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\":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\":\"cTokenCollateral\",\"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\":\"contract ComptrollerInterface\",\"name\":\"oldComptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract ComptrollerInterface\",\"name\":\"newComptroller\",\"type\":\"address\"}],\"name\":\"NewComptroller\",\"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\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"constant\":false,\"inputs\":[],\"name\":\"_acceptAdmin\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"newComptroller\",\"type\":\"address\"}],\"name\":\"_setComptroller\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"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\":[],\"name\":\"accrualBlockNumber\",\"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\":\"borrowRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"comptroller\",\"outputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"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\":\"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\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"comptroller_\",\"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\":\"isCToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"contract CTokenDeprecated\",\"name\":\"cTokenCollateral\",\"type\":\"address\"}],\"name\":\"liquidateBorrow\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"mint\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"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\":[],\"name\":\"repayBorrow\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"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\":\"supplyRatePerBlock\",\"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\":\"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\"}],\"devdoc\":{\"author\":\"Compound\",\"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)\"},\"_reduceReserves(uint256)\":{\"params\":{\"reduceAmount\":\"Amount of reduction to reserves\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_setComptroller(address)\":{\"details\":\"Admin function to set a new comptroller\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_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)\"},\"_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 block  up to the current block 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\"},\"borrowRatePerBlock()\":{\"return\":\"The borrow interest rate per block, scaled by 1e18\"},\"constructor\":{\"params\":{\"admin_\":\"Address of the administrator of this token\",\"comptroller_\":\"The address of the Comptroller\",\"decimals_\":\"ERC-20 decimal precision of this token\",\"initialExchangeRateMantissa_\":\"The initial exchange rate, scaled by 1e18\",\"interestRateModel_\":\"The address of the interest rate model\",\"name_\":\"ERC-20 name of this token\",\"symbol_\":\"ERC-20 symbol of this token\"}},\"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\"},\"getAccountSnapshot(address)\":{\"details\":\"This is used by comptroller 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,uint256,string,string,uint8)\":{\"params\":{\"comptroller_\":\"The address of the Comptroller\",\"decimals_\":\"EIP-20 decimal precision of this token\",\"initialExchangeRateMantissa_\":\"The initial exchange rate, scaled by 1e18\",\"interestRateModel_\":\"The address of the interest rate model\",\"name_\":\"EIP-20 name of this token\",\"symbol_\":\"EIP-20 symbol of this token\"}},\"liquidateBorrow(address,address)\":{\"details\":\"Reverts upon any failure\",\"params\":{\"borrower\":\"The borrower of this cToken to be liquidated\",\"cTokenCollateral\":\"The market in which to seize collateral from the borrower\"}},\"mint()\":{\"details\":\"Reverts upon any failure\"},\"redeem(uint256)\":{\"details\":\"Accrues interest whether or not the operation succeeds, unless reverted\",\"params\":{\"redeemTokens\":\"The number of cTokens 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)\"},\"repayBorrow()\":{\"details\":\"Reverts upon any failure\"},\"seize(address,address,uint256)\":{\"details\":\"Will fail unless called by another cToken during the process of liquidation. Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.\",\"params\":{\"borrower\":\"The account having collateral seized\",\"liquidator\":\"The account receiving seized collateral\",\"seizeTokens\":\"The number of cTokens to seize\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"supplyRatePerBlock()\":{\"return\":\"The supply interest rate per block, 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\"}},\"title\":\"Compound's CEther Contract\"},\"userdoc\":{\"methods\":{\"_acceptAdmin()\":{\"notice\":\"Accepts transfer of admin rights. msg.sender must be pendingAdmin\"},\"_reduceReserves(uint256)\":{\"notice\":\"Accrues interest and reduces reserves by transferring to admin\"},\"_setComptroller(address)\":{\"notice\":\"Sets a new comptroller for the market\"},\"_setInterestRateModel(address)\":{\"notice\":\"accrues interest and updates the interest rate model using _setInterestRateModelFresh\"},\"_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\"},\"borrowRatePerBlock()\":{\"notice\":\"Returns the current per-block borrow interest rate for this cToken\"},\"constructor\":\"Construct a new CEther money market\",\"exchangeRateCurrent()\":{\"notice\":\"Accrue interest then return the up-to-date exchange rate\"},\"exchangeRateStored()\":{\"notice\":\"Calculates the exchange rate from the underlying to the CToken\"},\"getAccountSnapshot(address)\":{\"notice\":\"Get a snapshot of the account's balances, and the cached exchange rate\"},\"getCash()\":{\"notice\":\"Get cash balance of this cToken in the underlying asset\"},\"initialize(address,address,uint256,string,string,uint8)\":{\"notice\":\"Initialize the money market\"},\"liquidateBorrow(address,address)\":{\"notice\":\"The sender liquidates the borrowers collateral. The collateral seized is transferred to the liquidator.\"},\"mint()\":{\"notice\":\"Sender supplies assets into the market and receives cTokens in exchange\"},\"redeem(uint256)\":{\"notice\":\"Sender redeems cTokens in exchange for the underlying asset\"},\"redeemUnderlying(uint256)\":{\"notice\":\"Sender redeems cTokens in exchange for a specified amount of underlying asset\"},\"repayBorrow()\":{\"notice\":\"Sender repays their own borrow\"},\"seize(address,address,uint256)\":{\"notice\":\"Transfers collateral tokens (this market) to the liquidator.\"},\"supplyRatePerBlock()\":{\"notice\":\"Returns the current per-block supply interest rate for this cToken\"},\"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`\"}},\"notice\":\"CToken which wraps Ether\"}},\"settings\":{\"compilationTarget\":{\"contracts/CEther.sol\":\"CEther\"},\"evmVersion\":\"istanbul\",\"libraries\":{\"__CACHE_BREAKER__\":\"0x00000000d41867734bbee4c6863d9255b2b06ac1\"},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CEther.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./CTokenDeprecated.sol\\\";\\n\\n/**\\n * @title Compound's CEther Contract\\n * @notice CToken which wraps Ether\\n * @author Compound\\n */\\ncontract CEther is CTokenDeprecated {\\n    /**\\n     * @notice Construct a new CEther money market\\n     * @param comptroller_ The address of the Comptroller\\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     * @param admin_ Address of the administrator of this token\\n     */\\n    constructor(\\n        ComptrollerInterface comptroller_,\\n        InterestRateModel interestRateModel_,\\n        uint256 initialExchangeRateMantissa_,\\n        string memory name_,\\n        string memory symbol_,\\n        uint8 decimals_,\\n        address payable admin_\\n    ) public {\\n        // Creator of the contract is admin during initialization\\n        admin = msg.sender;\\n\\n        initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\\n\\n        // Set the proper admin now that initialization is done\\n        admin = admin_;\\n    }\\n\\n    /*** User Interface ***/\\n\\n    /**\\n     * @notice Sender supplies assets into the market and receives cTokens in exchange\\n     * @dev Reverts upon any failure\\n     */\\n    function mint() external payable {\\n        (uint256 err, ) = mintInternal(msg.value);\\n        requireNoError(err, \\\"mint failed\\\");\\n    }\\n\\n    /**\\n     * @notice Sender redeems cTokens in exchange for the underlying asset\\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n     * @param redeemTokens The number of cTokens 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);\\n    }\\n\\n    /**\\n     * @notice Sender redeems cTokens 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);\\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);\\n    }\\n\\n    /**\\n     * @notice Sender repays their own borrow\\n     * @dev Reverts upon any failure\\n     */\\n    function repayBorrow() external payable {\\n        (uint256 err, ) = repayBorrowInternal(msg.value);\\n        requireNoError(err, \\\"repayBorrow failed\\\");\\n    }\\n\\n    /**\\n     * @notice The sender liquidates the borrowers collateral.\\n     *  The collateral seized is transferred to the liquidator.\\n     * @dev Reverts upon any failure\\n     * @param borrower The borrower of this cToken to be liquidated\\n     * @param cTokenCollateral The market in which to seize collateral from the borrower\\n     */\\n    function liquidateBorrow(address borrower, CTokenDeprecated cTokenCollateral) external payable {\\n        (uint256 err, ) = liquidateBorrowInternal(borrower, msg.value, cTokenCollateral);\\n        requireNoError(err, \\\"liquidateBorrow failed\\\");\\n    }\\n\\n    /**\\n     * @notice Send Ether to CEther to mint\\n     */\\n    function() external payable {\\n        (uint256 err, ) = mintInternal(msg.value);\\n        requireNoError(err, \\\"mint failed\\\");\\n    }\\n\\n    /*** Safe Token ***/\\n\\n    /**\\n     * @notice Gets balance of this contract in terms of Ether, before this message\\n     * @dev This excludes the value of the current message, if any\\n     * @return The quantity of Ether owned by this contract\\n     */\\n    function getCashPrior() internal view returns (uint256) {\\n        (MathError err, uint256 startingBalance) = subUInt(address(this).balance, msg.value);\\n        require(err == MathError.NO_ERROR);\\n        return startingBalance;\\n    }\\n\\n    /**\\n     * @notice Perform the actual transfer in, which is a no-op\\n     * @param from Address sending the Ether\\n     * @param amount Amount of Ether being sent\\n     * @return The actual amount of Ether transferred\\n     */\\n    function doTransferIn(address from, uint256 amount) internal returns (uint256) {\\n        // Sanity checks\\n        require(msg.sender == from, \\\"sender mismatch\\\");\\n        require(msg.value == amount, \\\"value mismatch\\\");\\n        return amount;\\n    }\\n\\n    function doTransferOut(address payable to, uint256 amount) internal {\\n        /* Send the Ether, with minimal gas and revert on failure */\\n        to.transfer(amount);\\n    }\\n\\n    function requireNoError(uint256 errCode, string memory message) internal pure {\\n        if (errCode == uint256(Error.NO_ERROR)) {\\n            return;\\n        }\\n\\n        bytes memory fullMessage = new bytes(bytes(message).length + 5);\\n        uint256 i;\\n\\n        for (i = 0; i < bytes(message).length; i++) {\\n            fullMessage[i] = bytes(message)[i];\\n        }\\n\\n        fullMessage[i + 0] = bytes1(uint8(32));\\n        fullMessage[i + 1] = bytes1(uint8(40));\\n        fullMessage[i + 2] = bytes1(uint8(48 + (errCode / 10)));\\n        fullMessage[i + 3] = bytes1(uint8(48 + (errCode % 10)));\\n        fullMessage[i + 4] = bytes1(uint8(41));\\n\\n        require(errCode == uint256(Error.NO_ERROR), string(fullMessage));\\n    }\\n}\\n\",\"keccak256\":\"0xea562c18a7e2d8aaedc60aedf0a0733289fcdf8cfa39c61797bc6d0bf16faae3\"},\"contracts/CToken.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Compound's CToken Contract\\n * @notice Abstract base for CTokens\\n * @author Compound\\n */\\ncontract CToken is CTokenInterface, Exponential, TokenErrorReporter {\\n    /**\\n     * @notice Initialize the money market\\n     * @param comptroller_ The address of the Comptroller\\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        ComptrollerInterface comptroller_,\\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(accrualBlockNumber == 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 comptroller\\n        uint256 err = _setComptroller(comptroller_);\\n        require(err == uint256(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n        // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n        accrualBlockNumber = getBlockNumber();\\n        borrowIndex = mantissaOne;\\n\\n        // Set the interest rate model (depends on block number / 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 comptroller 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 cTokenBalance = getCTokenBalanceInternal(account);\\n        uint256 borrowBalance = borrowBalanceStoredInternal(account);\\n        uint256 exchangeRateMantissa = exchangeRateStoredInternal();\\n\\n        return (uint256(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n    }\\n\\n    /**\\n     * @dev Function to simply retrieve block number\\n     *  This exists mainly for inheriting test contracts to stub this result.\\n     */\\n    function getBlockNumber() internal view returns (uint256) {\\n        return block.timestamp;\\n    }\\n\\n    /**\\n     * @notice Returns the current per-block borrow interest rate for this cToken\\n     * @return The borrow interest rate per block, scaled by 1e18\\n     */\\n    function borrowRatePerBlock() external view returns (uint256) {\\n        return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n    }\\n\\n    /**\\n     * @notice Returns the current per-block supply interest rate for this cToken\\n     * @return The supply interest rate per block, scaled by 1e18\\n     */\\n    function supplyRatePerBlock() external view returns (uint256) {\\n        return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n    }\\n\\n    /**\\n     * @notice Returns the estimated per-block borrow interest rate for this cToken after some change\\n     * @return The borrow interest rate per block, scaled by 1e18\\n     */\\n    function estimateBorrowRatePerBlockAfterChange(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-block supply interest rate for this cToken after some change\\n     * @return The supply interest rate per block, scaled by 1e18\\n     */\\n    function estimateSupplyRatePerBlockAfterChange(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 CToken\\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 CToken\\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 cToken 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 block\\n     *   up to the current block and writes new checkpoint to storage.\\n     */\\n    function accrueInterest() public returns (uint256) {\\n        /* Remember the initial block number */\\n        uint256 currentBlockNumber = getBlockNumber();\\n        uint256 accrualBlockNumberPrior = accrualBlockNumber;\\n\\n        /* Short-circuit accumulating 0 interest */\\n        if (accrualBlockNumberPrior == currentBlockNumber) {\\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 blocks elapsed since the last accrual */\\n        uint256 blockDelta = sub_(currentBlockNumber, accrualBlockNumberPrior);\\n\\n        /*\\n         * Calculate the interest accumulated into borrows and reserves and the new index:\\n         *  simpleInterestFactor = borrowRate * blockDelta\\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}), blockDelta);\\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        accrualBlockNumber = currentBlockNumber;\\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 cTokens 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 cTokens in exchange for the underlying asset\\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n     * @param redeemTokens The number of cTokens 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 cTokens 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 cTokens\\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 = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n        if (allowed != 0) {\\n            return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n        }\\n\\n        /*\\n         * Return if borrowAmount is zero.\\n         * Put behind `borrowAllowed` for accuring potential COMP rewards.\\n         */\\n        if (borrowAmount == 0) {\\n            accountBorrows[borrower].interestIndex = borrowIndex;\\n            return uint256(Error.NO_ERROR);\\n        }\\n\\n        /* Verify market's block number equals current block number */\\n        if (accrualBlockNumber != getBlockNumber()) {\\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 cToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the cToken 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        // comptroller.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    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 = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n        if (allowed != 0) {\\n            return (\\n                failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n                0\\n            );\\n        }\\n\\n        /*\\n         * Return if repayAmount is zero.\\n         * Put behind `repayBorrowAllowed` for accuring potential COMP 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 number equals current block number */\\n        if (accrualBlockNumber != getBlockNumber()) {\\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 cToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the cToken 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        // comptroller.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 cToken to be liquidated\\n     * @param repayAmount The amount of the underlying borrowed asset to repay\\n     * @param cTokenCollateral 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        CTokenInterface cTokenCollateral,\\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 = cTokenCollateral.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, cTokenCollateral, 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 cToken to be liquidated\\n     * @param liquidator The address repaying the borrow and seizing collateral\\n     * @param cTokenCollateral 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        CTokenInterface cTokenCollateral,\\n        bool isNative\\n    ) internal returns (uint256, uint256) {\\n        /* Fail if liquidate not allowed */\\n        uint256 allowed = comptroller.liquidateBorrowAllowed(\\n            address(this),\\n            address(cTokenCollateral),\\n            liquidator,\\n            borrower,\\n            repayAmount\\n        );\\n        if (allowed != 0) {\\n            return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n        }\\n\\n        /* Verify market's block number equals current block number */\\n        if (accrualBlockNumber != getBlockNumber()) {\\n            return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n        }\\n\\n        /* Verify cTokenCollateral market's block number equals current block number */\\n        if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\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) = comptroller.liquidateCalculateSeizeTokens(\\n            address(this),\\n            address(cTokenCollateral),\\n            actualRepayAmount\\n        );\\n        require(amountSeizeError == uint256(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n        /* Revert if borrower collateral token balance < seizeTokens */\\n        require(cTokenCollateral.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(cTokenCollateral) == address(this)) {\\n            seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n        } else {\\n            seizeError = cTokenCollateral.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(cTokenCollateral), seizeTokens);\\n\\n        /* We call the defense hook */\\n        // unused function\\n        // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), 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 cToken during the process of liquidation.\\n     *  Its absolutely critical to use msg.sender as the borrowed cToken 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 cTokens 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 comptroller for the market\\n     * @dev Admin function to set a new comptroller\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _setComptroller(ComptrollerInterface newComptroller) public returns (uint256) {\\n        // Check caller is admin\\n        if (msg.sender != admin) {\\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n        }\\n\\n        ComptrollerInterface oldComptroller = comptroller;\\n        // Ensure invoke comptroller.isComptroller() returns true\\n        require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n        // Set market's comptroller to newComptroller\\n        comptroller = newComptroller;\\n\\n        // Emit NewComptroller(oldComptroller, newComptroller)\\n        emit NewComptroller(oldComptroller, newComptroller);\\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 number equals current block number\\n        if (accrualBlockNumber != getBlockNumber()) {\\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 number equals current block number\\n        if (accrualBlockNumber != getBlockNumber()) {\\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 cToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the cToken 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 number equals current block number\\n        if (accrualBlockNumber != getBlockNumber()) {\\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 `CWrappedNative` 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 number equals current block number\\n        if (accrualBlockNumber != getBlockNumber()) {\\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 cToken balances\\n     */\\n    function getCTokenBalanceInternal(address account) internal view returns (uint256);\\n\\n    /**\\n     * @notice User supplies assets into the market and receives cTokens in exchange\\n     * @dev Assumes interest has already been accrued up to the current block\\n     */\\n    function mintFresh(\\n        address minter,\\n        uint256 mintAmount,\\n        bool isNative\\n    ) internal returns (uint256, uint256);\\n\\n    /**\\n     * @notice User redeems cTokens in exchange for the underlying asset\\n     * @dev Assumes interest has already been accrued up to the current block\\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 CToken.\\n     *  Its absolutely critical to use msg.sender as the seizer cToken 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\":\"0x4f67ad56baaf08d0577c2890f3476e40a7bead5d1ac0e534d63a6f36721ff6f1\"},\"contracts/CTokenDeprecated.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./CTokenInterfaces.sol\\\";\\nimport \\\"./ErrorReporter.sol\\\";\\nimport \\\"./Exponential.sol\\\";\\nimport \\\"./EIP20Interface.sol\\\";\\nimport \\\"./EIP20NonStandardInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title Deprecated CToken Contract only for CEther.\\n * @dev CEther will not be used anymore and existing CEther can't be upgraded.\\n * @author Cream\\n */\\ncontract CTokenDeprecated is CTokenInterface, Exponential, TokenErrorReporter {\\n    /**\\n     * @notice Initialize the money market\\n     * @param comptroller_ The address of the Comptroller\\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        ComptrollerInterface comptroller_,\\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(accrualBlockNumber == 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 comptroller\\n        uint256 err = _setComptroller(comptroller_);\\n        require(err == uint256(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n        // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n        accrualBlockNumber = getBlockNumber();\\n        borrowIndex = mantissaOne;\\n\\n        // Set the interest rate model (depends on block number / 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 `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        /* Fail if transfer not allowed */\\n        uint256 allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n        if (allowed != 0) {\\n            return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_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        uint256 allowanceNew = sub_(startingAllowance, tokens);\\n        uint256 srcTokensNew = sub_(accountTokens[src], tokens);\\n        uint256 dstTokensNew = add_(accountTokens[dst], tokens);\\n\\n        /////////////////////////\\n        // EFFECTS & INTERACTIONS\\n        // (No safe failures beyond this point)\\n\\n        accountTokens[src] = srcTokensNew;\\n        accountTokens[dst] = dstTokensNew;\\n\\n        /* Eat some of the allowance (if necessary) */\\n        if (startingAllowance != uint256(-1)) {\\n            transferAllowances[src][spender] = allowanceNew;\\n        }\\n\\n        /* We emit a Transfer event */\\n        emit Transfer(src, dst, tokens);\\n\\n        comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n        return uint256(Error.NO_ERROR);\\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 comptroller 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 cTokenBalance = accountTokens[account];\\n        uint256 borrowBalance = borrowBalanceStoredInternal(account);\\n        uint256 exchangeRateMantissa = exchangeRateStoredInternal();\\n\\n        return (uint256(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\\n    }\\n\\n    /**\\n     * @dev Function to simply retrieve block number\\n     *  This exists mainly for inheriting test contracts to stub this result.\\n     */\\n    function getBlockNumber() internal view returns (uint256) {\\n        return block.number;\\n    }\\n\\n    /**\\n     * @notice Returns the current per-block borrow interest rate for this cToken\\n     * @return The borrow interest rate per block, scaled by 1e18\\n     */\\n    function borrowRatePerBlock() external view returns (uint256) {\\n        return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n    }\\n\\n    /**\\n     * @notice Returns the current per-block supply interest rate for this cToken\\n     * @return The supply interest rate per block, scaled by 1e18\\n     */\\n    function supplyRatePerBlock() external view returns (uint256) {\\n        return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, 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 CToken\\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 CToken\\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 cToken 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 block\\n     *   up to the current block and writes new checkpoint to storage.\\n     */\\n    function accrueInterest() public returns (uint256) {\\n        /* Remember the initial block number */\\n        uint256 currentBlockNumber = getBlockNumber();\\n        uint256 accrualBlockNumberPrior = accrualBlockNumber;\\n\\n        /* Short-circuit accumulating 0 interest */\\n        if (accrualBlockNumberPrior == currentBlockNumber) {\\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 blocks elapsed since the last accrual */\\n        uint256 blockDelta = sub_(currentBlockNumber, accrualBlockNumberPrior);\\n\\n        /*\\n         * Calculate the interest accumulated into borrows and reserves and the new index:\\n         *  simpleInterestFactor = borrowRate * blockDelta\\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}), blockDelta);\\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        accrualBlockNumber = currentBlockNumber;\\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 cTokens 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, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n     */\\n    function mintInternal(uint256 mintAmount) 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);\\n    }\\n\\n    struct MintLocalVars {\\n        Error err;\\n        MathError mathErr;\\n        uint256 exchangeRateMantissa;\\n        uint256 mintTokens;\\n        uint256 totalSupplyNew;\\n        uint256 accountTokensNew;\\n        uint256 actualMintAmount;\\n    }\\n\\n    /**\\n     * @notice User supplies assets into the market and receives cTokens in exchange\\n     * @dev Assumes interest has already been accrued up to the current block\\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     * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n     */\\n    function mintFresh(address minter, uint256 mintAmount) internal returns (uint256, uint256) {\\n        /* Fail if mint not allowed */\\n        uint256 allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n        if (allowed != 0) {\\n            return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n        }\\n\\n        /* Verify market's block number equals current block number */\\n        if (accrualBlockNumber != getBlockNumber()) {\\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 cToken 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 cToken holds an additional `actualMintAmount`\\n         *  of cash.\\n         */\\n        vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n        /*\\n         * We get the current exchange rate and calculate the number of cTokens to be minted:\\n         *  mintTokens = actualMintAmount / exchangeRate\\n         */\\n\\n        vars.mintTokens = div_ScalarByExpTruncate(vars.actualMintAmount, Exp({mantissa: vars.exchangeRateMantissa}));\\n\\n        /*\\n         * We calculate the new total supply of cTokens and minter token balance, checking for overflow:\\n         *  totalSupplyNew = totalSupply + mintTokens\\n         *  accountTokensNew = accountTokens[minter] + mintTokens\\n         */\\n        vars.totalSupplyNew = add_(totalSupply, vars.mintTokens);\\n        vars.accountTokensNew = add_(accountTokens[minter], vars.mintTokens);\\n\\n        /* We write previously calculated values into storage */\\n        totalSupply = vars.totalSupplyNew;\\n        accountTokens[minter] = vars.accountTokensNew;\\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        comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n        return (uint256(Error.NO_ERROR), vars.actualMintAmount);\\n    }\\n\\n    /**\\n     * @notice Sender redeems cTokens in exchange for the underlying asset\\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n     * @param redeemTokens The number of cTokens to redeem into underlying\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function redeemInternal(uint256 redeemTokens) 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);\\n    }\\n\\n    /**\\n     * @notice Sender redeems cTokens 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 cTokens\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function redeemUnderlyingInternal(uint256 redeemAmount) 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);\\n    }\\n\\n    struct RedeemLocalVars {\\n        Error err;\\n        MathError mathErr;\\n        uint256 exchangeRateMantissa;\\n        uint256 redeemTokens;\\n        uint256 redeemAmount;\\n        uint256 totalSupplyNew;\\n        uint256 accountTokensNew;\\n    }\\n\\n    /**\\n     * @notice User redeems cTokens in exchange for the underlying asset\\n     * @dev Assumes interest has already been accrued up to the current block\\n     * @param redeemer The address of the account which is redeeming the tokens\\n     * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n     * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\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    ) internal returns (uint256) {\\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        /* Fail if redeem not allowed */\\n        uint256 allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n        if (allowed != 0) {\\n            return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\\n        }\\n\\n        /* Verify market's block number equals current block number */\\n        if (accrualBlockNumber != getBlockNumber()) {\\n            return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDEEM_FRESHNESS_CHECK);\\n        }\\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        vars.totalSupplyNew = sub_(totalSupply, vars.redeemTokens);\\n        vars.accountTokensNew = sub_(accountTokens[redeemer], vars.redeemTokens);\\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 cToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the cToken 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);\\n\\n        /* We write previously calculated values into storage */\\n        totalSupply = vars.totalSupplyNew;\\n        accountTokens[redeemer] = vars.accountTokensNew;\\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        comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n        return uint256(Error.NO_ERROR);\\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 borrowInternal(uint256 borrowAmount) 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);\\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     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function borrowFresh(address payable borrower, uint256 borrowAmount) internal returns (uint256) {\\n        /* Fail if borrow not allowed */\\n        uint256 allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n        if (allowed != 0) {\\n            return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\\n        }\\n\\n        /* Verify market's block number equals current block number */\\n        if (accrualBlockNumber != getBlockNumber()) {\\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 cToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the cToken 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);\\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        comptroller.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     * @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) 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);\\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     * @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    ) internal returns (uint256, uint256) {\\n        /* Fail if repayBorrow not allowed */\\n        uint256 allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n        if (allowed != 0) {\\n            return (\\n                failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n                0\\n            );\\n        }\\n\\n        /* Verify market's block number equals current block number */\\n        if (accrualBlockNumber != getBlockNumber()) {\\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 cToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the cToken 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);\\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        comptroller.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 cToken to be liquidated\\n     * @param cTokenCollateral The market in which to seize collateral from the borrower\\n     * @param repayAmount The amount of the underlying borrowed asset to repay\\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        CTokenInterface cTokenCollateral\\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 = cTokenCollateral.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, cTokenCollateral);\\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 cToken to be liquidated\\n     * @param liquidator The address repaying the borrow and seizing collateral\\n     * @param cTokenCollateral The market in which to seize collateral from the borrower\\n     * @param repayAmount The amount of the underlying borrowed asset to repay\\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        CTokenInterface cTokenCollateral\\n    ) internal returns (uint256, uint256) {\\n        /* Fail if liquidate not allowed */\\n        uint256 allowed = comptroller.liquidateBorrowAllowed(\\n            address(this),\\n            address(cTokenCollateral),\\n            liquidator,\\n            borrower,\\n            repayAmount\\n        );\\n        if (allowed != 0) {\\n            return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n        }\\n\\n        /* Verify market's block number equals current block number */\\n        if (accrualBlockNumber != getBlockNumber()) {\\n            return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n        }\\n\\n        /* Verify cTokenCollateral market's block number equals current block number */\\n        if (cTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\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(liquidator, borrower, repayAmount);\\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) = comptroller.liquidateCalculateSeizeTokens(\\n            address(this),\\n            address(cTokenCollateral),\\n            actualRepayAmount\\n        );\\n        require(amountSeizeError == uint256(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n        /* Revert if borrower collateral token balance < seizeTokens */\\n        require(cTokenCollateral.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(cTokenCollateral) == address(this)) {\\n            seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n        } else {\\n            seizeError = cTokenCollateral.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(cTokenCollateral), seizeTokens);\\n\\n        /* We call the defense hook */\\n        comptroller.liquidateBorrowVerify(\\n            address(this),\\n            address(cTokenCollateral),\\n            liquidator,\\n            borrower,\\n            actualRepayAmount,\\n            seizeTokens\\n        );\\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 cToken during the process of liquidation.\\n     *  Its absolutely critical to use msg.sender as the borrowed cToken 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 cTokens 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    /**\\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 CToken.\\n     *  Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\\n     * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\\n     * @param liquidator The account receiving seized collateral\\n     * @param borrower The account having collateral seized\\n     * @param seizeTokens The number of cTokens 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        /* Fail if seize not allowed */\\n        uint256 allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n        if (allowed != 0) {\\n            return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\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, failing on underflow/overflow:\\n         *  borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n         *  liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n         */\\n        uint256 borrowerTokensNew = sub_(accountTokens[borrower], seizeTokens);\\n        uint256 liquidatorTokensNew = add_(accountTokens[liquidator], seizeTokens);\\n\\n        /////////////////////////\\n        // EFFECTS & INTERACTIONS\\n        // (No safe failures beyond this point)\\n\\n        /* We write the previously calculated values into storage */\\n        accountTokens[borrower] = borrowerTokensNew;\\n        accountTokens[liquidator] = liquidatorTokensNew;\\n\\n        /* Emit a Transfer event */\\n        emit Transfer(borrower, liquidator, seizeTokens);\\n\\n        /* We call the defense hook */\\n        comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n        return uint256(Error.NO_ERROR);\\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 comptroller for the market\\n     * @dev Admin function to set a new comptroller\\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _setComptroller(ComptrollerInterface newComptroller) public returns (uint256) {\\n        // Check caller is admin\\n        if (msg.sender != admin) {\\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n        }\\n\\n        ComptrollerInterface oldComptroller = comptroller;\\n        // Ensure invoke comptroller.isComptroller() returns true\\n        require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n        // Set market's comptroller to newComptroller\\n        comptroller = newComptroller;\\n\\n        // Emit NewComptroller(oldComptroller, newComptroller)\\n        emit NewComptroller(oldComptroller, newComptroller);\\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 number equals current block number\\n        if (accrualBlockNumber != getBlockNumber()) {\\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     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n     */\\n    function _addReservesInternal(uint256 addAmount) 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);\\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     * @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) internal returns (uint256, uint256) {\\n        // totalReserves + actualAddAmount\\n        uint256 totalReservesNew;\\n        uint256 actualAddAmount;\\n\\n        // We fail gracefully unless market's block number equals current block number\\n        if (accrualBlockNumber != getBlockNumber()) {\\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 cToken must handle variations between ERC-20 and ETH underlying.\\n         *  On success, the cToken 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);\\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 number equals current block number\\n        if (accrualBlockNumber != getBlockNumber()) {\\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        doTransferOut(admin, reduceAmount);\\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 number equals current block number\\n        if (accrualBlockNumber != getBlockNumber()) {\\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(address from, uint256 amount) 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(address payable to, uint256 amount) internal;\\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\":\"0x39aa3acd6b3e924cc6409088af655e89bfd5f774629354d7ce371b34b44d054b\"},\"contracts/CTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./ComptrollerInterface.sol\\\";\\nimport \\\"./InterestRateModel.sol\\\";\\nimport \\\"./ERC3156FlashBorrowerInterface.sol\\\";\\n\\ncontract CTokenStorage {\\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% / block)\\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-cToken operations\\n     */\\n    ComptrollerInterface public comptroller;\\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 CTokens (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 number that interest was last accrued at\\n     */\\n    uint256 public accrualBlockNumber;\\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 CErc20Storage {\\n    /**\\n     * @notice Underlying asset for this CToken\\n     */\\n    address public underlying;\\n\\n    /**\\n     * @notice Implementation address for this contract\\n     */\\n    address public implementation;\\n}\\n\\ncontract CSupplyCapStorage {\\n    /**\\n     * @notice Internal cash counter for this CToken. Should equal underlying.balanceOf(address(this)) for CERC20.\\n     */\\n    uint256 public internalCash;\\n}\\n\\ncontract CCollateralCapStorage {\\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 CToken, zero for no cap.\\n     */\\n    uint256 public collateralCap;\\n}\\n\\n/*** Interface ***/\\n\\ncontract CTokenInterface is CTokenStorage {\\n    /**\\n     * @notice Indicator that this is a CToken contract (for inspection)\\n     */\\n    bool public constant isCToken = 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 cTokenCollateral,\\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 comptroller is changed\\n     */\\n    event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\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 borrowRatePerBlock() external view returns (uint256);\\n\\n    function supplyRatePerBlock() 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 _setComptroller(ComptrollerInterface newComptroller) 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 CErc20Interface is CErc20Storage {\\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 liquidateBorrow(\\n        address borrower,\\n        uint256 repayAmount,\\n        CTokenInterface cTokenCollateral\\n    ) external returns (uint256);\\n\\n    function _addReserves(uint256 addAmount) external returns (uint256);\\n}\\n\\ncontract CWrappedNativeInterface is CErc20Interface {\\n    /**\\n     * @notice Flash loan fee ratio\\n     */\\n    uint256 public constant flashFeeBips = 3;\\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 liquidateBorrowNative(address borrower, CTokenInterface cTokenCollateral)\\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 CCapableErc20Interface is CErc20Interface, CSupplyCapStorage {\\n    /**\\n     * @notice Flash loan fee ratio\\n     */\\n    uint256 public constant flashFeeBips = 3;\\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 CCollateralCapErc20Interface is CCapableErc20Interface, CCollateralCapStorage {\\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 CDelegatorInterface {\\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 CDelegateInterface {\\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\":\"0x64e87b2f810fcbee3ec2b9e2ae3b38ed30ec9739fb3e094aad663aa5c0bb24c0\"},\"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/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.sol\\\";\\nimport \\\"./ComptrollerStorage.sol\\\";\\n\\ncontract ComptrollerInterface {\\n    /// @notice Indicator that this is a Comptroller contract (for inspection)\\n    bool public constant isComptroller = true;\\n\\n    /*** Assets You Are In ***/\\n\\n    function enterMarkets(address[] calldata cTokens) external returns (uint256[] memory);\\n\\n    function exitMarket(address cToken) external returns (uint256);\\n\\n    /*** Policy Hooks ***/\\n\\n    function mintAllowed(\\n        address cToken,\\n        address minter,\\n        uint256 mintAmount\\n    ) external returns (uint256);\\n\\n    function mintVerify(\\n        address cToken,\\n        address minter,\\n        uint256 mintAmount,\\n        uint256 mintTokens\\n    ) external;\\n\\n    function redeemAllowed(\\n        address cToken,\\n        address redeemer,\\n        uint256 redeemTokens\\n    ) external returns (uint256);\\n\\n    function redeemVerify(\\n        address cToken,\\n        address redeemer,\\n        uint256 redeemAmount,\\n        uint256 redeemTokens\\n    ) external;\\n\\n    function borrowAllowed(\\n        address cToken,\\n        address borrower,\\n        uint256 borrowAmount\\n    ) external returns (uint256);\\n\\n    function borrowVerify(\\n        address cToken,\\n        address borrower,\\n        uint256 borrowAmount\\n    ) external;\\n\\n    function repayBorrowAllowed(\\n        address cToken,\\n        address payer,\\n        address borrower,\\n        uint256 repayAmount\\n    ) external returns (uint256);\\n\\n    function repayBorrowVerify(\\n        address cToken,\\n        address payer,\\n        address borrower,\\n        uint256 repayAmount,\\n        uint256 borrowerIndex\\n    ) external;\\n\\n    function liquidateBorrowAllowed(\\n        address cTokenBorrowed,\\n        address cTokenCollateral,\\n        address liquidator,\\n        address borrower,\\n        uint256 repayAmount\\n    ) external returns (uint256);\\n\\n    function liquidateBorrowVerify(\\n        address cTokenBorrowed,\\n        address cTokenCollateral,\\n        address liquidator,\\n        address borrower,\\n        uint256 repayAmount,\\n        uint256 seizeTokens\\n    ) external;\\n\\n    function seizeAllowed(\\n        address cTokenCollateral,\\n        address cTokenBorrowed,\\n        address liquidator,\\n        address borrower,\\n        uint256 seizeTokens\\n    ) external returns (uint256);\\n\\n    function seizeVerify(\\n        address cTokenCollateral,\\n        address cTokenBorrowed,\\n        address liquidator,\\n        address borrower,\\n        uint256 seizeTokens\\n    ) external;\\n\\n    function transferAllowed(\\n        address cToken,\\n        address src,\\n        address dst,\\n        uint256 transferTokens\\n    ) external returns (uint256);\\n\\n    function transferVerify(\\n        address cToken,\\n        address src,\\n        address dst,\\n        uint256 transferTokens\\n    ) external;\\n\\n    /*** Liquidity/Liquidation Calculations ***/\\n\\n    function liquidateCalculateSeizeTokens(\\n        address cTokenBorrowed,\\n        address cTokenCollateral,\\n        uint256 repayAmount\\n    ) external view returns (uint256, uint256);\\n}\\n\\ninterface ComptrollerInterfaceExtension {\\n    function checkMembership(address account, CToken cToken) external view returns (bool);\\n\\n    function updateCTokenVersion(address cToken, ComptrollerV1Storage.Version version) external;\\n\\n    function flashloanAllowed(\\n        address cToken,\\n        address receiver,\\n        uint256 amount,\\n        bytes calldata params\\n    ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xf0d6ccceedab5506e6e66686b2a5063081eac187cc68bab30c6f573de3408909\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"./CToken.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 comptrollerImplementation;\\n\\n    /**\\n     * @notice Pending brains of Unitroller\\n     */\\n    address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage 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 => CToken[]) 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 CToken version\\n        Version version;\\n    }\\n\\n    /**\\n     * @notice Official mapping of cTokens -> 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    struct CompMarketState {\\n        /// @notice The market's last updated compBorrowIndex or compSupplyIndex\\n        uint224 index;\\n        /// @notice The block number the index was last updated at\\n        uint32 block;\\n    }\\n\\n    /// @notice A list of all markets\\n    CToken[] public allMarkets;\\n\\n    /// @notice The portion of compRate that each market currently receives\\n    mapping(address => uint256) public compSpeeds;\\n\\n    /// @notice The COMP market supply state for each market\\n    mapping(address => CompMarketState) public compSupplyState;\\n\\n    /// @notice The COMP market borrow state for each market\\n    mapping(address => CompMarketState) public compBorrowState;\\n\\n    /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\\n    mapping(address => mapping(address => uint256)) public compSupplierIndex;\\n\\n    /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\\n    mapping(address => mapping(address => uint256)) public compBorrowerIndex;\\n\\n    /// @notice The COMP accrued but not yet transferred to each user\\n    mapping(address => uint256) public compAccrued;\\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 cToken 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 cToken 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 liquidityMining the liquidity mining module that handles the LM rewards distribution.\\n    address public liquidityMining;\\n}\\n\",\"keccak256\":\"0xb62fd5913e466594bfa47892bb5e29b9e763e566f52da3a1961887e7e23a5112\"},\"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/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\ncontract ComptrollerErrorReporter {\\n    enum Error {\\n        NO_ERROR,\\n        UNAUTHORIZED,\\n        COMPTROLLER_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        COMPTROLLER_REJECTION,\\n        COMPTROLLER_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_COMPTROLLER_REJECTION,\\n        LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n        LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n        LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n        LIQUIDATE_COMPTROLLER_REJECTION,\\n        LIQUIDATE_COMPTROLLER_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_COMPTROLLER_REJECTION,\\n        LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n        LIQUIDATE_SEIZE_TOO_MUCH,\\n        MINT_ACCRUE_INTEREST_FAILED,\\n        MINT_COMPTROLLER_REJECTION,\\n        MINT_FRESHNESS_CHECK,\\n        MINT_TRANSFER_IN_FAILED,\\n        MINT_TRANSFER_IN_NOT_POSSIBLE,\\n        REDEEM_ACCRUE_INTEREST_FAILED,\\n        REDEEM_COMPTROLLER_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_BORROW_ACCRUE_INTEREST_FAILED,\\n        REPAY_BORROW_COMPTROLLER_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_COMPTROLLER_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_COMPTROLLER_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\":\"0x83e0ec825df37a55dbc7ff92676922d1bc137680224902bcbca5b9332c970f79\"},\"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 block\\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 block (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 block\\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 block (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\":\"0x739209ad7d99f78436ac0c66eeadab58519398c6edc94033c93ba04e8fd9efe6\"},\"contracts/PriceOracle/PriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity ^0.5.16;\\n\\nimport \\\"../CToken.sol\\\";\\n\\ncontract PriceOracle {\\n    /**\\n     * @notice Get the underlying price of a cToken asset\\n     * @param cToken The cToken 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(CToken cToken) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xc72c2be6584f9c5590dd089a174cf760f9e1146606224ee86b9196a46255c514\"}},\"version\":1}",
  "bytecode": "0x60806040523480156200001157600080fd5b5060405162004a6f38038062004a6f833981810160405260e08110156200003757600080fd5b8151602083015160408085015160608601805192519496939591949391820192846401000000008211156200006b57600080fd5b9083019060208201858111156200008157600080fd5b82516401000000008111828201881017156200009c57600080fd5b82525081516020918201929091019080838360005b83811015620000cb578181015183820152602001620000b1565b50505050905090810190601f168015620000f95780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200011d57600080fd5b9083019060208201858111156200013357600080fd5b82516401000000008111828201881017156200014e57600080fd5b82525081516020918201929091019080838360005b838110156200017d57818101518382015260200162000163565b50505050905090810190601f168015620001ab5780820380516001836020036101000a031916815260200191505b506040908152602082015191015160038054610100600160a81b03191633610100021790559092509050620001e587878787878762000218565b600380546001600160a01b0390921661010002610100600160a81b03199092169190911790555062000853945050505050565b60035461010090046001600160a01b03163314620002685760405162461bcd60e51b8152600401808060200182810382526024815260200180620049d66024913960400191505060405180910390fd5b600954158015620002795750600a54155b620002b65760405162461bcd60e51b8152600401808060200182810382526023815260200180620049fa6023913960400191505060405180910390fd5b600784905583620002f95760405162461bcd60e51b815260040180806020018281038252603081526020018062004a1d6030913960400191505060405180910390fd5b60006200030f876001600160e01b036200042e16565b9050801562000365576040805162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c6564000000000000604482015290519081900360640190fd5b620003786001600160e01b036200059616565b600955670de0b6b3a7640000600a556200039b866001600160e01b036200059b16565b90508015620003dc5760405162461bcd60e51b815260040180806020018281038252602281526020018062004a4d6022913960400191505060405180910390fd5b8351620003f1906001906020870190620007b1565b50825162000407906002906020860190620007b1565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b60035460009061010090046001600160a01b03163314620004685762000460600160286001600160e01b036200074116565b905062000591565b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd2916004808301926020929190829003018186803b158015620004ae57600080fd5b505afa158015620004c3573d6000803e3d6000fd5b505050506040513d6020811015620004da57600080fd5b50516200052e576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d9281900390910190a160005b9150505b919050565b435b90565b600354600090819061010090046001600160a01b03163314620005d857620005cf6001602b6001600160e01b036200074116565b91505062000591565b620005eb6001600160e01b036200059616565b600954146200060b57620005cf600a602a6001600160e01b036200074116565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200065d57600080fd5b505afa15801562000672573d6000803e3d6000fd5b505050506040513d60208110156200068957600080fd5b5051620006dd576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269281900390910190a160006200058d565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360108111156200077157fe5b8360378111156200077e57fe5b604080519283526020830191909152600082820152519081900360600190a1826010811115620007aa57fe5b9392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620007f457805160ff191683800117855562000824565b8280016001018555821562000824579182015b828111156200082457825182559160200191906001019062000807565b506200083292915062000836565b5090565b6200059891905b808211156200083257600081556001016200083d565b61417380620008636000396000f3fe6080604052600436106102675760003560e01c806395d89b4111610144578063c37f68e2116100b6578063f2b3abbd1161007a578063f2b3abbd146109f1578063f3fdb15a14610a24578063f851a44014610a39578063f8f9da2814610a4e578063fca7820b14610a63578063fe9c44ae14610a8d57610267565b8063c37f68e2146108f4578063c5ebeaec1461094d578063db006a7514610977578063dd62ed3e146109a1578063e9c714f2146109dc57610267565b8063aa5af0fd11610108578063aa5af0fd14610811578063aae40a2a14610826578063ae9d70b014610854578063b2a02ff114610869578063b71d1a0c146108ac578063bd6d894d146108df57610267565b806395d89b411461061c57806395dd91931461063157806399d8c1b414610664578063a6afed95146107c3578063a9059cbb146107d857610267565b80633b1d21a2116101dd578063601a0bf1116101a1578063601a0bf1146105565780636c540baf1461058057806370a082311461059557806373acee98146105c8578063852a12e3146105dd5780638f840ddd1461060757610267565b80633b1d21a2146104dc5780634576b5db146104f157806347bd3718146105245780634e4d9fea146105395780635fe3b5671461054157610267565b806318160ddd1161022f57806318160ddd146103e0578063182df0f5146103f557806323b872dd1461040a578063267822471461044d578063313ce5671461047e5780633af9e669146104a957610267565b806306fdde03146102a5578063095ea7b31461032f5780631249c58b1461037c578063173b99041461038657806317bfdfbc146103ad575b600061027234610aa2565b5090506102a2816040518060400160405280600b81526020016a1b5a5b9d0819985a5b195960aa1b815250610b4a565b50005b3480156102b157600080fd5b506102ba610d4a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102f45781810151838201526020016102dc565b50505050905090810190601f1680156103215780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561033b57600080fd5b506103686004803603604081101561035257600080fd5b506001600160a01b038135169060200135610dd7565b604080519115158252519081900360200190f35b610384610e44565b005b34801561039257600080fd5b5061039b610e82565b60408051918252519081900360200190f35b3480156103b957600080fd5b5061039b600480360360208110156103d057600080fd5b50356001600160a01b0316610e88565b3480156103ec57600080fd5b5061039b610f48565b34801561040157600080fd5b5061039b610f4e565b34801561041657600080fd5b506103686004803603606081101561042d57600080fd5b506001600160a01b03813581169160208101359091169060400135610f5e565b34801561045957600080fd5b50610462610fd0565b604080516001600160a01b039092168252519081900360200190f35b34801561048a57600080fd5b50610493610fdf565b6040805160ff9092168252519081900360200190f35b3480156104b557600080fd5b5061039b600480360360208110156104cc57600080fd5b50356001600160a01b0316610fe8565b3480156104e857600080fd5b5061039b611037565b3480156104fd57600080fd5b5061039b6004803603602081101561051457600080fd5b50356001600160a01b0316611041565b34801561053057600080fd5b5061039b611193565b610384611199565b34801561054d57600080fd5b506104626111db565b34801561056257600080fd5b5061039b6004803603602081101561057957600080fd5b50356111ea565b34801561058c57600080fd5b5061039b611285565b3480156105a157600080fd5b5061039b600480360360208110156105b857600080fd5b50356001600160a01b031661128b565b3480156105d457600080fd5b5061039b6112a6565b3480156105e957600080fd5b5061039b6004803603602081101561060057600080fd5b503561135c565b34801561061357600080fd5b5061039b611367565b34801561062857600080fd5b506102ba61136d565b34801561063d57600080fd5b5061039b6004803603602081101561065457600080fd5b50356001600160a01b03166113c5565b34801561067057600080fd5b50610384600480360360c081101561068757600080fd5b6001600160a01b038235811692602081013590911691604082013591908101906080810160608201356401000000008111156106c257600080fd5b8201836020820111156106d457600080fd5b803590602001918460018302840111640100000000831117156106f657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561074957600080fd5b82018360208201111561075b57600080fd5b8035906020019184600183028401116401000000008311171561077d57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff1691506113d09050565b3480156107cf57600080fd5b5061039b6115b7565b3480156107e457600080fd5b50610368600480360360408110156107fb57600080fd5b506001600160a01b0381351690602001356117c7565b34801561081d57600080fd5b5061039b611838565b6103846004803603604081101561083c57600080fd5b506001600160a01b038135811691602001351661183e565b34801561086057600080fd5b5061039b61188b565b34801561087557600080fd5b5061039b6004803603606081101561088c57600080fd5b506001600160a01b0381358116916020810135909116906040013561192a565b3480156108b857600080fd5b5061039b600480360360208110156108cf57600080fd5b50356001600160a01b031661199b565b3480156108eb57600080fd5b5061039b611a27565b34801561090057600080fd5b506109276004803603602081101561091757600080fd5b50356001600160a01b0316611ae3565b604080519485526020850193909352838301919091526060830152519081900360800190f35b34801561095957600080fd5b5061039b6004803603602081101561097057600080fd5b5035611b2a565b34801561098357600080fd5b5061039b6004803603602081101561099a57600080fd5b5035611b35565b3480156109ad57600080fd5b5061039b600480360360408110156109c457600080fd5b506001600160a01b0381358116916020013516611b40565b3480156109e857600080fd5b5061039b611b6b565b3480156109fd57600080fd5b5061039b60048036036020811015610a1457600080fd5b50356001600160a01b0316611c6e565b348015610a3057600080fd5b50610462611ca8565b348015610a4557600080fd5b50610462611cb7565b348015610a5a57600080fd5b5061039b611ccb565b348015610a6f57600080fd5b5061039b60048036036020811015610a8657600080fd5b5035611d2f565b348015610a9957600080fd5b50610368611dad565b60008054819060ff16610ae9576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155610afb6115b7565b90508015610b2657610b19816010811115610b1257fe5b6014611db2565b925060009150610b369050565b610b303385611e1f565b92509250505b6000805460ff191660011790559092909150565b81610b5457610d46565b606081516005016040519080825280601f01601f191660200182016040528015610b85576020820181803883390190505b50905060005b8251811015610bd657828181518110610ba057fe5b602001015160f81c60f81b828281518110610bb757fe5b60200101906001600160f81b031916908160001a905350600101610b8b565b8151600160fd1b90839083908110610bea57fe5b60200101906001600160f81b031916908160001a905350602860f81b828260010181518110610c1557fe5b60200101906001600160f81b031916908160001a905350600a840460300160f81b828260020181518110610c4557fe5b60200101906001600160f81b031916908160001a905350600a840660300160f81b828260030181518110610c7557fe5b60200101906001600160f81b031916908160001a905350602960f81b828260040181518110610ca057fe5b60200101906001600160f81b031916908160001a905350818415610d425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d07578181015183820152602001610cef565b50505050905090810190601f168015610d345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5050505b5050565b60018054604080516020600284861615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dcf5780601f10610da457610100808354040283529160200191610dcf565b820191906000526020600020905b815481529060010190602001808311610db257829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855290835281842086905581518681529151939493909284927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a360019150505b92915050565b6000610e4f34610aa2565b509050610e7f816040518060400160405280600b81526020016a1b5a5b9d0819985a5b195960aa1b815250610b4a565b50565b60085481565b6000805460ff16610ecd576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155610edf6115b7565b14610f2a576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b610f33826113c5565b90505b6000805460ff19166001179055919050565b600d5481565b6000610f586120b6565b90505b90565b6000805460ff16610fa3576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155610fb93386868661211c565b1490506000805460ff191660011790559392505050565b6004546001600160a01b031681565b60035460ff1681565b6000610ff2613eca565b6040518060200160405280611005611a27565b90526001600160a01b0384166000908152600e602052604090205490915061102e9082906123b8565b9150505b919050565b6000610f586123d7565b60035460009061010090046001600160a01b0316331461106e5761106760016028611db2565b9050611032565b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd2916004808301926020929190829003018186803b1580156110b357600080fd5b505afa1580156110c7573d6000803e3d6000fd5b505050506040513d60208110156110dd57600080fd5b5051611130576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d9281900390910190a1600061102e565b600b5481565b60006111a434612409565b509050610e7f81604051806040016040528060128152602001711c995c185e509bdc9c9bddc819985a5b195960721b815250610b4a565b6005546001600160a01b031681565b6000805460ff1661122f576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556112416115b7565b905080156112675761125f81601081111561125857fe5b601d611db2565b915050610f36565b6112708361248b565b9150506000805460ff19166001179055919050565b60095481565b6001600160a01b03166000908152600e602052604090205490565b6000805460ff166112eb576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556112fd6115b7565b14611348576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b50600b546000805460ff1916600117905590565b6000610e3e82612587565b600c5481565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610dcf5780601f10610da457610100808354040283529160200191610dcf565b6000610e3e82612608565b60035461010090046001600160a01b0316331461141e5760405162461bcd60e51b815260040180806020018281038252602481526020018061401f6024913960400191505060405180910390fd5b60095415801561142e5750600a54155b6114695760405162461bcd60e51b81526004018080602001828103825260238152602001806140436023913960400191505060405180910390fd5b6007849055836114aa5760405162461bcd60e51b81526004018080602001828103825260308152602001806140666030913960400191505060405180910390fd5b60006114b587611041565b9050801561150a576040805162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c6564000000000000604482015290519081900360640190fd5b61151261265d565b600955670de0b6b3a7640000600a5561152a86612661565b905080156115695760405162461bcd60e51b81526004018080602001828103825260228152602001806140966022913960400191505060405180910390fd5b835161157c906001906020870190613edd565b508251611590906002906020860190613edd565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b6000806115c261265d565b600954909150808214156115db57600092505050610f5b565b60006115e56123d7565b600b54600c54600a54600654604080516315f2405360e01b815260048101879052602481018690526044810185905290519596509394929391926000926001600160a01b03909216916315f24053916064808301926020929190829003018186803b15801561165357600080fd5b505afa158015611667573d6000803e3d6000fd5b505050506040513d602081101561167d57600080fd5b5051905065048c273950008111156116dc576040805162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c79206869676800000000604482015290519081900360640190fd5b60006116e888886127d6565b90506116f2613eca565b61170a60405180602001604052808581525083612810565b9050600061171882886123b8565b90506000611726828961283a565b905060006117456040518060200160405280600854815250848a612870565b9050600061175485898a612870565b60098e9055600a819055600b849055600c839055604080518d8152602081018790528082018390526060810186905290519192507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc04919081900360800190a160009d505050505050505050505050505090565b6000805460ff1661180c576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556118223333868661211c565b1490506000805460ff1916600117905592915050565b600a5481565b600061184b833484612898565b50905061188681604051806040016040528060168152602001751b1a5c5d5a59185d19509bdc9c9bddc819985a5b195960521b815250610b4a565b505050565b6006546000906001600160a01b031663b81688166118a76123d7565b600b54600c546008546040518563ffffffff1660e01b81526004018085815260200184815260200183815260200182815260200194505050505060206040518083038186803b1580156118f957600080fd5b505afa15801561190d573d6000803e3d6000fd5b505050506040513d602081101561192357600080fd5b5051905090565b6000805460ff1661196f576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19169055611985338585856129ca565b90506000805460ff191660011790559392505050565b60035460009061010090046001600160a01b031633146119c1576110676001602e611db2565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a1600061102e565b6000805460ff16611a6c576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611a7e6115b7565b14611ac9576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b611ad1610f4e565b90506000805460ff1916600117905590565b6001600160a01b0381166000908152600e602052604081205481908190819081611b0c87612608565b90506000611b186120b6565b90506000989297509095509350915050565b6000610e3e82612bd3565b6000610e3e82612c52565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6004546000906001600160a01b031633141580611b86575033155b15611b9e57611b9760016000611db2565b9050610f5b565b60038054600480546001600160a01b03818116610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401528351909391927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600454604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160009250505090565b600080611c796115b7565b90508015611c9f57611c97816010811115611c9057fe5b6029611db2565b915050611032565b61102e83612661565b6006546001600160a01b031681565b60035461010090046001600160a01b031681565b6006546000906001600160a01b03166315f24053611ce76123d7565b600b54600c546040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b1580156118f957600080fd5b6000805460ff16611d74576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611d866115b7565b90508015611da45761125f816010811115611d9d57fe5b602f611db2565b61127083612ccc565b600181565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836010811115611de157fe5b836037811115611ded57fe5b604080519283526020830191909152600082820152519081900360600190a1826010811115611e1857fe5b9392505050565b60055460408051634ef4c3e160e01b81523060048201526001600160a01b03858116602483015260448201859052915160009384938493911691634ef4c3e19160648082019260209290919082900301818787803b158015611e8057600080fd5b505af1158015611e94573d6000803e3d6000fd5b505050506040513d6020811015611eaa57600080fd5b505190508015611ece57611ec16003601583612d74565b9250600091506120af9050565b611ed661265d565b60095414611eea57611ec1600a6016611db2565b611ef2613f57565b611efa6120b6565b6040820152611f098686612dda565b60c0820181905260408051602081018252908301518152611f2a9190612e76565b60608201819052600d54611f3d9161283a565b60808201526001600160a01b0386166000908152600e60205260409020546060820151611f6a919061283a565b60a082018190526080820151600d556001600160a01b0387166000818152600e60209081526040918290209390935560c084015160608086015183519485529484019190915282820193909352517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f929181900390910190a1606081015160408051918252516001600160a01b0388169130916000805160206140b88339815191529181900360200190a360055460c08201516060830151604080516341c728b960e01b81523060048201526001600160a01b038b81166024830152604482019490945260648101929092525191909216916341c728b991608480830192600092919082900301818387803b15801561208257600080fd5b505af1158015612096573d6000803e3d6000fd5b50600092506120a3915050565b8160c001519350935050505b9250929050565b600d54600090806120cb575050600754610f5b565b60006120d56123d7565b905060006120f06120e883600b5461283a565b600c546127d6565b9050600061210c82604051806020016040528087815250612e8a565b9450610f5b9350505050565b5090565b600554604080516317b9b84b60e31b81523060048201526001600160a01b03868116602483015285811660448301526064820185905291516000938493169163bdcdc25891608480830192602092919082900301818787803b15801561218157600080fd5b505af1158015612195573d6000803e3d6000fd5b505050506040513d60208110156121ab57600080fd5b5051905080156121ca576121c26003603383612d74565b9150506123b0565b836001600160a01b0316856001600160a01b031614156121f0576121c260026034611db2565b60006001600160a01b03878116908716141561220f5750600019612237565b506001600160a01b038086166000908152600f60209081526040808320938a16835292905220545b600061224382866127d6565b6001600160a01b0388166000908152600e60205260408120549192509061226a90876127d6565b6001600160a01b0388166000908152600e602052604081205491925090612291908861283a565b6001600160a01b03808b166000908152600e6020526040808220869055918b16815220819055905060001984146122eb576001600160a01b03808a166000908152600f60209081526040808320938e168352929052208390555b876001600160a01b0316896001600160a01b03166000805160206140b8833981519152896040518082815260200191505060405180910390a36005546040805163352b4a3f60e11b81523060048201526001600160a01b038c811660248301528b81166044830152606482018b905291519190921691636a56947e91608480830192600092919082900301818387803b15801561238757600080fd5b505af115801561239b573d6000803e3d6000fd5b50600092506123a8915050565b955050505050505b949350505050565b60006123c2613eca565b6123cc8484612810565b90506123b081612ea8565b60008060006123e64734612eb7565b909250905060008260038111156123f957fe5b1461240357600080fd5b91505090565b60008054819060ff16612450576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556124626115b7565b9050801561248057610b1981601081111561247957fe5b6022611db2565b610b30333386612eda565b600354600090819061010090046001600160a01b031633146124b357611c976001601e611db2565b6124bb61265d565b600954146124cf57611c97600a6020611db2565b826124d86123d7565b10156124ea57611c97600e601f611db2565b600c5483111561250057611c9760026021611db2565b61250c600c54846127d6565b600c81905560035490915061252f9061010090046001600160a01b031684613182565b600354604080516101009092046001600160a01b0316825260208201859052818101839052517f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e916060908290030190a1600061102e565b6000805460ff166125cc576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556125de6115b7565b905080156125fc5761125f8160108111156125f557fe5b6019611db2565b611270336000856131b8565b6001600160a01b03811660009081526010602052604081208054612630576000915050611032565b60006126428260000154600a546134e7565b90506000612654828460010154613529565b95945050505050565b4390565b600354600090819061010090046001600160a01b0316331461268957611c976001602b611db2565b61269161265d565b600954146126a557611c97600a602a611db2565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126f657600080fd5b505afa15801561270a573d6000803e3d6000fd5b505050506040513d602081101561272057600080fd5b5051612773576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269281900390910190a1600061102e565b6000611e188383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061355c565b612818613eca565b60405180602001604052806128318560000151856134e7565b90529392505050565b6000611e188383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b8152506135b6565b600061287a613eca565b6128848585612810565b905061265461289282612ea8565b8461283a565b60008054819060ff166128df576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556128f16115b7565b9050801561291c5761290f81601081111561290857fe5b6007611db2565b9250600091506129b39050565b836001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561295757600080fd5b505af115801561296b573d6000803e3d6000fd5b505050506040513d602081101561298157600080fd5b5051905080156129a15761290f81601081111561299a57fe5b6008611db2565b6129ad33878787613614565b92509250505b6000805460ff191660011790559094909350915050565b6005546040805163d02f735160e01b81523060048201526001600160a01b038781166024830152868116604483015285811660648301526084820185905291516000938493169163d02f73519160a480830192602092919082900301818787803b158015612a3757600080fd5b505af1158015612a4b573d6000803e3d6000fd5b505050506040513d6020811015612a6157600080fd5b505190508015612a78576121c26003601183612d74565b846001600160a01b0316846001600160a01b03161415612a9e576121c260066012611db2565b6001600160a01b0384166000908152600e6020526040812054612ac190856127d6565b6001600160a01b0387166000908152600e602052604081205491925090612ae8908661283a565b6001600160a01b038088166000818152600e60209081526040808320889055938c168083529184902085905583518a81529351949550909391926000805160206140b8833981519152929081900390910190a360055460408051636d35bf9160e01b81523060048201526001600160a01b038b811660248301528a8116604483015289811660648301526084820189905291519190921691636d35bf919160a480830192600092919082900301818387803b158015612ba657600080fd5b505af1158015612bba573d6000803e3d6000fd5b5060009250612bc7915050565b98975050505050505050565b6000805460ff16612c18576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612c2a6115b7565b90508015612c485761125f816010811115612c4157fe5b6002611db2565b6112703384613b97565b6000805460ff16612c97576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612ca96115b7565b90508015612cc05761125f8160108111156125f557fe5b611270338460006131b8565b60035460009061010090046001600160a01b03163314612cf25761106760016030611db2565b612cfa61265d565b60095414612d0e57611067600a6031611db2565b670de0b6b3a7640000821115612d2a5761106760026032611db2565b6008805490839055604080518281526020810185905281517faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460929181900390910190a1600061102e565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846010811115612da357fe5b846037811115612daf57fe5b604080519283526020830191909152818101859052519081900360600190a18360108111156123b057fe5b6000336001600160a01b03841614612e2b576040805162461bcd60e51b815260206004820152600f60248201526e0e6cadcc8cae440dad2e6dac2e8c6d608b1b604482015290519081900360640190fd5b813414612e70576040805162461bcd60e51b815260206004820152600e60248201526d0ecc2d8eaca40dad2e6dac2e8c6d60931b604482015290519081900360640190fd5b50919050565b6000612e80613eca565b6123cc8484613db5565b6000611e18612ea184670de0b6b3a76400006134e7565b8351613529565b51670de0b6b3a7640000900490565b600080838311612ece5750600090508183036120af565b506003905060006120af565b60055460408051631200453160e11b81523060048201526001600160a01b0386811660248301528581166044830152606482018590529151600093849384939116916324008a629160848082019260209290919082900301818787803b158015612f4357600080fd5b505af1158015612f57573d6000803e3d6000fd5b505050506040513d6020811015612f6d57600080fd5b505190508015612f9157612f846003602383612d74565b92506000915061317a9050565b612f9961265d565b60095414612fad57612f84600a6024611db2565b612fb5613f95565b6001600160a01b0386166000908152601060205260409020600101546060820152612fdf86612608565b6080820152600019851415612ffd5760808101516040820152613005565b604081018590525b613013878260400151612dda565b60e082018190526080820151613028916127d6565b60a0820152600b5460e082015161303f91906127d6565b60c0820190815260a080830180516001600160a01b03808b16600081815260106020908152604091829020948555600a546001909501949094559551600b81905560e088015194518751938f16845293830191909152818601939093526060810191909152608081019190915291517f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19281900390910190a160055460e0820151606083015160408051631ededc9160e01b81523060048201526001600160a01b038c811660248301528b8116604483015260648201949094526084810192909252519190921691631ededc919160a480830192600092919082900301818387803b15801561314d57600080fd5b505af1158015613161573d6000803e3d6000fd5b506000925061316e915050565b8160e001519350935050505b935093915050565b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611886573d6000803e3d6000fd5b60008215806131c5575081155b6132005760405162461bcd60e51b815260040180806020018281038252603481526020018061410b6034913960400191505060405180910390fd5b613208613f57565b6132106120b6565b6040820152831561324657606081018490526040805160208101825290820151815261323c90856123b8565b608082015261326f565b6132628360405180602001604052808460400151815250612e76565b6060820152608081018390525b60055460608201516040805163eabe7d9160e01b81523060048201526001600160a01b03898116602483015260448201939093529051600093929092169163eabe7d919160648082019260209290919082900301818787803b1580156132d457600080fd5b505af11580156132e8573d6000803e3d6000fd5b505050506040513d60208110156132fe57600080fd5b50519050801561331e576133156003601a83612d74565b92505050611e18565b61332661265d565b6009541461333a57613315600a601b611db2565b61334a600d5483606001516127d6565b60a08301526001600160a01b0386166000908152600e6020526040902054606083015161337791906127d6565b60c083015260808201516133896123d7565b101561339b57613315600e601c611db2565b6133a9868360800151613182565b60a0820151600d5560c08201516001600160a01b0387166000818152600e60209081526040918290209390935560608501518151908152905130936000805160206140b8833981519152928290030190a36080820151606080840151604080516001600160a01b038b168152602081019490945283810191909152517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a9299281900390910190a160055460808301516060840151604080516351dff98960e01b81523060048201526001600160a01b038b81166024830152604482019490945260648101929092525191909216916351dff98991608480830192600092919082900301818387803b1580156134bc57600080fd5b505af11580156134d0573d6000803e3d6000fd5b50600092506134dd915050565b9695505050505050565b6000611e1883836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250613df2565b6000611e1883836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250613e68565b600081848411156135ae5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610d07578181015183820152602001610cef565b505050900390565b6000838301828582101561360b5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610d07578181015183820152602001610cef565b50949350505050565b60055460408051632fe3f38f60e11b81523060048201526001600160a01b0384811660248301528781166044830152868116606483015260848201869052915160009384938493911691635fc7e71e9160a48082019260209290919082900301818787803b15801561368557600080fd5b505af1158015613699573d6000803e3d6000fd5b505050506040513d60208110156136af57600080fd5b5051905080156136d3576136c66003600a83612d74565b925060009150613b8e9050565b6136db61265d565b600954146136ef576136c6600a600e611db2565b6136f761265d565b846001600160a01b0316636c540baf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561373057600080fd5b505afa158015613744573d6000803e3d6000fd5b505050506040513d602081101561375a57600080fd5b50511461376d576136c6600a6009611db2565b866001600160a01b0316866001600160a01b03161415613793576136c66006600f611db2565b846137a4576136c66007600d611db2565b6000198514156137ba576136c66007600c611db2565b6000806137c8898989612eda565b909250905081156137f8576137e98260108111156137e257fe5b6010611db2565b945060009350613b8e92505050565b6005546040805163c488847b60e01b81523060048201526001600160a01b038981166024830152604482018590528251600094859492169263c488847b926064808301939192829003018186803b15801561385257600080fd5b505afa158015613866573d6000803e3d6000fd5b505050506040513d604081101561387c57600080fd5b508051602090910151909250905081156138c75760405162461bcd60e51b81526004018080602001828103825260338152602001806140d86033913960400191505060405180910390fd5b80886001600160a01b03166370a082318c6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561391e57600080fd5b505afa158015613932573d6000803e3d6000fd5b505050506040513d602081101561394857600080fd5b5051101561399d576040805162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d5543480000000000000000604482015290519081900360640190fd5b60006001600160a01b0389163014156139c3576139bc308d8d856129ca565b9050613a4d565b6040805163b2a02ff160e01b81526001600160a01b038e811660048301528d81166024830152604482018590529151918b169163b2a02ff1916064808201926020929091908290030181600087803b158015613a1e57600080fd5b505af1158015613a32573d6000803e3d6000fd5b505050506040513d6020811015613a4857600080fd5b505190505b8015613a97576040805162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b604482015290519081900360640190fd5b604080516001600160a01b03808f168252808e1660208301528183018790528b1660608201526080810184905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a1600554604080516347ef3b3b60e01b81523060048201526001600160a01b038c811660248301528f811660448301528e811660648301526084820188905260a48201869052915191909216916347ef3b3b9160c480830192600092919082900301818387803b158015613b6257600080fd5b505af1158015613b76573d6000803e3d6000fd5b5060009250613b83915050565b975092955050505050505b94509492505050565b6005546040805163368f515360e21b81523060048201526001600160a01b0385811660248301526044820185905291516000938493169163da3d454c91606480830192602092919082900301818787803b158015613bf457600080fd5b505af1158015613c08573d6000803e3d6000fd5b505050506040513d6020811015613c1e57600080fd5b505190508015613c3d57613c356003600683612d74565b915050610e3e565b613c4561265d565b60095414613c5957613c35600a6004611db2565b82613c626123d7565b1015613c7457613c35600e6003611db2565b613c7c613fdb565b613c8585612608565b60208201819052613c96908561283a565b6040820152600b54613ca8908561283a565b6060820152613cb78585613182565b604080820180516001600160a01b03881660008181526010602090815290859020928355600a54600190930192909255606080860151600b81905593518551928352928201899052818501929092529081019190915290517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809181900360800190a160055460408051635c77860560e01b81523060048201526001600160a01b0388811660248301526044820188905291519190921691635c77860591606480830192600092919082900301818387803b158015613d9457600080fd5b505af1158015613da8573d6000803e3d6000fd5b5060009250612654915050565b613dbd613eca565b6000613dd1670de0b6b3a7640000856134e7565b90506040518060200160405280613de88386612e8a565b9052949350505050565b6000831580613dff575082155b15613e0c57506000611e18565b83830283858281613e1957fe5b0414839061360b5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610d07578181015183820152602001610cef565b60008183613eb75760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610d07578181015183820152602001610cef565b50828481613ec157fe5b04949350505050565b6040518060200160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613f1e57805160ff1916838001178555613f4b565b82800160010185558215613f4b579182015b82811115613f4b578251825591602001919060010190613f30565b50612118929150614004565b6040805160e0810190915280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604080516080810190915280600081526020016000815260200160008152602001600081525090565b610f5b91905b80821115612118576000815560010161400a56fe6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d61726b65746d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6e6365696e697469616c2065786368616e67652072617465206d7573742062652067726561746572207468616e207a65726f2e73657474696e6720696e7465726573742072617465206d6f64656c206661696c6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f414d4f554e545f5345495a455f4641494c45446f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416d6f756e74496e206d757374206265207a65726fa265627a7a72315820f6ea870115936cf827e59721ee714513701b3e9e6fefb74cd7510eecc8d0cbbe64736f6c634300051000326f6e6c792061646d696e206d617920696e697469616c697a6520746865206d61726b65746d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6e6365696e697469616c2065786368616e67652072617465206d7573742062652067726561746572207468616e207a65726f2e73657474696e6720696e7465726573742072617465206d6f64656c206661696c6564",
  "deployedBytecode": "0x6080604052600436106102675760003560e01c806395d89b4111610144578063c37f68e2116100b6578063f2b3abbd1161007a578063f2b3abbd146109f1578063f3fdb15a14610a24578063f851a44014610a39578063f8f9da2814610a4e578063fca7820b14610a63578063fe9c44ae14610a8d57610267565b8063c37f68e2146108f4578063c5ebeaec1461094d578063db006a7514610977578063dd62ed3e146109a1578063e9c714f2146109dc57610267565b8063aa5af0fd11610108578063aa5af0fd14610811578063aae40a2a14610826578063ae9d70b014610854578063b2a02ff114610869578063b71d1a0c146108ac578063bd6d894d146108df57610267565b806395d89b411461061c57806395dd91931461063157806399d8c1b414610664578063a6afed95146107c3578063a9059cbb146107d857610267565b80633b1d21a2116101dd578063601a0bf1116101a1578063601a0bf1146105565780636c540baf1461058057806370a082311461059557806373acee98146105c8578063852a12e3146105dd5780638f840ddd1461060757610267565b80633b1d21a2146104dc5780634576b5db146104f157806347bd3718146105245780634e4d9fea146105395780635fe3b5671461054157610267565b806318160ddd1161022f57806318160ddd146103e0578063182df0f5146103f557806323b872dd1461040a578063267822471461044d578063313ce5671461047e5780633af9e669146104a957610267565b806306fdde03146102a5578063095ea7b31461032f5780631249c58b1461037c578063173b99041461038657806317bfdfbc146103ad575b600061027234610aa2565b5090506102a2816040518060400160405280600b81526020016a1b5a5b9d0819985a5b195960aa1b815250610b4a565b50005b3480156102b157600080fd5b506102ba610d4a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102f45781810151838201526020016102dc565b50505050905090810190601f1680156103215780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561033b57600080fd5b506103686004803603604081101561035257600080fd5b506001600160a01b038135169060200135610dd7565b604080519115158252519081900360200190f35b610384610e44565b005b34801561039257600080fd5b5061039b610e82565b60408051918252519081900360200190f35b3480156103b957600080fd5b5061039b600480360360208110156103d057600080fd5b50356001600160a01b0316610e88565b3480156103ec57600080fd5b5061039b610f48565b34801561040157600080fd5b5061039b610f4e565b34801561041657600080fd5b506103686004803603606081101561042d57600080fd5b506001600160a01b03813581169160208101359091169060400135610f5e565b34801561045957600080fd5b50610462610fd0565b604080516001600160a01b039092168252519081900360200190f35b34801561048a57600080fd5b50610493610fdf565b6040805160ff9092168252519081900360200190f35b3480156104b557600080fd5b5061039b600480360360208110156104cc57600080fd5b50356001600160a01b0316610fe8565b3480156104e857600080fd5b5061039b611037565b3480156104fd57600080fd5b5061039b6004803603602081101561051457600080fd5b50356001600160a01b0316611041565b34801561053057600080fd5b5061039b611193565b610384611199565b34801561054d57600080fd5b506104626111db565b34801561056257600080fd5b5061039b6004803603602081101561057957600080fd5b50356111ea565b34801561058c57600080fd5b5061039b611285565b3480156105a157600080fd5b5061039b600480360360208110156105b857600080fd5b50356001600160a01b031661128b565b3480156105d457600080fd5b5061039b6112a6565b3480156105e957600080fd5b5061039b6004803603602081101561060057600080fd5b503561135c565b34801561061357600080fd5b5061039b611367565b34801561062857600080fd5b506102ba61136d565b34801561063d57600080fd5b5061039b6004803603602081101561065457600080fd5b50356001600160a01b03166113c5565b34801561067057600080fd5b50610384600480360360c081101561068757600080fd5b6001600160a01b038235811692602081013590911691604082013591908101906080810160608201356401000000008111156106c257600080fd5b8201836020820111156106d457600080fd5b803590602001918460018302840111640100000000831117156106f657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561074957600080fd5b82018360208201111561075b57600080fd5b8035906020019184600183028401116401000000008311171561077d57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff1691506113d09050565b3480156107cf57600080fd5b5061039b6115b7565b3480156107e457600080fd5b50610368600480360360408110156107fb57600080fd5b506001600160a01b0381351690602001356117c7565b34801561081d57600080fd5b5061039b611838565b6103846004803603604081101561083c57600080fd5b506001600160a01b038135811691602001351661183e565b34801561086057600080fd5b5061039b61188b565b34801561087557600080fd5b5061039b6004803603606081101561088c57600080fd5b506001600160a01b0381358116916020810135909116906040013561192a565b3480156108b857600080fd5b5061039b600480360360208110156108cf57600080fd5b50356001600160a01b031661199b565b3480156108eb57600080fd5b5061039b611a27565b34801561090057600080fd5b506109276004803603602081101561091757600080fd5b50356001600160a01b0316611ae3565b604080519485526020850193909352838301919091526060830152519081900360800190f35b34801561095957600080fd5b5061039b6004803603602081101561097057600080fd5b5035611b2a565b34801561098357600080fd5b5061039b6004803603602081101561099a57600080fd5b5035611b35565b3480156109ad57600080fd5b5061039b600480360360408110156109c457600080fd5b506001600160a01b0381358116916020013516611b40565b3480156109e857600080fd5b5061039b611b6b565b3480156109fd57600080fd5b5061039b60048036036020811015610a1457600080fd5b50356001600160a01b0316611c6e565b348015610a3057600080fd5b50610462611ca8565b348015610a4557600080fd5b50610462611cb7565b348015610a5a57600080fd5b5061039b611ccb565b348015610a6f57600080fd5b5061039b60048036036020811015610a8657600080fd5b5035611d2f565b348015610a9957600080fd5b50610368611dad565b60008054819060ff16610ae9576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155610afb6115b7565b90508015610b2657610b19816010811115610b1257fe5b6014611db2565b925060009150610b369050565b610b303385611e1f565b92509250505b6000805460ff191660011790559092909150565b81610b5457610d46565b606081516005016040519080825280601f01601f191660200182016040528015610b85576020820181803883390190505b50905060005b8251811015610bd657828181518110610ba057fe5b602001015160f81c60f81b828281518110610bb757fe5b60200101906001600160f81b031916908160001a905350600101610b8b565b8151600160fd1b90839083908110610bea57fe5b60200101906001600160f81b031916908160001a905350602860f81b828260010181518110610c1557fe5b60200101906001600160f81b031916908160001a905350600a840460300160f81b828260020181518110610c4557fe5b60200101906001600160f81b031916908160001a905350600a840660300160f81b828260030181518110610c7557fe5b60200101906001600160f81b031916908160001a905350602960f81b828260040181518110610ca057fe5b60200101906001600160f81b031916908160001a905350818415610d425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610d07578181015183820152602001610cef565b50505050905090810190601f168015610d345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5050505b5050565b60018054604080516020600284861615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dcf5780601f10610da457610100808354040283529160200191610dcf565b820191906000526020600020905b815481529060010190602001808311610db257829003601f168201915b505050505081565b336000818152600f602090815260408083206001600160a01b03871680855290835281842086905581518681529151939493909284927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a360019150505b92915050565b6000610e4f34610aa2565b509050610e7f816040518060400160405280600b81526020016a1b5a5b9d0819985a5b195960aa1b815250610b4a565b50565b60085481565b6000805460ff16610ecd576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155610edf6115b7565b14610f2a576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b610f33826113c5565b90505b6000805460ff19166001179055919050565b600d5481565b6000610f586120b6565b90505b90565b6000805460ff16610fa3576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155610fb93386868661211c565b1490506000805460ff191660011790559392505050565b6004546001600160a01b031681565b60035460ff1681565b6000610ff2613eca565b6040518060200160405280611005611a27565b90526001600160a01b0384166000908152600e602052604090205490915061102e9082906123b8565b9150505b919050565b6000610f586123d7565b60035460009061010090046001600160a01b0316331461106e5761106760016028611db2565b9050611032565b60055460408051623f1ee960e11b815290516001600160a01b0392831692851691627e3dd2916004808301926020929190829003018186803b1580156110b357600080fd5b505afa1580156110c7573d6000803e3d6000fd5b505050506040513d60208110156110dd57600080fd5b5051611130576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d9281900390910190a1600061102e565b600b5481565b60006111a434612409565b509050610e7f81604051806040016040528060128152602001711c995c185e509bdc9c9bddc819985a5b195960721b815250610b4a565b6005546001600160a01b031681565b6000805460ff1661122f576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556112416115b7565b905080156112675761125f81601081111561125857fe5b601d611db2565b915050610f36565b6112708361248b565b9150506000805460ff19166001179055919050565b60095481565b6001600160a01b03166000908152600e602052604090205490565b6000805460ff166112eb576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556112fd6115b7565b14611348576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b50600b546000805460ff1916600117905590565b6000610e3e82612587565b600c5481565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610dcf5780601f10610da457610100808354040283529160200191610dcf565b6000610e3e82612608565b60035461010090046001600160a01b0316331461141e5760405162461bcd60e51b815260040180806020018281038252602481526020018061401f6024913960400191505060405180910390fd5b60095415801561142e5750600a54155b6114695760405162461bcd60e51b81526004018080602001828103825260238152602001806140436023913960400191505060405180910390fd5b6007849055836114aa5760405162461bcd60e51b81526004018080602001828103825260308152602001806140666030913960400191505060405180910390fd5b60006114b587611041565b9050801561150a576040805162461bcd60e51b815260206004820152601a60248201527f73657474696e6720636f6d7074726f6c6c6572206661696c6564000000000000604482015290519081900360640190fd5b61151261265d565b600955670de0b6b3a7640000600a5561152a86612661565b905080156115695760405162461bcd60e51b81526004018080602001828103825260228152602001806140966022913960400191505060405180910390fd5b835161157c906001906020870190613edd565b508251611590906002906020860190613edd565b50506003805460ff90921660ff199283161790556000805490911660011790555050505050565b6000806115c261265d565b600954909150808214156115db57600092505050610f5b565b60006115e56123d7565b600b54600c54600a54600654604080516315f2405360e01b815260048101879052602481018690526044810185905290519596509394929391926000926001600160a01b03909216916315f24053916064808301926020929190829003018186803b15801561165357600080fd5b505afa158015611667573d6000803e3d6000fd5b505050506040513d602081101561167d57600080fd5b5051905065048c273950008111156116dc576040805162461bcd60e51b815260206004820152601c60248201527f626f72726f772072617465206973206162737572646c79206869676800000000604482015290519081900360640190fd5b60006116e888886127d6565b90506116f2613eca565b61170a60405180602001604052808581525083612810565b9050600061171882886123b8565b90506000611726828961283a565b905060006117456040518060200160405280600854815250848a612870565b9050600061175485898a612870565b60098e9055600a819055600b849055600c839055604080518d8152602081018790528082018390526060810186905290519192507f4dec04e750ca11537cabcd8a9eab06494de08da3735bc8871cd41250e190bc04919081900360800190a160009d505050505050505050505050505090565b6000805460ff1661180c576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556118223333868661211c565b1490506000805460ff1916600117905592915050565b600a5481565b600061184b833484612898565b50905061188681604051806040016040528060168152602001751b1a5c5d5a59185d19509bdc9c9bddc819985a5b195960521b815250610b4a565b505050565b6006546000906001600160a01b031663b81688166118a76123d7565b600b54600c546008546040518563ffffffff1660e01b81526004018085815260200184815260200183815260200182815260200194505050505060206040518083038186803b1580156118f957600080fd5b505afa15801561190d573d6000803e3d6000fd5b505050506040513d602081101561192357600080fd5b5051905090565b6000805460ff1661196f576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19169055611985338585856129ca565b90506000805460ff191660011790559392505050565b60035460009061010090046001600160a01b031633146119c1576110676001602e611db2565b600480546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a1600061102e565b6000805460ff16611a6c576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611a7e6115b7565b14611ac9576040805162461bcd60e51b81526020600482015260166024820152751858d8dc9d59481a5b9d195c995cdd0819985a5b195960521b604482015290519081900360640190fd5b611ad1610f4e565b90506000805460ff1916600117905590565b6001600160a01b0381166000908152600e602052604081205481908190819081611b0c87612608565b90506000611b186120b6565b90506000989297509095509350915050565b6000610e3e82612bd3565b6000610e3e82612c52565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205490565b6004546000906001600160a01b031633141580611b86575033155b15611b9e57611b9760016000611db2565b9050610f5b565b60038054600480546001600160a01b03818116610100818102610100600160a81b0319871617968790556001600160a01b031990931690935560408051948390048216808652929095041660208401528351909391927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600454604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160009250505090565b600080611c796115b7565b90508015611c9f57611c97816010811115611c9057fe5b6029611db2565b915050611032565b61102e83612661565b6006546001600160a01b031681565b60035461010090046001600160a01b031681565b6006546000906001600160a01b03166315f24053611ce76123d7565b600b54600c546040518463ffffffff1660e01b815260040180848152602001838152602001828152602001935050505060206040518083038186803b1580156118f957600080fd5b6000805460ff16611d74576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155611d866115b7565b90508015611da45761125f816010811115611d9d57fe5b602f611db2565b61127083612ccc565b600181565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836010811115611de157fe5b836037811115611ded57fe5b604080519283526020830191909152600082820152519081900360600190a1826010811115611e1857fe5b9392505050565b60055460408051634ef4c3e160e01b81523060048201526001600160a01b03858116602483015260448201859052915160009384938493911691634ef4c3e19160648082019260209290919082900301818787803b158015611e8057600080fd5b505af1158015611e94573d6000803e3d6000fd5b505050506040513d6020811015611eaa57600080fd5b505190508015611ece57611ec16003601583612d74565b9250600091506120af9050565b611ed661265d565b60095414611eea57611ec1600a6016611db2565b611ef2613f57565b611efa6120b6565b6040820152611f098686612dda565b60c0820181905260408051602081018252908301518152611f2a9190612e76565b60608201819052600d54611f3d9161283a565b60808201526001600160a01b0386166000908152600e60205260409020546060820151611f6a919061283a565b60a082018190526080820151600d556001600160a01b0387166000818152600e60209081526040918290209390935560c084015160608086015183519485529484019190915282820193909352517f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f929181900390910190a1606081015160408051918252516001600160a01b0388169130916000805160206140b88339815191529181900360200190a360055460c08201516060830151604080516341c728b960e01b81523060048201526001600160a01b038b81166024830152604482019490945260648101929092525191909216916341c728b991608480830192600092919082900301818387803b15801561208257600080fd5b505af1158015612096573d6000803e3d6000fd5b50600092506120a3915050565b8160c001519350935050505b9250929050565b600d54600090806120cb575050600754610f5b565b60006120d56123d7565b905060006120f06120e883600b5461283a565b600c546127d6565b9050600061210c82604051806020016040528087815250612e8a565b9450610f5b9350505050565b5090565b600554604080516317b9b84b60e31b81523060048201526001600160a01b03868116602483015285811660448301526064820185905291516000938493169163bdcdc25891608480830192602092919082900301818787803b15801561218157600080fd5b505af1158015612195573d6000803e3d6000fd5b505050506040513d60208110156121ab57600080fd5b5051905080156121ca576121c26003603383612d74565b9150506123b0565b836001600160a01b0316856001600160a01b031614156121f0576121c260026034611db2565b60006001600160a01b03878116908716141561220f5750600019612237565b506001600160a01b038086166000908152600f60209081526040808320938a16835292905220545b600061224382866127d6565b6001600160a01b0388166000908152600e60205260408120549192509061226a90876127d6565b6001600160a01b0388166000908152600e602052604081205491925090612291908861283a565b6001600160a01b03808b166000908152600e6020526040808220869055918b16815220819055905060001984146122eb576001600160a01b03808a166000908152600f60209081526040808320938e168352929052208390555b876001600160a01b0316896001600160a01b03166000805160206140b8833981519152896040518082815260200191505060405180910390a36005546040805163352b4a3f60e11b81523060048201526001600160a01b038c811660248301528b81166044830152606482018b905291519190921691636a56947e91608480830192600092919082900301818387803b15801561238757600080fd5b505af115801561239b573d6000803e3d6000fd5b50600092506123a8915050565b955050505050505b949350505050565b60006123c2613eca565b6123cc8484612810565b90506123b081612ea8565b60008060006123e64734612eb7565b909250905060008260038111156123f957fe5b1461240357600080fd5b91505090565b60008054819060ff16612450576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556124626115b7565b9050801561248057610b1981601081111561247957fe5b6022611db2565b610b30333386612eda565b600354600090819061010090046001600160a01b031633146124b357611c976001601e611db2565b6124bb61265d565b600954146124cf57611c97600a6020611db2565b826124d86123d7565b10156124ea57611c97600e601f611db2565b600c5483111561250057611c9760026021611db2565b61250c600c54846127d6565b600c81905560035490915061252f9061010090046001600160a01b031684613182565b600354604080516101009092046001600160a01b0316825260208201859052818101839052517f3bad0c59cf2f06e7314077049f48a93578cd16f5ef92329f1dab1420a99c177e916060908290030190a1600061102e565b6000805460ff166125cc576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556125de6115b7565b905080156125fc5761125f8160108111156125f557fe5b6019611db2565b611270336000856131b8565b6001600160a01b03811660009081526010602052604081208054612630576000915050611032565b60006126428260000154600a546134e7565b90506000612654828460010154613529565b95945050505050565b4390565b600354600090819061010090046001600160a01b0316331461268957611c976001602b611db2565b61269161265d565b600954146126a557611c97600a602a611db2565b600660009054906101000a90046001600160a01b03169050826001600160a01b0316632191f92a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126f657600080fd5b505afa15801561270a573d6000803e3d6000fd5b505050506040513d602081101561272057600080fd5b5051612773576040805162461bcd60e51b815260206004820152601c60248201527f6d61726b6572206d6574686f642072657475726e65642066616c736500000000604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03858116918217909255604080519284168352602083019190915280517fedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f9269281900390910190a1600061102e565b6000611e188383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061355c565b612818613eca565b60405180602001604052806128318560000151856134e7565b90529392505050565b6000611e188383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b8152506135b6565b600061287a613eca565b6128848585612810565b905061265461289282612ea8565b8461283a565b60008054819060ff166128df576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff191681556128f16115b7565b9050801561291c5761290f81601081111561290857fe5b6007611db2565b9250600091506129b39050565b836001600160a01b031663a6afed956040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561295757600080fd5b505af115801561296b573d6000803e3d6000fd5b505050506040513d602081101561298157600080fd5b5051905080156129a15761290f81601081111561299a57fe5b6008611db2565b6129ad33878787613614565b92509250505b6000805460ff191660011790559094909350915050565b6005546040805163d02f735160e01b81523060048201526001600160a01b038781166024830152868116604483015285811660648301526084820185905291516000938493169163d02f73519160a480830192602092919082900301818787803b158015612a3757600080fd5b505af1158015612a4b573d6000803e3d6000fd5b505050506040513d6020811015612a6157600080fd5b505190508015612a78576121c26003601183612d74565b846001600160a01b0316846001600160a01b03161415612a9e576121c260066012611db2565b6001600160a01b0384166000908152600e6020526040812054612ac190856127d6565b6001600160a01b0387166000908152600e602052604081205491925090612ae8908661283a565b6001600160a01b038088166000818152600e60209081526040808320889055938c168083529184902085905583518a81529351949550909391926000805160206140b8833981519152929081900390910190a360055460408051636d35bf9160e01b81523060048201526001600160a01b038b811660248301528a8116604483015289811660648301526084820189905291519190921691636d35bf919160a480830192600092919082900301818387803b158015612ba657600080fd5b505af1158015612bba573d6000803e3d6000fd5b5060009250612bc7915050565b98975050505050505050565b6000805460ff16612c18576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612c2a6115b7565b90508015612c485761125f816010811115612c4157fe5b6002611db2565b6112703384613b97565b6000805460ff16612c97576040805162461bcd60e51b815260206004820152600a6024820152691c994b595b9d195c995960b21b604482015290519081900360640190fd5b6000805460ff19168155612ca96115b7565b90508015612cc05761125f8160108111156125f557fe5b611270338460006131b8565b60035460009061010090046001600160a01b03163314612cf25761106760016030611db2565b612cfa61265d565b60095414612d0e57611067600a6031611db2565b670de0b6b3a7640000821115612d2a5761106760026032611db2565b6008805490839055604080518281526020810185905281517faaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460929181900390910190a1600061102e565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846010811115612da357fe5b846037811115612daf57fe5b604080519283526020830191909152818101859052519081900360600190a18360108111156123b057fe5b6000336001600160a01b03841614612e2b576040805162461bcd60e51b815260206004820152600f60248201526e0e6cadcc8cae440dad2e6dac2e8c6d608b1b604482015290519081900360640190fd5b813414612e70576040805162461bcd60e51b815260206004820152600e60248201526d0ecc2d8eaca40dad2e6dac2e8c6d60931b604482015290519081900360640190fd5b50919050565b6000612e80613eca565b6123cc8484613db5565b6000611e18612ea184670de0b6b3a76400006134e7565b8351613529565b51670de0b6b3a7640000900490565b600080838311612ece5750600090508183036120af565b506003905060006120af565b60055460408051631200453160e11b81523060048201526001600160a01b0386811660248301528581166044830152606482018590529151600093849384939116916324008a629160848082019260209290919082900301818787803b158015612f4357600080fd5b505af1158015612f57573d6000803e3d6000fd5b505050506040513d6020811015612f6d57600080fd5b505190508015612f9157612f846003602383612d74565b92506000915061317a9050565b612f9961265d565b60095414612fad57612f84600a6024611db2565b612fb5613f95565b6001600160a01b0386166000908152601060205260409020600101546060820152612fdf86612608565b6080820152600019851415612ffd5760808101516040820152613005565b604081018590525b613013878260400151612dda565b60e082018190526080820151613028916127d6565b60a0820152600b5460e082015161303f91906127d6565b60c0820190815260a080830180516001600160a01b03808b16600081815260106020908152604091829020948555600a546001909501949094559551600b81905560e088015194518751938f16845293830191909152818601939093526060810191909152608081019190915291517f1a2a22cb034d26d1854bdc6666a5b91fe25efbbb5dcad3b0355478d6f5c362a19281900390910190a160055460e0820151606083015160408051631ededc9160e01b81523060048201526001600160a01b038c811660248301528b8116604483015260648201949094526084810192909252519190921691631ededc919160a480830192600092919082900301818387803b15801561314d57600080fd5b505af1158015613161573d6000803e3d6000fd5b506000925061316e915050565b8160e001519350935050505b935093915050565b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611886573d6000803e3d6000fd5b60008215806131c5575081155b6132005760405162461bcd60e51b815260040180806020018281038252603481526020018061410b6034913960400191505060405180910390fd5b613208613f57565b6132106120b6565b6040820152831561324657606081018490526040805160208101825290820151815261323c90856123b8565b608082015261326f565b6132628360405180602001604052808460400151815250612e76565b6060820152608081018390525b60055460608201516040805163eabe7d9160e01b81523060048201526001600160a01b03898116602483015260448201939093529051600093929092169163eabe7d919160648082019260209290919082900301818787803b1580156132d457600080fd5b505af11580156132e8573d6000803e3d6000fd5b505050506040513d60208110156132fe57600080fd5b50519050801561331e576133156003601a83612d74565b92505050611e18565b61332661265d565b6009541461333a57613315600a601b611db2565b61334a600d5483606001516127d6565b60a08301526001600160a01b0386166000908152600e6020526040902054606083015161337791906127d6565b60c083015260808201516133896123d7565b101561339b57613315600e601c611db2565b6133a9868360800151613182565b60a0820151600d5560c08201516001600160a01b0387166000818152600e60209081526040918290209390935560608501518151908152905130936000805160206140b8833981519152928290030190a36080820151606080840151604080516001600160a01b038b168152602081019490945283810191909152517fe5b754fb1abb7f01b499791d0b820ae3b6af3424ac1c59768edb53f4ec31a9299281900390910190a160055460808301516060840151604080516351dff98960e01b81523060048201526001600160a01b038b81166024830152604482019490945260648101929092525191909216916351dff98991608480830192600092919082900301818387803b1580156134bc57600080fd5b505af11580156134d0573d6000803e3d6000fd5b50600092506134dd915050565b9695505050505050565b6000611e1883836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250613df2565b6000611e1883836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250613e68565b600081848411156135ae5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610d07578181015183820152602001610cef565b505050900390565b6000838301828582101561360b5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610d07578181015183820152602001610cef565b50949350505050565b60055460408051632fe3f38f60e11b81523060048201526001600160a01b0384811660248301528781166044830152868116606483015260848201869052915160009384938493911691635fc7e71e9160a48082019260209290919082900301818787803b15801561368557600080fd5b505af1158015613699573d6000803e3d6000fd5b505050506040513d60208110156136af57600080fd5b5051905080156136d3576136c66003600a83612d74565b925060009150613b8e9050565b6136db61265d565b600954146136ef576136c6600a600e611db2565b6136f761265d565b846001600160a01b0316636c540baf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561373057600080fd5b505afa158015613744573d6000803e3d6000fd5b505050506040513d602081101561375a57600080fd5b50511461376d576136c6600a6009611db2565b866001600160a01b0316866001600160a01b03161415613793576136c66006600f611db2565b846137a4576136c66007600d611db2565b6000198514156137ba576136c66007600c611db2565b6000806137c8898989612eda565b909250905081156137f8576137e98260108111156137e257fe5b6010611db2565b945060009350613b8e92505050565b6005546040805163c488847b60e01b81523060048201526001600160a01b038981166024830152604482018590528251600094859492169263c488847b926064808301939192829003018186803b15801561385257600080fd5b505afa158015613866573d6000803e3d6000fd5b505050506040513d604081101561387c57600080fd5b508051602090910151909250905081156138c75760405162461bcd60e51b81526004018080602001828103825260338152602001806140d86033913960400191505060405180910390fd5b80886001600160a01b03166370a082318c6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561391e57600080fd5b505afa158015613932573d6000803e3d6000fd5b505050506040513d602081101561394857600080fd5b5051101561399d576040805162461bcd60e51b815260206004820152601860248201527f4c49515549444154455f5345495a455f544f4f5f4d5543480000000000000000604482015290519081900360640190fd5b60006001600160a01b0389163014156139c3576139bc308d8d856129ca565b9050613a4d565b6040805163b2a02ff160e01b81526001600160a01b038e811660048301528d81166024830152604482018590529151918b169163b2a02ff1916064808201926020929091908290030181600087803b158015613a1e57600080fd5b505af1158015613a32573d6000803e3d6000fd5b505050506040513d6020811015613a4857600080fd5b505190505b8015613a97576040805162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b604482015290519081900360640190fd5b604080516001600160a01b03808f168252808e1660208301528183018790528b1660608201526080810184905290517f298637f684da70674f26509b10f07ec2fbc77a335ab1e7d6215a4b2484d8bb529181900360a00190a1600554604080516347ef3b3b60e01b81523060048201526001600160a01b038c811660248301528f811660448301528e811660648301526084820188905260a48201869052915191909216916347ef3b3b9160c480830192600092919082900301818387803b158015613b6257600080fd5b505af1158015613b76573d6000803e3d6000fd5b5060009250613b83915050565b975092955050505050505b94509492505050565b6005546040805163368f515360e21b81523060048201526001600160a01b0385811660248301526044820185905291516000938493169163da3d454c91606480830192602092919082900301818787803b158015613bf457600080fd5b505af1158015613c08573d6000803e3d6000fd5b505050506040513d6020811015613c1e57600080fd5b505190508015613c3d57613c356003600683612d74565b915050610e3e565b613c4561265d565b60095414613c5957613c35600a6004611db2565b82613c626123d7565b1015613c7457613c35600e6003611db2565b613c7c613fdb565b613c8585612608565b60208201819052613c96908561283a565b6040820152600b54613ca8908561283a565b6060820152613cb78585613182565b604080820180516001600160a01b03881660008181526010602090815290859020928355600a54600190930192909255606080860151600b81905593518551928352928201899052818501929092529081019190915290517f13ed6866d4e1ee6da46f845c46d7e54120883d75c5ea9a2dacc1c4ca8984ab809181900360800190a160055460408051635c77860560e01b81523060048201526001600160a01b0388811660248301526044820188905291519190921691635c77860591606480830192600092919082900301818387803b158015613d9457600080fd5b505af1158015613da8573d6000803e3d6000fd5b5060009250612654915050565b613dbd613eca565b6000613dd1670de0b6b3a7640000856134e7565b90506040518060200160405280613de88386612e8a565b9052949350505050565b6000831580613dff575082155b15613e0c57506000611e18565b83830283858281613e1957fe5b0414839061360b5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610d07578181015183820152602001610cef565b60008183613eb75760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610d07578181015183820152602001610cef565b50828481613ec157fe5b04949350505050565b6040518060200160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613f1e57805160ff1916838001178555613f4b565b82800160010185558215613f4b579182015b82811115613f4b578251825591602001919060010190613f30565b50612118929150614004565b6040805160e0810190915280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604080516080810190915280600081526020016000815260200160008152602001600081525090565b610f5b91905b80821115612118576000815560010161400a56fe6f6e6c792061646d696e206d617920696e697469616c697a6520746865206d61726b65746d61726b6574206d6179206f6e6c7920626520696e697469616c697a6564206f6e6365696e697469616c2065786368616e67652072617465206d7573742062652067726561746572207468616e207a65726f2e73657474696e6720696e7465726573742072617465206d6f64656c206661696c6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c4154455f414d4f554e545f5345495a455f4641494c45446f6e65206f662072656465656d546f6b656e73496e206f722072656465656d416d6f756e74496e206d757374206265207a65726fa265627a7a72315820f6ea870115936cf827e59721ee714513701b3e9e6fefb74cd7510eecc8d0cbbe64736f6c63430005100032",
  "devdoc": {
    "author": "Compound",
    "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)"
      },
      "_reduceReserves(uint256)": {
        "params": {
          "reduceAmount": "Amount of reduction to reserves"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "_setComptroller(address)": {
        "details": "Admin function to set a new comptroller",
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "_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)"
      },
      "_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 block  up to the current block 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"
      },
      "borrowRatePerBlock()": {
        "return": "The borrow interest rate per block, scaled by 1e18"
      },
      "constructor": {
        "params": {
          "admin_": "Address of the administrator of this token",
          "comptroller_": "The address of the Comptroller",
          "decimals_": "ERC-20 decimal precision of this token",
          "initialExchangeRateMantissa_": "The initial exchange rate, scaled by 1e18",
          "interestRateModel_": "The address of the interest rate model",
          "name_": "ERC-20 name of this token",
          "symbol_": "ERC-20 symbol of this token"
        }
      },
      "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"
      },
      "getAccountSnapshot(address)": {
        "details": "This is used by comptroller 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,uint256,string,string,uint8)": {
        "params": {
          "comptroller_": "The address of the Comptroller",
          "decimals_": "EIP-20 decimal precision of this token",
          "initialExchangeRateMantissa_": "The initial exchange rate, scaled by 1e18",
          "interestRateModel_": "The address of the interest rate model",
          "name_": "EIP-20 name of this token",
          "symbol_": "EIP-20 symbol of this token"
        }
      },
      "liquidateBorrow(address,address)": {
        "details": "Reverts upon any failure",
        "params": {
          "borrower": "The borrower of this cToken to be liquidated",
          "cTokenCollateral": "The market in which to seize collateral from the borrower"
        }
      },
      "mint()": {
        "details": "Reverts upon any failure"
      },
      "redeem(uint256)": {
        "details": "Accrues interest whether or not the operation succeeds, unless reverted",
        "params": {
          "redeemTokens": "The number of cTokens 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)"
      },
      "repayBorrow()": {
        "details": "Reverts upon any failure"
      },
      "seize(address,address,uint256)": {
        "details": "Will fail unless called by another cToken during the process of liquidation. Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.",
        "params": {
          "borrower": "The account having collateral seized",
          "liquidator": "The account receiving seized collateral",
          "seizeTokens": "The number of cTokens to seize"
        },
        "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)"
      },
      "supplyRatePerBlock()": {
        "return": "The supply interest rate per block, 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"
      }
    },
    "title": "Compound's CEther Contract"
  },
  "userdoc": {
    "methods": {
      "_acceptAdmin()": {
        "notice": "Accepts transfer of admin rights. msg.sender must be pendingAdmin"
      },
      "_reduceReserves(uint256)": {
        "notice": "Accrues interest and reduces reserves by transferring to admin"
      },
      "_setComptroller(address)": {
        "notice": "Sets a new comptroller for the market"
      },
      "_setInterestRateModel(address)": {
        "notice": "accrues interest and updates the interest rate model using _setInterestRateModelFresh"
      },
      "_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"
      },
      "borrowRatePerBlock()": {
        "notice": "Returns the current per-block borrow interest rate for this cToken"
      },
      "constructor": "Construct a new CEther money market",
      "exchangeRateCurrent()": {
        "notice": "Accrue interest then return the up-to-date exchange rate"
      },
      "exchangeRateStored()": {
        "notice": "Calculates the exchange rate from the underlying to the CToken"
      },
      "getAccountSnapshot(address)": {
        "notice": "Get a snapshot of the account's balances, and the cached exchange rate"
      },
      "getCash()": {
        "notice": "Get cash balance of this cToken in the underlying asset"
      },
      "initialize(address,address,uint256,string,string,uint8)": {
        "notice": "Initialize the money market"
      },
      "liquidateBorrow(address,address)": {
        "notice": "The sender liquidates the borrowers collateral. The collateral seized is transferred to the liquidator."
      },
      "mint()": {
        "notice": "Sender supplies assets into the market and receives cTokens in exchange"
      },
      "redeem(uint256)": {
        "notice": "Sender redeems cTokens in exchange for the underlying asset"
      },
      "redeemUnderlying(uint256)": {
        "notice": "Sender redeems cTokens in exchange for a specified amount of underlying asset"
      },
      "repayBorrow()": {
        "notice": "Sender repays their own borrow"
      },
      "seize(address,address,uint256)": {
        "notice": "Transfers collateral tokens (this market) to the liquidator."
      },
      "supplyRatePerBlock()": {
        "notice": "Returns the current per-block supply interest rate for this cToken"
      },
      "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`"
      }
    },
    "notice": "CToken which wraps Ether"
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 12158,
        "contract": "contracts/CEther.sol:CEther",
        "label": "_notEntered",
        "offset": 0,
        "slot": "0",
        "type": "t_bool"
      },
      {
        "astId": 12160,
        "contract": "contracts/CEther.sol:CEther",
        "label": "name",
        "offset": 0,
        "slot": "1",
        "type": "t_string_storage"
      },
      {
        "astId": 12162,
        "contract": "contracts/CEther.sol:CEther",
        "label": "symbol",
        "offset": 0,
        "slot": "2",
        "type": "t_string_storage"
      },
      {
        "astId": 12164,
        "contract": "contracts/CEther.sol:CEther",
        "label": "decimals",
        "offset": 0,
        "slot": "3",
        "type": "t_uint8"
      },
      {
        "astId": 12172,
        "contract": "contracts/CEther.sol:CEther",
        "label": "admin",
        "offset": 1,
        "slot": "3",
        "type": "t_address_payable"
      },
      {
        "astId": 12174,
        "contract": "contracts/CEther.sol:CEther",
        "label": "pendingAdmin",
        "offset": 0,
        "slot": "4",
        "type": "t_address_payable"
      },
      {
        "astId": 12176,
        "contract": "contracts/CEther.sol:CEther",
        "label": "comptroller",
        "offset": 0,
        "slot": "5",
        "type": "t_contract(ComptrollerInterface)21910"
      },
      {
        "astId": 12178,
        "contract": "contracts/CEther.sol:CEther",
        "label": "interestRateModel",
        "offset": 0,
        "slot": "6",
        "type": "t_contract(InterestRateModel)25284"
      },
      {
        "astId": 12180,
        "contract": "contracts/CEther.sol:CEther",
        "label": "initialExchangeRateMantissa",
        "offset": 0,
        "slot": "7",
        "type": "t_uint256"
      },
      {
        "astId": 12182,
        "contract": "contracts/CEther.sol:CEther",
        "label": "reserveFactorMantissa",
        "offset": 0,
        "slot": "8",
        "type": "t_uint256"
      },
      {
        "astId": 12184,
        "contract": "contracts/CEther.sol:CEther",
        "label": "accrualBlockNumber",
        "offset": 0,
        "slot": "9",
        "type": "t_uint256"
      },
      {
        "astId": 12186,
        "contract": "contracts/CEther.sol:CEther",
        "label": "borrowIndex",
        "offset": 0,
        "slot": "10",
        "type": "t_uint256"
      },
      {
        "astId": 12188,
        "contract": "contracts/CEther.sol:CEther",
        "label": "totalBorrows",
        "offset": 0,
        "slot": "11",
        "type": "t_uint256"
      },
      {
        "astId": 12190,
        "contract": "contracts/CEther.sol:CEther",
        "label": "totalReserves",
        "offset": 0,
        "slot": "12",
        "type": "t_uint256"
      },
      {
        "astId": 12192,
        "contract": "contracts/CEther.sol:CEther",
        "label": "totalSupply",
        "offset": 0,
        "slot": "13",
        "type": "t_uint256"
      },
      {
        "astId": 12196,
        "contract": "contracts/CEther.sol:CEther",
        "label": "accountTokens",
        "offset": 0,
        "slot": "14",
        "type": "t_mapping(t_address,t_uint256)"
      },
      {
        "astId": 12202,
        "contract": "contracts/CEther.sol:CEther",
        "label": "transferAllowances",
        "offset": 0,
        "slot": "15",
        "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))"
      },
      {
        "astId": 12211,
        "contract": "contracts/CEther.sol:CEther",
        "label": "accountBorrows",
        "offset": 0,
        "slot": "16",
        "type": "t_mapping(t_address,t_struct(BorrowSnapshot)12207_storage)"
      }
    ],
    "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(ComptrollerInterface)21910": {
        "encoding": "inplace",
        "label": "contract ComptrollerInterface",
        "numberOfBytes": "20"
      },
      "t_contract(InterestRateModel)25284": {
        "encoding": "inplace",
        "label": "contract InterestRateModel",
        "numberOfBytes": "20"
      },
      "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)12207_storage)": {
        "encoding": "mapping",
        "key": "t_address",
        "label": "mapping(address => struct CTokenStorage.BorrowSnapshot)",
        "numberOfBytes": "32",
        "value": "t_struct(BorrowSnapshot)12207_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)12207_storage": {
        "encoding": "inplace",
        "label": "struct CTokenStorage.BorrowSnapshot",
        "members": [
          {
            "astId": 12204,
            "contract": "contracts/CEther.sol:CEther",
            "label": "principal",
            "offset": 0,
            "slot": "0",
            "type": "t_uint256"
          },
          {
            "astId": 12206,
            "contract": "contracts/CEther.sol:CEther",
            "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"
      }
    }
  }
}